python批量为视频添加文字水印和图片水印的程序
如题,代码如下,可设置多个图片水印及它们的移动位置
功能为:可以添加多个动态移动的水印,还可以设置水印的大小以及移动速度,也可以增加文字水印,重点是这个是批量执行的,可以对目录下的所有视频文件批量添加水印
import cv2
import os
import numpy as np
from moviepy.editor import VideoFileClipdef 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):# 读取视频video_clip = VideoFileClip(video_path)audio_clip = video_clip.audio# 获取视频的宽度和高度width, height = video_clip.size# 准备文本水印if add_text_watermark:# 创建用于绘制文本水印的画布text_watermark_canvas = np.zeros((height, width, 3), dtype=np.uint8)# 设置文本水印属性font_face = cv2.FONT_HERSHEY_SIMPLEXfont_scale = 1.5font_thickness = 2# 获取文本水印的大小(text_width, text_height), _ = cv2.getTextSize(text_watermark_text, font_face, font_scale, font_thickness)# 计算文本水印的位置text_x = int((width - text_width) / 2)text_y = int(height - text_height - 10)# 在画布上绘制文本水印cv2.putText(text_watermark_canvas, text_watermark_text, (text_x, text_y), font_face, font_scale, text_watermark_color, font_thickness, cv2.LINE_AA)# 在每一帧上添加水印watermark_positions = [(0, 0)] * len(watermark_image_paths)def process_frame(t, x):nonlocal watermark_positionsframe = 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.shapeif watermark_width > width or watermark_height > height:scale_factor = min(width / watermark_width, height / 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 = False# 检查新位置与已选择水印位置之间的距离for j in range(i):dist = np.sqrt((x - watermark_positions[j][0]) ** 2 + (y - watermark_positions[j][1]) ** 2)if dist < watermark_image.shape[1] or dist < watermark_image.shape[0]:too_close = Truebreakif not too_close:watermark_positions[i] = (x, y)breakelse: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.0for c in range(3):frame_copy = frame.copy()frame_copy[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_textcv2.imshow("Watermarked Video", frame)cv2.waitKey(1)return frame# 处理视频每一帧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 "水印添加完成!"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):# 获取目录中的所有文件file_list = os.listdir(directory)# 遍历文件列表for file_name in file_list:# 检查文件是否为视频文件if file_name.lower().endswith(('.avi', '.mp4', '.mov', '.mkv')):file_path = os.path.join(directory, file_name)# 设置输出文件路径output_file_path = os.path.join(output_directory, file_name)# 添加水印add_dynamic_watermarks_with_audio(file_path, output_file_path, watermark_image_paths, watermark_sizes, watermark_speeds, add_text_watermark, text_watermark_text if add_text_watermark else None, (255, 255, 255))return "批量处理完成!"# 使用示例
if __name__ == '__main__':directory = input("请输入视频文件所在目录路径:") # 视频文件所在目录output_directory = input("请输入输出视频文件目录路径:") # 输出视频文件目录# 检查并创建输出目录os.makedirs(output_directory, exist_ok=True)watermark_image_paths = []watermark_sizes = []watermark_speeds = []num_watermarks = int(input("请输入要添加的水印数量:"))for i in range(num_watermarks):watermark_image_path = input(f"请输入第{i+1}个水印图片的路径:")watermark_size = float(input(f"请输入第{i+1}个水印图片的大小(0~1之间):"))watermark_speed = int(input(f"请输入第{i+1}个水印图片的速度:"))watermark_image_paths.append(watermark_image_path)watermark_sizes.append(watermark_size)watermark_speeds.append(watermark_speed)add_text_watermark_input = input("是否添加文本水印?(y/n) ")if add_text_watermark_input.lower() == 'y':add_text_watermark = Truetext_watermark_text = input("请输入文本水印内容:")else:add_text_watermark = Falsetext_watermark_text = Nonebatch_add_watermarks_in_directory_with_audio(directory, output_directory, watermark_image_paths, watermark_sizes, watermark_speeds, add_text_watermark, text_watermark_text)
相关文章:
python批量为视频添加文字水印和图片水印的程序
如题,代码如下,可设置多个图片水印及它们的移动位置 功能为:可以添加多个动态移动的水印,还可以设置水印的大小以及移动速度,也可以增加文字水印,重点是这个是批量执行的,可以对目录下的所有视…...
使用 webpack 打包 express 应用
使用 webpack 打包 express 应用 安装 webpack 依赖 pnpm add webpack webpack-cli -D初始化配置 可以使用命令 webpack init 初始化配置或者直接自己创建 webpack.config.js 文件和增加 npm 脚本: 下面是 npm 脚本 和 webpack.config.js 配置: // G…...

深度学习——(生成模型)DDPM
前置数学知识 1、先验概率和后验概率 先验概率:根据以往经验和分析得到的概率,它往往作为“由因求果”问题中的“因”出现,如 q ( x t ∣ x t − 1 ) q(x_t|x_{t-1}) q(xt∣xt−1) 后验概率:指在得到“结果”的信息后重新修正的概率,是…...
uniapp如何使用api相关提示框
uni.showToast:用于显示一条带有图标的提示框。title:提示的内容。icon:图标,可选值包括 success、loading、none。duration:提示框持续时间(单位:毫秒),默认为1500。 un…...

