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()
相关推荐
wt_cs17 分钟前
银行回单ocr api集成解析-图像文字识别-文字识别技术
开发语言·python
_WndProc39 分钟前
【Python】Flask网页
开发语言·python·flask
互联网搬砖老肖41 分钟前
Python 中如何使用 Conda 管理版本和创建 Django 项目
python·django·conda
测试者家园1 小时前
基于DeepSeek和crewAI构建测试用例脚本生成器
人工智能·python·测试用例·智能体·智能化测试·crewai
liujing102329291 小时前
Day04_刷题niuke20250703
java·开发语言·算法
大模型真好玩1 小时前
准确率飙升!Graph RAG如何利用知识图谱提升RAG答案质量(四)——微软GraphRAG代码实战
人工智能·python·mcp
前端付豪1 小时前
11、打造自己的 CLI 工具:从命令行到桌面效率神器
后端·python
前端付豪1 小时前
12、用类写出更可控、更易扩展的爬虫框架🕷
后端·python
feiyangqingyun1 小时前
Qt音视频开发技巧/推流带旋转角度/rtsprtmp推流/保存文件到MP4/拉流解析旋转角度
qt·音视频·qt旋转角度推流
能工智人小辰1 小时前
二刷 苍穹外卖day10(含bug修改)
java·开发语言