Python實現(xiàn)批量添加視頻文本水印
1. 簡介
這個是一個基于PyQt5開發(fā)的視頻水印批量添加工具,旨在為多個視頻文件添加文本水印。用戶可以自定義水印的文本內(nèi)容、字體顏色、字號大小以及位置(如左上角、右上角、左下角、右下角和中心位置)。程序支持常見的視頻格式,如MP4、AVI、MOV和MKV,并能夠批量處理視頻文件,輸出帶有水印的新視頻。
2.功能介紹
選擇輸入和輸出目錄: 用戶可以通過文件對話框選擇視頻文件的輸入目錄和保存帶水印視頻的輸出目錄。
自定義水印文本: 用戶可以在輸入框中填寫水印的文本內(nèi)容,水印會被添加到視頻上。
自定義水印位置: 水印可以選擇顯示在視頻的不同位置,包括左上角、右上角、左下角、右下角和中心。
自定義水印字體顏色: 用戶可以通過顏色選擇器來選擇水印文本的顏色,支持豐富的顏色選擇。
選擇水印字體大小: 提供了多個字體大小選項(20到100),用戶可以根據(jù)需要選擇合適的字號。
批量處理視頻: 程序會遍歷輸入目錄中的所有視頻文件,逐一為其添加水印并保存到輸出目錄。支持的視頻格式包括MP4、AVI、MOV、MKV等。
進度條與日志顯示: 程序提供實時進度條,顯示當前視頻處理的進度。同時,日志框顯示詳細的處理信息和錯誤提示,幫助用戶實時了解處理狀態(tài)。
處理完成提示: 所有視頻處理完成后,會彈出提示框,告知用戶所有視頻水印已成功添加。
3. 運行效果


4.相關(guān)源碼
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:
# 創(chuàng)建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_()
5. 總結(jié)
這款視頻水印批量添加軟件通過PyQt5實現(xiàn)了一個簡潔且功能強大的圖形用戶界面,支持對多個視頻文件進行水印添加。用戶可以輕松自定義水印的各項參數(shù),程序在處理過程中提供實時進度條和日志顯示,確保用戶能夠清晰了解每個視頻的處理狀態(tài)。該工具特別適合需要批量處理視頻并添加水印的用戶,提供了便捷且高效的視頻編輯功能
到此這篇關(guān)于Python實現(xiàn)批量添加視頻文本水印的文章就介紹到這了,更多相關(guān)Python視頻添加水印內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在django view中給form傳入?yún)?shù)的例子
今天小編就為大家分享一篇在django view中給form傳入?yún)?shù)的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07
Python根據(jù)Windows窗口截圖的幾種實現(xiàn)方法
文章介紹了Windows下Python截圖的四種方法:PIL庫(簡單快速)、win32gui(精準控制窗口)、mss庫(跨平臺高性能)及win32API處理隱藏窗口,需注意窗口標題匹配、權(quán)限問題和DPI縮放調(diào)整,推薦常規(guī)截圖用PIL或mss,需精準控制時使用win32API,需要的朋友可以參考下2025-10-10

