这个是一个基于PyQt5开发的视频水印批量添加工具,旨在为多个视频文件添加文本水印。用户可以自定义水印的文本内容、字体颜色、字号大小以及位置(如左上角、右上角、左下角、右下角和中心位置)。程序支持常见的视频格式,如MP4、AVI、MOV和MKV,并能够批量处理视频文件,输出带有水印的新视频。
选择输入和输出目录: 用户可以通过文件对话框选择视频文件的输入目录和保存带水印视频的输出目录。
自定义水印文本: 用户可以在输入框中填写水印的文本内容,水印会被添加到视频上。
自定义水印位置: 水印可以选择显示在视频的不同位置,包括左上角、右上角、左下角、右下角和中心。
自定义水印字体颜色: 用户可以通过颜色选择器来选择水印文本的颜色,支持丰富的颜色选择。
选择水印字体大小: 提供了多个字体大小选项(20到100),用户可以根据需要选择合适的字号。
批量处理视频: 程序会遍历输入目录中的所有视频文件,逐一为其添加水印并保存到输出目录。支持的视频格式包括MP4、AVI、MOV、MKV等。
进度条与日志显示: 程序提供实时进度条,显示当前视频处理的进度。同时,日志框显示详细的处理信息和错误提示,帮助用户实时了解处理状态。
处理完成提示: 所有视频处理完成后,会弹出提示框,告知用户所有视频水印已成功添加。
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
import os import time import cv2 import numpy as np from PyQt5.QtCore import Qt, QThread, pyqtSignal, QThreadPool, QRunnable, QObject from PyQt5.QtGui import QColor from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QFileDialog, QTextBrowser, QProgressBar, QComboBox, QLabel, QLineEdit, QColorDialog, QMessageBox, QHBoxLayout from PyQt5.QtGui import QFont from PIL import Image, ImageDraw, ImageFont
class WatermarkWorker(QObject): update_log_signal = pyqtSignal(str) update_progress_signal = pyqtSignal(int) processing_complete_signal = pyqtSignal()
def __init__(self, input_dir, output_dir, watermark_text, watermark_position, watermark_color, font_size, video_file): super().__init__() self.input_dir = input_dir self.output_dir = output_dir self.watermark_text = watermark_text self.watermark_position = watermark_position self.watermark_color = watermark_color self.font_size = font_size self.video_file = video_file
def add_watermark(self): input_video_path = os.path.join(self.input_dir, self.video_file) output_video_path = os.path.join(self.output_dir, "watermarked_" + self.video_file)
self.update_log_signal.emit(f"[{self.get_current_time()}] 开始处理视频: {self.video_file}")
cap = cv2.VideoCapture(input_video_path) frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fourcc = cv2.VideoWriter_fourcc(*'mp4v') out = cv2.VideoWriter(output_video_path, fourcc, 30.0, (frame_width, frame_height))
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) processed_frames = 0
while cap.isOpened(): ret, frame = cap.read() if not ret: break
frame = self.add_text_watermark(frame, self.watermark_text, self.watermark_position, frame_width, frame_height) out.write(frame)
processed_frames += 1 progress = int((processed_frames / total_frames) * 100) self.update_progress_signal.emit(progress)
cap.release() out.release()
self.update_log_signal.emit(f"[{self.get_current_time()}] 水印已添加并保存到: {output_video_path}") self.update_progress_signal.emit(100) self.processing_complete_signal.emit()
def add_text_watermark(self, frame, text, position, width, height): pil_image = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) draw = ImageDraw.Draw(pil_image) try: font = ImageFont.truetype("simhei.ttf", self.font_size) except IOError: font = ImageFont.load_default()
bbox = draw.textbbox((0, 0), text, font=font) text_width = bbox[2] - bbox[0] text_height = bbox[3] - bbox[1]
x, y = 10, 30 if position == "左上角": x, y = 10, 30 elif position == "右上角": x, y = width - text_width - 10, 30 elif position == "左下角": x, y = 10, height - text_height - 10 elif position == "右下角": x, y = width - text_width - 10, height - text_height - 10 elif position == "中心位置": x, y = (width - text_width) // 2, (height - text_height) // 2
color = (self.watermark_color.red(), self.watermark_color.green(), self.watermark_color.blue()) draw.text((x, y), text, font=font, fill=color)
return cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
def get_current_time(self): return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
class WatermarkApp(QWidget): def __init__(self): super().__init__()
self.setWindowTitle("视频水印批量添加软件") self.setGeometry(300, 300, 650, 400)
self.input_dir = "" self.output_dir = "" self.watermark_text = "" self.watermark_position = "center" self.watermark_color = QColor(255, 255, 255) self.font_size = 30
self.thread_pool = QThreadPool()
self.initUI()
def initUI(self): main_layout = QHBoxLayout() left_layout = QVBoxLayout()
self.setStyleSheet("background-color: #F5F5F5;")
self.input_button = QPushButton("选择视频输入目录") self.input_button.setStyleSheet("background-color: #4CAF50; color: white; font-size: 14px; padding: 5px;") self.input_button.clicked.connect(self.select_input_directory) left_layout.addWidget(self.input_button)
self.output_button = QPushButton("选择视频输出目录") self.output_button.setStyleSheet("background-color: #4CAF50; color: white; font-size: 14px; padding: 5px;") self.output_button.clicked.connect(self.select_output_directory) left_layout.addWidget(self.output_button)
watermark_layout = QHBoxLayout()
self.watermark_label = QLabel("水印文本:") self.watermark_label.setStyleSheet("font-size: 14px; color: #333333;") watermark_layout.addWidget(self.watermark_label)
self.watermark_input = QLineEdit(self) self.watermark_input.setFont(QFont("Arial", 10)) self.watermark_input.setStyleSheet("padding: 5px; border-radius: 5px; border: 1px solid #ccc;") self.watermark_input.textChanged.connect(self.update_watermark_text) watermark_layout.addWidget(self.watermark_input)
left_layout.addLayout(watermark_layout)
self.color_button = QPushButton("选择字体颜色") self.color_button.setStyleSheet("background-color: #4CAF50; color: white; font-size: 14px; padding: 5px;") self.color_button.clicked.connect(self.select_color) left_layout.addWidget(self.color_button)
font_size_layout = QHBoxLayout()
self.font_size_label = QLabel("选择字号大小:") self.font_size_label.setStyleSheet("font-size: 14px; color: #333333;") font_size_layout.addWidget(self.font_size_label)
self.font_size_combo = QComboBox(self) self.font_size_combo.addItem("20") self.font_size_combo.addItem("30") self.font_size_combo.addItem("40") self.font_size_combo.addItem("50") self.font_size_combo.addItem("60") self.font_size_combo.addItem("70") self.font_size_combo.addItem("80") self.font_size_combo.addItem("90") self.font_size_combo.addItem("100") self.font_size_combo.setStyleSheet("padding: 5px; border-radius: 5px; border: 1px solid #ccc;") self.font_size_combo.currentTextChanged.connect(self.update_font_size) font_size_layout.addWidget(self.font_size_combo)
left_layout.addLayout(font_size_layout)
position_layout = QHBoxLayout() self.position_label = QLabel("选择水印位置:") self.position_label.setStyleSheet("font-size: 14px; color: #333333;") self.position_combo = QComboBox(self) self.position_combo.addItem("左上角") self.position_combo.addItem("右上角") self.position_combo.addItem("左下角") self.position_combo.addItem("右下角") self.position_combo.addItem("中心位置") self.position_combo.setStyleSheet("padding: 5px; border-radius: 5px; border: 1px solid #ccc;") self.position_combo.currentTextChanged.connect(self.update_watermark_position)
position_layout.addWidget(self.position_label) position_layout.addWidget(self.position_combo) left_layout.addLayout(position_layout)
self.process_button = QPushButton("添加水印并保存视频") self.process_button.setStyleSheet("background-color: #FF5722; color: white; font-size: 14px; padding: 10px;") self.process_button.clicked.connect(self.add_watermark) left_layout.addWidget(self.process_button)
self.progress_bar = QProgressBar(self) self.progress_bar.setRange(0, 100) self.progress_bar.setValue(0) self.progress_bar.setTextVisible(True) self.progress_bar.setStyleSheet("height: 20px; background-color: #ddd;") left_layout.addWidget(self.progress_bar)
self.log_browser = QTextBrowser(self) self.log_browser.setStyleSheet("background-color: #F5F5F5; border: 1px solid #ccc; padding: 5px;") self.log_browser.setFont(QFont("Arial", 10)) main_layout.addLayout(left_layout) main_layout.addWidget(self.log_browser)
self.setLayout(main_layout)
def select_input_directory(self): self.input_dir = QFileDialog.getExistingDirectory(self, "选择输入目录") self.log_browser.append(f"[<font color='red'>{self.get_current_time()}</font>] 选择的输入目录: {self.input_dir}")
def select_output_directory(self): self.output_dir = QFileDialog.getExistingDirectory(self, "选择输出目录") self.log_browser.append(f"[<font color='red'>{self.get_current_time()}</font>] 选择的输出目录: {self.output_dir}")
def update_watermark_text(self): self.watermark_text = self.watermark_input.text()
def update_watermark_position(self): self.watermark_position = self.position_combo.currentText()
def update_font_size(self): self.font_size = int(self.font_size_combo.currentText())
def select_color(self): color = QColorDialog.getColor(self.watermark_color, self, "选择字体颜色") if color.isValid(): self.watermark_color = color self.log_browser.append(f"[<font color='red'>{self.get_current_time()}</font>] 已选择水印字体颜色: {self.watermark_color.name()}")
def add_watermark(self): if not self.input_dir or not self.output_dir or not self.watermark_text: self.log_browser.append(f"[<font color='red'>{self.get_current_time()}</font>] 错误: 请检查输入目录、输出目录和水印文本") return
video_files = [f for f in os.listdir(self.input_dir) if f.endswith(('.mp4', '.avi', '.mov', '.mkv'))] for video_file in video_files: # 创建WatermarkWorker实例 worker = WatermarkWorker(self.input_dir, self.output_dir, self.watermark_text, self.watermark_position, self.watermark_color, self.font_size, video_file) # 连接信号 worker.update_log_signal.connect(self.log_browser.append) worker.update_progress_signal.connect(self.progress_bar.setValue) worker.processing_complete_signal.connect(self.show_completion_message)
# 启动处理 worker.add_watermark()
def show_completion_message(self): QMessageBox.information(self, "处理完成", "所有视频水印添加完毕!", QMessageBox.Ok)
def get_current_time(self): return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
if __name__ == '__main__': app = QApplication([]) window = WatermarkApp() window.show() app.exec_() |
这款视频水印批量添加软件通过PyQt5实现了一个简洁且功能强大的图形用户界面,支持对多个视频文件进行水印添加。用户可以轻松自定义水印的各项参数,程序在处理过程中提供实时进度条和日志显示,确保用户能够清晰了解每个视频的处理状态。该工具特别适合需要批量处理视频并添加水印的用户,提供了便捷且高效的视频编辑功能