场景
经常有运营反馈视频上传到系统之后,变短了。原版视频200分钟上传上来(转码)之后,只有40分钟了。这种情况通常是视频的时间戳混乱导致的,比如视频的40分钟处,时间戳变为0。下面学习下使用 ffprobe 来分析确认这种问题。
本地安装 ffmpeg
mac 系统可以先配置清华大学的镜像,然后执行 brew install ffmpeg
Debian / Ubuntu 系统:sudo apt-get install ffmpeg
Windows 系统:下载 ffmpeg 并将其添加到环境变量中。
使用 ffprobe 分析
查询视频帧率
ffprobe 工具可以用来分析视频文件,可以得到视频的信息,包括视频时长、码率、分辨率等。
可以简单的理解视频是一帧一帧的图片组成,一帧就是这个视频最小切割单元,也可以叫一个数据包。
ffprobe -i '/Users/zhoumengkang/Documents/normal_video.mp4'
...
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/Users/zhoumengkang/Documents/normal_video.mp4':
Metadata:
major_brand : mp42
minor_version : 1
compatible_brands: isommp41mp42
creation_time : 2022-11-04T09:46:54.000000Z
Duration: 00:01:12.64, start: 0.000000, bitrate: 2164 kb/s
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc, unknown/bt470bg/iec61966-2-1, progressive), 960x544, 2095 kb/s, SAR 1:1 DAR 30:17, 28 fps, 28 tbr, 600 tbn (default)
Metadata:
creation_time : 2022-11-04T09:46:54.000000Z
handler_name : Core Media Video
vendor_id : [0][0][0][0]
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 62 kb/s (default)
Metadata:
creation_time : 2022-11-04T09:46:54.000000Z
handler_name : Core Media Audio
vendor_id : [0][0][0][0]
可以看到视频文件有两个Stream
,Stream #0:0
是视频;Stream #0:1
是音频。我主要是关注视频的帧率28 fps
,也就是说一帧的时长大概是是1/28
秒,也就是0.035714秒。
逐帧分析视频
ffprobe -select_streams v -show_entries packet=pts_time,duration_time '/Users/zhoumengkang/Documents/normal_video.mp4'
-select_streams v:选择视频流进行分析,v 表示视频流。如果视频文件中包含多个视频流,则需要根据实际情况进行调整。
-show_entries packet=pts_time,duration_time:输出视频数据包的 PTS 时间戳和时长信息。
[PACKET]
pts_time=0.000000
duration_time=0.035000
[/PACKET]
[PACKET]
pts_time=0.071667
duration_time=0.035000
[/PACKET]
[PACKET]
pts_time=0.035000
duration_time=0.035000
[/PACKET]
[PACKET]
pts_time=0.143333
duration_time=0.035000
[/PACKET]
[PACKET]
pts_time=0.106667
duration_time=0.035000
[/PACKET]
[PACKET]
pts_time=0.215000
duration_time=0.035000
[/PACKET]
[PACKET]
pts_time=0.178333
duration_time=0.035000
[/PACKET]
[PACKET]
pts_time=0.285000
duration_time=0.035000
[/PACKET]
...
可以再增加一个参数输出位 csv 格式,方便后续分析
ffprobe -select_streams v -show_entries packet=pts_time,duration_time -of csv '/Users/zhoumengkang/Documents/normal_video.mp4'|head -n 10
...
packet,0.000000,0.035000
packet,0.071667,0.035000
packet,0.035000,0.035000
packet,0.143333,0.035000
packet,0.106667,0.035000
packet,0.215000,0.035000
packet,0.178333,0.035000
packet,0.285000,0.035000
第二列是时间戳,第三列是这一帧的时长。
可以发现时间戳不是完全顺序的,这就是有问题的么?
这样的结果并不一定说明时间戳是乱序的。每个视频数据包的 pts_time 属性表示该数据包的显示时间,而 duration_time 属性表示该数据包的显示时长,这两个属性并不依赖于视频数据包的先后顺序。因此,这些数据包的先后顺序并不一定是乱序的,可能是正常的时间顺序。
另外,对于视频数据包的时间戳顺序,需要根据实际情况进行分析。有时候,由于视频的编码方式或其他因素,视频数据包的时间戳可能会存在跳跃或非线性变化的情况。这种情况下,需要特别注意分析视频数据包的时间戳和时长信息,以确保分析结果的正确性。
我理解可能算法上有一些优化,我可以粗估如果前后两个数据包时间差距不大于5帧秒就是正常的。(我的外行理解)
5*0.035=0.175
下面的命令的意思就是上下两帧时间戳差距了0.175
了,就报错。
ffprobe -select_streams v -show_entries packet=pts_time,duration_time -of csv '/Users/zhoumengkang/Documents/normal_video.mp4'|awk -F ',' '{print $2}'| awk '{if ($1-p>0.175 || p-$1>0.175) {print "timestamps error:" p,$1} p=$1}'
分析视频是否有错
实际遇到的场景就是分析一个远程文件,就会遇到这种问题。线上文件有问题,不用下载,支持 https 文件。