前言
本文描述了两种对实时视频流或视频文件,进行批量抽帧截图保存的方法。
该方法提出的背景是:比如有100个视频文件或者实时视频流监控点位,我们要逐个查看具体视频画面是什么样的。
方法
两种抽帧截图方式:
- 使用opencv模块中的cv2.VideoCapture()方法进行抽帧截图;
- 使用ffmpeg工具进行抽帧,需要提前安装好ffmpeg工具(安装方式不表,百度吧);
建议选择第二种使用ffmpeg的方式。
原因之一是如果视频中有H265编码格式的,(简单来说)使用opencv方式还需要一定的兼容工作量,因为opencv支持默认的是H264编码格式。而ffmpeg则都支持。
原理实现
ffmpeg具体实现方式是使用如下命令:
ffmpeg -i rtsp://17.98.11.30:8554/Rss=38140000531320000026 -ss 2 -f image2 -frames:v 1 -y ./pics/38140000531320000026.jpg
命令参数说明:
-i 视频流地址或视频文件名
-ss 设置开始时间偏移量,单位为s或者时刻都行。如2,则代表播放2秒后开始截图。如02:55,则代表视频播放了2分55秒后开始截图。
-f image2 固定这样写即可,实际是设置输出文件的格式为image2图片
-frames:v 设置截图图片数量,这个参数需要和最后的文件名联动起来。如果是大于1张,则需要动态设置图片名称。
批量截图实现
#coding=utf-8
#这里需要引入一个readFile文件,用来读取txt中的每一行流地址内容
from readFile import readFile
import os
#【需视情况修改】
#将视频流地址放入到txt中(1行1个)
#调用readFile函数来逐行读取视频流地址
video_list = readFile("./list.txt")
#循环截图
for i in range(0, len(video_list)):
#使用strip()函数来去除,从txt文件中获取到的流地址后的换行符
current_rtsp_url = (video_list[i]).strip("\n")
#从流地址中获取设备id,用于给输出的截图命名
video_id = (current_rtsp_url.split("="))[1]
#打印出即将处理的设备ID,以让你知道当前处理到哪里啦
print(video_id)
try:
#【需视情况修改】
#使用os.system()来执行ffmpeg命令,注意最后使用了设备id作为最终图片名称,存储到pics文件夹下
os.system("ffmpeg -i " + current_rtsp_url + " -ss 2 -f image2 -frames:v 1 -y ./pics/" + video_id + ".jpg")
except Exception as e:
#如果ffmpeg命令执行报错了,print一下输出,让你知道哪个流地址报错了
print('--xxxxxxxx--:' + current_rtsp_url)
上述脚本需import的readFile函数文件内容如下,使用时,直接复制下面内容到readFile.py文件中即可:
#coding=utf-8
#function description:
#read each line of your pointed file and return list for you
#REMAINED: there is a "\n" at the end of each line content in return-list, you need to strip it before you use.
#2021年12月8日11:09:00
def readFile(filename):
with open(filename, encoding='utf-8') as f:
return f.readlines()
f.close()
if __name__ == '__main__':
filename = 'E://list.txt'
readFile(filename)
list.txt文件内容截图类似如下:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。