Python 视频水印批量添加器

功能如下可以

一、选择水印位置

二、批量添加水印

三、可添加文本或图片

复制代码
# -*- 编码:utf-8 -*-
import cv2
import os
import numpy as np
from moviepy.editor import VideoFileClip
from concurrent.futures import ThreadPoolExecutor
import tkinter as tk
from tkinter import filedialog, messagebox
from PIL import ImageFont, ImageDraw, Image
 
 
def add_dynamic_watermarks_with_audio(video_path, output_path, watermark_image_paths, watermark_sizes, watermark_speeds,
add_text_watermark, text_watermark_text, text_watermark_color,
text_watermark_position):
try:
video_clip = VideoFileClip(video_path)
audio_clip = video_clip.audio
width, height = video_clip.size
 
if add_text_watermark:
font_path = "msyh.ttc" # Windows字体路径,可以根据需要更改
font_size = 50
font = ImageFont.truetype(font_path, font_size)
text_watermark_canvas = np.zeros((高度,宽度,3),dtype=np.uint8)
text_pil = 图像.fromarray(text_watermark_canvas)
绘制 = ImageDraw.Draw(text_pil)
text_bbox = draw.textbbox((0, 0), text_watermark_text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
 
如果 text_watermark_position == "中心":
text_x = (宽度 - text_width) / 2
text_y = (高度 - text_height) / 2
elif text_watermark_position == "左上":
text_x = 10
text_y = 10
elif text_watermark_position == "右上":
text_x = 宽度 - text_width - 10
text_y = 10
elif text_watermark_position == "左下":
text_x = 10
text_y = 高度 - text_height - 10
elif text_watermark_position == "右下":
text_x = 宽度 - text_width - 10
text_y = 高度 - text_height - 10
 
draw.text((text_x, text_y), text_watermark_text, font=font, fill=text_watermark_color)
text_watermark_canvas = np.array(text_pil)
 
watermark_positions = [(0, 0)] * len(watermark_image_paths)
 
def process_frame(t, x):
非本地 watermark_positions
frame = video_clip.get_frame(t)
 
for i in range(len(watermark_image_paths)):
watermark_image_path = watermark_image_paths[i]
watermark_size = watermark_sizes[i]
watermark_speed = watermark_speeds[i]
watermark_image = cv2.imread(watermark_image_path)
 
watermark_height, watermark_width, _ = watermark_image.shape
如果宽度或watermark_height >高度watermark_width >:
scale_factor = min(宽度 / watermark_width, 高度 / watermark_height)
watermark_image = cv2.resize(watermark_image, (
int(watermark_width * scale_factor), int(watermark_height * scale_factor)),
interpolation=cv2.INTER_LINEAR)
 
if t % watermark_speed == 0:
while True:
x = np.random.randint(0, width - watermark_image.shape[1])
y = np.random.randint(0, height - watermark_image.shape[0])
too_close = 范围 (i) 中 j 的 False
 
:
dist = np.sqrt((x - watermark_positions[j][0]) ** 2 + (y - watermark_positions[j][1]) ** 2)
if dist < watermark_image.shape[1] 或 dist < watermark_image.shape[0]:
too_close = True
break
 
if not too_close:
watermark_positions[i] = (x, y)
break
else:
x, y = watermark_positions[i]
 
watermark_resized = cv2.resize(watermark_image, (
int(watermark_size * watermark_width), int(watermark_size * watermark_height)))
alpha = watermark_resized[:, :, 0] / 255.0
for c in range(3):
frame[y: y + watermark_resized.shape[0], x: x + watermark_resized.shape[1], c] = (
frame[y: y + watermark_resized.shape[0], x: x + watermark_resized.shape[1], c] * (1 - alpha)
+ watermark_resized[:, :, c] * alpha
)
 
if add_text_watermark:
frame_with_text = cv2.addWeighted(frame, 1, text_watermark_canvas, 0.7, 0)
frame = frame_with_text
 
返回帧
 
processed_clip = video_clip.fl(lambda gf, t: process_frame(t, gf))
final_clip = processed_clip.set_audio(audio_clip)
final_clip.write_videofile(output_path, codec='libx264', audio_codec="aac")
 
return "水印添加完成!"
except Exception as e:
print(f"处理视频时出错 {video_path}: {e}")
return f"处理视频 {video_path} 时出错:{e}"
 
 
def batch_add_watermarks_in_directory_with_audio(directory, output_directory, watermark_image_paths, watermark_sizes,
watermark_speeds, add_text_watermark=False, text_watermark_text=None,
text_watermark_position='右下'):
file_list = os.listdir(directory)
video_files = [文件在file_list if file.lower().endswith(('.avi', '.mp4', '.mov', '.mkv'))]
 
将 ThreadPoolExecutor() 作为执行器:
futures = []
for file_name in video_files:
file_path = os.path.join(directory, file_name)
output_file_path = os.path.join(output_directory, file_name)
futures.append(executor.submit(
add_dynamic_watermarks_with_audio,
file_path, output_file_path, watermark_image_paths, watermark_sizes, watermark_speeds,
add_text_watermark, text_watermark_text, (255, 255, 255), text_watermark_position
))
 
for future in futures:
result = future.result()
print(result)
 
return "批量处理完成!"
 
 
def select_directory(entry):
directory =filedialog.askdirectory()
entry.delete(0, tk.END)
entry.insert(0, directory)
 
 
def select_files(entry, file_list, size_list, speed_list):
files = filedialog.askopenfilenames(filetypes=[("Image files", "*.png;*.jpg;*.jpeg")])
for file in files:
file_list.append(file)
entry.insert(tk.END, file)
size_list.append(float(input(f"请输入水印图片{file}的大小(0~1之间):")))
speed_list.append(int(input(f"请输入水印图片{file}的速度:"))))def
 
 
start_processing():
directory = input_dir_entry.get()
output_directory = output_dir_entry.get()
os.makedirs(output_directory, exist_ok=True)
 
