Python實(shí)現(xiàn)批量添加視頻文本水印
1. 簡(jiǎn)介
這個(gè)是一個(gè)基于PyQt5開(kāi)發(fā)的視頻水印批量添加工具,旨在為多個(gè)視頻文件添加文本水印。用戶可以自定義水印的文本內(nèi)容、字體顏色、字號(hào)大小以及位置(如左上角、右上角、左下角、右下角和中心位置)。程序支持常見(jiàn)的視頻格式,如MP4、AVI、MOV和MKV,并能夠批量處理視頻文件,輸出帶有水印的新視頻。
2.功能介紹
選擇輸入和輸出目錄: 用戶可以通過(guò)文件對(duì)話框選擇視頻文件的輸入目錄和保存帶水印視頻的輸出目錄。
自定義水印文本: 用戶可以在輸入框中填寫水印的文本內(nèi)容,水印會(huì)被添加到視頻上。
自定義水印位置: 水印可以選擇顯示在視頻的不同位置,包括左上角、右上角、左下角、右下角和中心。
自定義水印字體顏色: 用戶可以通過(guò)顏色選擇器來(lái)選擇水印文本的顏色,支持豐富的顏色選擇。
選擇水印字體大小: 提供了多個(gè)字體大小選項(xiàng)(20到100),用戶可以根據(jù)需要選擇合適的字號(hào)。
批量處理視頻: 程序會(huì)遍歷輸入目錄中的所有視頻文件,逐一為其添加水印并保存到輸出目錄。支持的視頻格式包括MP4、AVI、MOV、MKV等。
進(jìn)度條與日志顯示: 程序提供實(shí)時(shí)進(jìn)度條,顯示當(dāng)前視頻處理的進(jìn)度。同時(shí),日志框顯示詳細(xì)的處理信息和錯(cuò)誤提示,幫助用戶實(shí)時(shí)了解處理狀態(tài)。
處理完成提示: 所有視頻處理完成后,會(huì)彈出提示框,告知用戶所有視頻水印已成功添加。
3. 運(yùn)行效果
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()}] 開(kāi)始處理視頻: {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("選擇字號(hào)大小:") 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>] 錯(cuò)誤: 請(qǐng)檢查輸入目錄、輸出目錄和水印文本") 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實(shí)例 worker = WatermarkWorker(self.input_dir, self.output_dir, self.watermark_text, self.watermark_position, self.watermark_color, self.font_size, video_file) # 連接信號(hào) 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) # 啟動(dòng)處理 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é)
這款視頻水印批量添加軟件通過(guò)PyQt5實(shí)現(xiàn)了一個(gè)簡(jiǎn)潔且功能強(qiáng)大的圖形用戶界面,支持對(duì)多個(gè)視頻文件進(jìn)行水印添加。用戶可以輕松自定義水印的各項(xiàng)參數(shù),程序在處理過(guò)程中提供實(shí)時(shí)進(jìn)度條和日志顯示,確保用戶能夠清晰了解每個(gè)視頻的處理狀態(tài)。該工具特別適合需要批量處理視頻并添加水印的用戶,提供了便捷且高效的視頻編輯功能
到此這篇關(guān)于Python實(shí)現(xiàn)批量添加視頻文本水印的文章就介紹到這了,更多相關(guān)Python視頻添加水印內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python機(jī)器學(xué)習(xí)庫(kù)Scikit-learn實(shí)戰(zhàn)教程
文章介紹了Python在機(jī)器學(xué)習(xí)領(lǐng)域的應(yīng)用,重點(diǎn)介紹了Scikit-learn庫(kù)的使用方法,并通過(guò)實(shí)際案例展示了如何使用Scikit-learn進(jìn)行分類、回歸、聚類和文本挖掘等任務(wù),同時(shí),文章還討論了特征工程、超參數(shù)調(diào)整、避免過(guò)擬合和交叉驗(yàn)證等進(jìn)階技巧2025-01-01利用Python3實(shí)現(xiàn)統(tǒng)計(jì)大量單詞中各字母出現(xiàn)的次數(shù)和頻率的方法
這篇文章主要介紹了利用Python3實(shí)現(xiàn)統(tǒng)計(jì)大量單詞中各字母出現(xiàn)的次數(shù)和頻率,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03Python使用Marshmallow輕松實(shí)現(xiàn)序列化和反序列化
這篇文章主要為大家詳細(xì)介紹了Python如何使用Marshmallow輕松實(shí)現(xiàn)序列化和反序列化,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-03-03