我正在尝试将视频文件的帧作为图像,并附带标签以表明该帧是 I 帧、P 帧还是 B 帧。
我知道 ffmpeg 只能使用以下方式输出特定类型的帧select
对于 I-Frames,可以执行以下操作:
ffmpeg -i input.mp4 -vf "select='eq(pict_type,PICT_TYPE_I)'" -vsync vfr iframe_%04d.png
其他图片类型可用于 B 或 P 帧。但是这会将帧输出为 iframe_0001.png、iframe_0002.png 等。视频中的原始帧编号会丢失。
例如,要实现类似的效果:iframes_0001.png、bframe_0002.png、bframe_0003.png、pframe_0004.png、bframe_0005.png、iframe_0006.png,...
如果需要多次传递,那么生成一个指定帧类型的辅助文件也是可以的(可能是具有帧编号和帧属性的文本文件)。
答案1
使用
ffmpeg -i input.mp4 -filter_complex "setpts=N/TB,select='1*eq(pict_type,PICT_TYPE_I)+2*eq(pict_type,PICT_TYPE_P)+3*eq(pict_type,PICT_TYPE_B)':n=3[i][p][b]" -vsync 0 -map "[i]" -r 1 -frame_pts 1 iframe_%04d.png -map "[p]" -r 1 -frame_pts 1 pframe_%04d.png -map "[b]" -r 1 -frame_pts 1 bframe_%04d.png
选择过滤器可以一次生成多个输出。帧发送到哪个输出取决于表达式的计算值。上面的表达式将根据帧类型计算为 1、2 或 3,并分别发送到第一个、第二个或第三个输出。然后将这三个输出映射到不同的输出。
frame_pts 选项使文件名包含帧时间戳。在 select 过滤器之前,添加了 setpts 过滤器以使帧时间戳相隔 1 秒。-r 1
添加到每个输出,以便文件名符合预期。请参阅快速提取图像中的 I 帧为什么。