add_text_watermark = text_watermark_var.get()
text_watermark_text = text_watermark_entry.get() 如果add_text_watermark其他 None text_watermark_position
= text_watermark_position_var.get()
 
batch_add_watermarks_in_directory_with_audio(
directory, output_directory, watermark_image_paths, watermark_sizes, watermark_speeds, add_text_watermark,
text_watermark_text, text_watermark_position
)
 
messagebox.showinfo("完成", "批量处理完成!")
 
 
root = tk.Tk()
root.title("视频水印批量添加器")
 
tk.Label(root, text="输入目录:").grid(row=0, column=0)
input_dir_entry = tk.Entry(root, width=50)
input_dir_entry.grid(row=0, column=1)
tk.Button(root, text="选择", command=lambda: select_directory(input_dir_entry)).grid(row=0, column=2)
 
tk.Label(root, text="输出目录:").grid(row=1, column=0)
output_dir_entry = tk.Entry(root, width=50)
output_dir_entry.grid(row=1, column=1)
tk.Button(root, text="选择", command=lambda: select_directory(output_dir_entry)).grid(row=1, column=2)
 
tk.Label(root, text="水印图片:").grid(row=2, column=0)
watermark_image_listbox = tk.Listbox(root, width=50)
watermark_image_listbox.grid(row=2, column=1)
watermark_image_paths = []
watermark_sizes = []
watermark_speeds = []
tk。Button(root, text="添加",
command=lambda: select_files(watermark_image_listbox, watermark_image_paths, watermark_sizes,
watermark_speeds)).grid(row=2, column=2)
 
text_watermark_var = tk.BooleanVar()
tk 中。Checkbutton(root, text="添加文本水印", variable=text_watermark_var).grid(row=3, column=0)
text_watermark_entry = tk.Entry(root, width=50)
text_watermark_entry.grid(row=3, column=1)
 
tk.Label(root, text="文本水印位置:").grid(row=4, column=0)
text_watermark_position_var = tk.StringVar(value="右下")
text_watermark_position_options = ["左上", "右上", "左下", "右下", "中心"]
text_watermark_position_menu = tk.OptionMenu(root, text_watermark_position_var, *text_watermark_position_options)
text_watermark_position_menu.grid(row=4, column=1)
 
tk。Button(root, text="开始处理", command=start_processing).grid(row=5, column=0, columnspan=3)
 
root.mainloop()
相关推荐
中文Python几秒前
小白中文Python-双色球LSTM模型出号程序
开发语言·人工智能·python·lstm·中文python·小白学python
越努力越幸运5083 分钟前
JavaScript进阶篇垃圾回收、闭包、函数提升、剩余参数、展开运算符、对象解构
开发语言·javascript
czhc11400756633 分钟前
C# 1116 流程控制 常量
开发语言·c#
superbadguy13 分钟前
用curl实现Ollama API流式调用
人工智能·python
嚴 帅14 分钟前
Pytnon入门学习(一)
python
小兵张健18 分钟前
Java + Spring 到 Python + FastAPI (二)
java·python·spring
vvoennvv43 分钟前
【Python TensorFlow】BiTCN-BiLSTM双向时间序列卷积双向长短期记忆神经网络时序预测算法(附代码)
python·rnn·tensorflow·lstm·tcn
程序定小飞1 小时前
基于springboot的汽车资讯网站开发与实现
java·开发语言·spring boot·后端·spring
大米粥哥哥1 小时前
Qt 使用QAMQP连接RabbitMQ
开发语言·qt·rabbitmq·qamqp
yivifu1 小时前
精益求精,支持处理嵌套表格的Word表格转HTML表格
开发语言·c#·word