ffmpeg CLI允许您指定-r <fps>
或-vf fps=<fps>
为您的输出设置固定的FPS。
我想要的行为是:
更多背景信息:
前面提到的选项非常适合将视频标准化为固定的FPS,但不能很好地确保视频无法有效地超过某个FPS阈值。实际上,如果我设置-r 30
并且视频是29 fps,那么当我的用例不需要时,ffmpeg会向我们提供大量的CPU以将其提升到30
。 / p>
答案 0 :(得分:2)
这可以在恒定帧速率视频上完成 - 我的下面的方法可能适用于VFR视频,但我没有合适的视频可供测试。
基本命令:
ffmpeg -i 120.mp4 -vf "select='eq(n,0)+if(gt(t-prev_selected_t,1/30.01),1,0)'" -vsync 0 out.mp4
在120 fps的流上,
Video: h264 (High) ... 120 fps, 120 tbr, 15360 tbn, 240 tbc
这会产生
Video: h264 (High) ... 30.08 fps, 30 tbr, 15360 tbn, 240 tbc
在选择第一帧之后,选择过滤器的作用是,如果它们与先前选择的帧的间隔是1/30秒或更多,则仅选择其他帧。实际上,这会将视频抽取到30 fps以下。
有两点需要注意:
1)最后一帧的持续时间被截断,因此fps
值将略大于目标。但所有其他帧的帧周期为30 fps。
2)输出帧速率是将源速率除以整数得到的最高数。因此,如果在命令中30.01
被26
替换,则结果将为24 tbr
,因为通过将120除以整数,都不能获得25和26。这有利于避免输出中的运动停顿。命令中的除数应略大于上限,即30.01
而不是30
。否则,结果会摇摆不定。
如果输入为30 fps或更低,则选择所有帧。
<强>附录强>:
如果将上述命令的输出传送到另一个ffmpeg实例,则输出fps
是准确的,并且编解码器速率tbc
也会被重置。
ffmpeg -i 120.mp4 -vf "select='eq(n,0)+if(gt(t-prev_selected_t,1/30.01),1,0)'" -vsync 0
-c:v rawvideo -c:a pcm_s16le -f nut - | ffmpeg -f nut -i - out.mp4