在Java代码中指定用JAXB的XmlElement注解的元素的顺序
例如,下面的类RegisterResponse 使用了XmlRootElement注解,同时也使用XmlType注解,并用XmlType注解的propOrder属性,指定了两个用XmlElement注解的元素出现的顺序,先出现flag,后出现enterpriseId࿰…...

Linux 基本语句_11_无名管道文件复制
父子进程: 父子进程的变量之间存在着读时共享,写时复制原则 无名管道: 无名管道仅能用于有亲缘关系的进程之间通信如父子进程 代码: #include <stdio.h> #include <unistd.h> #include <sys/types.h> #inc…...

侧面多级菜单(一个大类、一个小类、小类下多个物体)
效果: 说明: 左右侧面板使用Animator组件控制滑入滑出。左侧面板中,左的左里面是大类,左的右有绿色的小类,绿色的小类下有多个真正的UI图片按钮。 要点: 结合了一点EasyGridBuilderPro插件的UI元素&…...
2-(脏读,不可重复读,幻读 ,mysql5.7以后默认隔离级别)、( 什么是qps,tps,并发量,pv,uv)、(什么是接口幂等性问题,如何解决?)
1 脏读,不可重复读,幻读 ,mysql5.7以后默认隔离级别是什么? 2 什么是qps,tps,并发量,pv,uv 3 什么是接口幂等性问题,如何解决? 1 脏读,不可重复读…...

wpf devexpress 创建布局
模板解决方案 例子是一个演示连接数据库连接程序。打开RegistrationForm.BaseProject项目和如下步骤 RegistrationForm.Lesson1 项目包含结果 审查Form设计 使用LayoutControl套件创建混合控件和布局 LayoutControl套件包含三个主控件: LayoutControl - 根布局…...

Chrome 浏览器经常卡死问题解决
Chrome 浏览器经常卡死问题解决 打开WX, 搜索“程序员奇点” chrome 任务管理器杀进程 mac 后台有很多 google chrome helper 线程并且内存占用较高 一直怀疑是插件的锅 其实并不是-0- 查看是哪个网页,哪个插件占用内存 chrome 更多工具 -> 任务管理器 切换到…...
listbox控件响应鼠标右键消息
众所周知,对话框中的listbox控件无法响应鼠标消息。 但是,使用SetWindowPtrLong API函数,然后在新的窗口处理程序中,可以响应WM_RBUTTONDOWN等鼠标消息。代码非常简单,暂不提供,自己测试即可。...

设计模式(二)-创建者模式(2)-工厂模式
一、为何需要工厂模式(Factory Pattern)? 由于简单工厂模式存在一个缺点,如果工厂类创建的对象过多,使得代码变得越来越臃肿。这样导致工厂类难以扩展新实例,以及难以维护代码逻辑。于是在简单工厂模式的基础上&…...

2023年高压电工证考试题库及高压电工试题解析
题库来源:安全生产模拟考试一点通公众号小程序 2023年高压电工证考试题库及高压电工试题解析是安全生产模拟考试一点通结合(安监局)特种作业人员操作证考试大纲和(质检局)特种设备作业人员上岗证考试大纲随机出的高压…...

公网访问全能知识库工具AFFINE,Notion的免费开源替代
文章目录 公网访问全能知识库工具AFFINE,Notion的免费开源替代品前言1. 使用Docker安装AFFINE2. 安装cpolar内网穿透工具3. 配置AFFINE公网访问地址4. 实现公网远程访问AFFINE 公网访问全能知识库工具AFFINE,Notion的免费开源替代品 前言 AFFiNE 是一个…...
数据存储模型
1、前言 写点什么东西呢 之前大学毕设搞了个高并发模型,里面使用到了select模型,里面用到了一个内存池,支持多客户端连接、登录、消息发送,现在工作经验三年多了,开发经验积累了不少,但是对喜爱的C的一些知…...

vue3+vant 实现树状多选组件
vue3vant 实现树状多选组件 需求描述效果图代码父组件引用selectTree组件 tree组件数据格式 需求描述 移动端需要复刻Pc端如上图的功能组件,但vant无组件可用,所以自己封装一个。 效果图 代码 父组件引用 import TreeSelect from "/selectTree.vu…...

Git安装与常用命令
Git简介: Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或大或小的项目。Git是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源代码的版本控制软件。Git与常用的版本控制工具CVS、Subversion等不同,它采用了分布式…...

uni-app 使用vscode开发uni-app
安装插件 uni-create-view 用于快速创建页面 配置插件 创建页面 输入页面名称,空格,顶部导航的标题,回车 自动生成页面并在pages.json中注册了路由 pages\login\login.vue <template><div class"login">login</d…...

单线程的JS中Vue导致的“线程安全”问题
目录 现象分析原因 浏览器中Js是单线程的,当然不可能出现线程安全问题。只是遇到的问题的现象与多线程的情况十分相似,导致对不了解Vue实现的我怀疑起了人生… 现象 项目中用到了element-plus中的加载组件,简单封装了一下,用来保…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...

Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...