使用 OpenCV 为视频添加视频时间水印

该文章的原创地址: https://bbs.huaweicloud.com/blogs/444240

1. 安装 opencv-python

pip install opencv-python

2. 代码逻辑

  1. 使用 opencv 读取视频文件
import cv2
import sys# 使用 cv 打开视频文件
cap = cv2.VideoCapture("./test.mp4")# 检查视频文件是否呈贡打开
if not cap.isOpened():print("failed to open the video file", file=sys.stderr)sys.exit(1)# 持续读取视频每一帧
while True:# ret 是读取结果, frame 是视频的每一帧ret, frame = cap.read()# 如果读取失败if not ret:print("read video file to end", file=sys.stderr)break# 显示视频# 第一个参数是窗口名称, 第二个参数是视频帧cv2.imshow("test.mp4", frame)if cv2.waitKey(1) & 0xFF == ord('q'):break
cap.release()
cv2.destroyAllWindows()
  1. 获取视频属性
# 获取视频 FPS
fps = cap.get(cv2.CAP_PROP_FPS)
# 获取视频尺寸
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 获取视频总帧数
total_frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))# 获取当前帧的时间, 毫秒
current_frame_time = (cap.get(cv2.CAP_PROP_POS_MSEC))
  1. 获取视频总时长
def get_total_video_time(frame_count, fps):(frame_count / fps) * 1000
  1. 转换帧时间为字符串
def milliseconds_to_time_str(milliseconds)# 将毫秒转换为秒seconds = milliseconds / 1000# 计算小时数hours = int(seconds // 3600)seconds %= 3600# 计算分钟数minutes = int(seconds // 60)seconds %= 60# 返回格式化的时间字符串return f"{hours:02}:{minutes:02}:{seconds:06.3f}"
  1. 绘制水印
# 总视频时长
total_video_time = get_total_video_time(total_frame_count, fps)
# 总视频时长字符串
total_video_time_str = milliseconds_to_time_str(total_video_time)# 当前视频时间字符串
current_frame_time_str = milliseconds_to_time_str(current_frame_time)# 绘制一个背景
rect_pos_1 = (0, frame_height)
rect_pos_2 = (460, frame_height - 70)
cv2.rectangle(frame, rect_pos_1, rect_pos_2, (25, 25, 25), cv2.FILLED)# 绘制帧进度
text_pos_1 = (5, frame_height - 40)
text = f"{frame_count:05}/{total_frame_count}"
cv2.putText(frame, text, text_pos_1, cv2.FONT_HERSHEY_DUPLEX ,1, (255, 255, 255), 1)# 绘制时间进度
text_pos_2 = (5, frame_height - 5)
text = f"{time_str}/{total_time_str}"
cv2.putText(frame, text, text_pos_2, cv2.FONT_HERSHEY_DUPLEX ,1, (255, 255, 255), 1)
  1. 保存视频
# 打开视频写
writer = cv2.VideoWriter("./output.mp4")
# 写出帧到视频文件
writer.write(frame)
# 释放写
writer.release()

3. 完整代码

import cv2
import sysdef get_total_video_time(frame_count, fps):return (frame_count / fps) * 1000def milliseconds_to_time_str(milliseconds):# 将毫秒转换为秒seconds = milliseconds / 1000# 计算小时数hours = int(seconds // 3600)seconds %= 3600# 计算分钟数minutes = int(seconds // 60)seconds %= 60# 返回格式化的时间字符串return f"{hours:02}:{minutes:02}:{seconds:06.3f}"def main(input_video, output_video):cap = cv2.VideoCapture(input_video)if not cap.isOpened():print(f"failed to open the video file, video_file={input_video}", file=sys.stderr)sys.exit(1)fps = cap.get(cv2.CAP_PROP_FPS)frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))total_frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))total_video_time = get_total_video_time(total_frame_count, fps)total_video_time_str = milliseconds_to_time_str(total_video_time)frame_index = 0text_pos_1 = (5, frame_height - 40)text_pos_2 = (5, frame_height - 5)rect_pos_1 = (0, frame_height)rect_pos_2 = (460, frame_height - 70)fourcc = cv2.VideoWriter_fourcc(*"mp4v")writer = cv2.VideoWriter(output_video, fourcc, fps, (frame_width, frame_height))while True:ret, frame = cap.read()if not ret:print("read to end of video", file=sys.stderr)sys.exit(1)frame_index += 1current_time = cap.get(cv2.CAP_PROP_POS_MSEC)current_time_str = milliseconds_to_time_str(current_time)cv2.rectangle(frame, rect_pos_1, rect_pos_2, (25, 25, 25), cv2.FILLED)text = f"{frame_index:05}/{total_frame_count}"cv2.putText(frame, text, text_pos_1, cv2.FONT_HERSHEY_DUPLEX, 1, (255, 255, 255), 1)text = f"{current_time_str}/{total_video_time_str}"cv2.putText(frame, text, text_pos_2, cv2.FONT_HERSHEY_DUPLEX, 1, (255, 255, 255), 1)writer.write(frame)writer.release()cap.release()cv2.destroyAllWindows()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/862274.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Typora-Markdown使用教程

