ffmpeg 的 -r 放错位置,把我整段时间标定搞偏了 2.3 倍
问题
我写了个脚本,用 ffmpeg 把一段监控视频降帧成 10fps,再一帧一帧喂给我的检测程序。降帧的目的,是让程序里”观察 10 秒""异常持续 5 秒才报警”这种时间窗算得准——帧率对了,时间才对。
我一开始是这么写的:
ffmpeg -r 10 -i input.mp4 ... -f rawvideo -
-r 10 放在 -i 前面,意思是”输入按 10fps 读”。当时觉得没毛病。
现象
跑完一段 150 秒的视频,程序打印的总耗时(elapsed)是 342 秒,差不多虚高了 2.3 倍。我顺手数了下输出的帧数,原片是 25fps,结果 ffmpeg 吐出来 3426 帧——也就是说它压根没按 10fps 降,还是按原片的 25fps 在出帧。
连锁反应很要命:我的”观察 10 秒”窗口,实际只覆盖了标称时长一半的画面;之前在 10fps 假设下标定好的所有阈值,全偏了。程序看着在跑,其实时间轴是歪的。
执行效果:
预期:150s 视频 -> 约 1500 帧,elapsed ≈ 150s
实际:150s 视频 -> 3426 帧,elapsed ≈ 342s(虚高 2.3x)
怎么解决
真正的原因在 ffmpeg 的选项位置:-i 把命令分成了”输入侧”和”输出侧”,很多参数是分边的。
-r 放在 -i 前面,是当成输入选项,对 mp4 这种本来就带固定帧率的文件几乎不生效——ffmpeg 直接沿用原片的 25fps。要强制”输出成 10fps”,得把 -r 10 挪到 -i 后面、当输出选项:
ffmpeg -i input.mp4 -r 10 -s 1280x720 -pix_fmt bgr24 -f rawvideo -
改完再跑,帧数和时间都对上了。
执行效果:
改动后:150s 视频 -> 约 1500 帧,elapsed ≈ 150s ✅
观察窗真实跨度 = 标称,阈值标定不再偏
结论
跟 ffmpeg 打交道,选项摆在 -i 前还是后差别很大:前面是输入侧、后面是输出侧,不少参数(不只是 -r)都认这个分界。想强制输出规格,一律放 -i 后。我现在写视频处理脚本,凡是涉及帧率、分辨率、像素格式的,都习惯性地排在输入文件后面,不再想当然往前摆。
另外,时间相关的程序,跑完一定要核对一下”实际帧数 × 帧间隔”是否等于视频真实时长,别只看”跑通了”就信时间轴是对的。我这回就是没核,差了两倍多都没发现。