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_()
|