Markdown介绍 Markdown是一种轻量级的标记语言 通过简单的标记语法使文本具备一定的格式,它的目标就是实现易读,易写。 标题如上在要转为标题的前面输入一个#+一个空格,光标再定位到其他位置一个一级标题就设置好了 或者使用快捷键:Ctrl+1 总结: 一级标题:一个#,或者 Ct…

[Java/Spring] 深入理解:Spring Web DispatcherServlet

1 概述:Spring Web DispatcherServlet DispatcherServlet 简介org.springframework.web.servlet.DispatcherServlet 是一个 Servlet,它接收所有的 HTTP 请求,并根据请求的信息将其分发给相应的处理器(Handler)进行处理。 它是 Spring MVC 架构模式中的关键部分,将请求处理…

DVWA靶场File Inclusion (文件包含) 漏洞所有级别通关教程及源码解析

文件包含 文件包含漏洞(File Inclusion Vulnerability)是一种常见的网络安全漏洞,主要出现在应用程序中不安全地处理文件路径时。攻击者可以利用此漏洞执行恶意文件,或者访问不该被访问的文件 1. low 有3个页面随便点击一个,可以在url处发现传参点访问:http://127.0.0.1/…

[Java]代理模式

本篇文章主要是对静态代理和动态代理实现思路的简述,以示例为主,少涉及理论。 如果文中阐述不全或不对的,多多交流。【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/18002823 出自【进步*于辰的博客】参考笔记一…

lvs+dr+httpd+keepalived高可用部署

lvs+dr+httpd+keepalived高可用部署参考文档:http://blog.csdn.net/m582445672/article/details/7670015 a、 keepalived 是lvs 的扩展项目,因此它们之间具备良好的兼容性。这点应该是keepalived 部署比其他类似工具能更简洁的原因吧! b、 通过对服务器池对象的健康检查,实…

《数字经济:行业产业链》全景梳理及区域热力图

行业主要上市公司:中兴通讯(000063)、大华股份(002236)、中科创达(300496)、软通动力(301236)、奇安信(688561)、同方股份(600100)、……等 本文核心数据:《数字经济:产业链 》、《数字经济:产业链 - 生态图谱》、《“产业数字化” 和 “数字产业化” 上市公司…

《数字经济行业产业链》全景梳理及区域热力图

行业主要上市公司:中兴通讯(000063)、大华股份(002236)、中科创达(300496)、软通动力(301236)、奇安信(688561)、同方股份(600100)、……等 本文核心数据:《数字经济产业链 》、《数字经济产业链生态图谱》、《产业数字化 和 数字产业化上市公司区域分布 TOP5》、…

【长路经】C#读取文件抛出FileNotFoundException异常

前言 在winform中读取文件信息时,突然抛出了FileNotFoundException的异常,但是本地是有这个文件的。 随后找到了这个文件,查看属性,[位置]属性,多了"\\?\"的前缀,百度得知这是windows对长路经的处理。需要注意: 目前在NetFx框架下,才有这个问题。 在NetCore…

【unity】学习制作类银河恶魔城游戏-5-

在-1---4-中,了解了unity的基础操作,从创建一个人物开始,通过状态机和代码完善人物的各种功能达到预期效果,随着功能的越来越多,状态机的处理也就越发麻烦,因此,从零开始设计一个合理的状态机很有必要 梦开始的地方 创建一个新的项目修改舒服的布局创建状态机,通过脚本…

CH340C 请求 USB 设备描述符失败

简短不看版如果出现上述状况,说明线有问题:线的确是数据线(不是电源线),但是不是能与CH340正常通讯的数据线(数据线的数据传输功能有问题。 需要更换其它数据线.前文该文分享CH340驱动使用过程可能出现的问题,以下出现的问题解决方案都建立在CH340硬件正常的情况下。CH3…

CH32V203F6P6-TSSOP20测试之02

一、问题思考 直接用官方提供的例程,为何下载程序后没有什么响应,难道自己设计的电路有什么不妥? 于是,对于电路进行具体分析,结果发现: 第一、官方的BOOT0采用杜邦线连接,在芯片手册好像找不到关于BOOT0的叙述,仅仅在《CH32V20x评估板说明书》中看到:也就是说,这芯片…

PVC

短线反弹