如何将 MP4 帧率转换为 15fps,例如 14.939948fps?

4

描述

我使用ffmpeg将USB摄像头视频流推送到名为SRS的RTMP流服务器。

SRS为我保存了一个MP4文件。帧率在VLC中不是常见的值,它是14.939948。我已经核实了——似乎是“ntsc”格式。

同时,我通过OpenCV接收了该流并将其保存为另一个MP4文件。它们不是同步的。

我尝试使用ffmpeg转换帧率,但仍然不同步。唯一的方法是将其放入Adobe Premiere中并修改帧率。这是我执行的ffmpeg命令:

ffmpeg -i 1639444871684_copy.mp4 -filter:v fps=15 out.mp4

除了流服务器之外,我如何将帧率转换为正常并同时保持同步?


我认为你的问题是,你有一个以14.939948帧每秒播放的视频,你想将其插值为以15帧每秒运行,但仍然以相同的速度播放。做一些快速的数学计算,你可以通过复制每249帧来实现这一点。也许采用电影转换的方法,在插入的帧中混合前后两个帧(即在两个帧上都设置50%的alpha值,以制作复合模糊帧)。我不知道这样做是否会看起来好。 - selbie
谢谢你,selbie!我认为这对我来说并不是一件简单的事情,但我希望比我更优秀的人能看到你的答案。 - Bling Bling Bytes
你不能依赖那样的相机有一个恒定的帧率。无论你使用的下游软件是什么,都需要读取时间戳而不仅仅是逐帧读取。问题就出在这里。 - Brad
3个回答

3
注意:不建议依赖FPS进行实时流媒体传输,因为RTMP/FLV始终使用固定的TBN(时间基准)为1k,这可能会在通过RTMP发布流或录制到TS/MP4等格式时引入偏差。
注意:对于WebRTC,FPS是可变的。请参考WebRTC是否使用恒定帧率来捕获视频帧可变帧率(VFR)以获取更多信息。
该问题与SRS或FPS无关,并且可以使用FFmpeg复制。
  1. 使用FFmpeg将doc/source.flv从25fps转码为15fps,然后通过RTMP协议发布到SRS(15fps)。
  2. 使用FFmpeg将RTMP(15fps)流录制为output.mp4(15fps)。
  3. 使用VLC播放output.mp4(15fps),您会注意到帧率并不完全是15fps。

首先,使用以下配置启动SRS,并确保禁用DVR功能:

# ./objs/srs -c test.conf
listen              1935;
daemon              off;
srs_log_tank        console;

vhost __defaultVhost__ {
}

运行FFmpeg进行转码并发布到SRS,将帧率改为15。
cd srs/trunk
ffmpeg -re -i doc/source.flv -c:v libx264 -r 15 -c:a copy \
  -f flv rtmp://localhost/live/livestream

记录 RTMP 流(以 15 帧每秒的速度)到 output.mp4。在 FFmpeg 日志中,你会看到帧率是 15。
ffmpeg -f flv -i rtmp://localhost/live/livestream -c copy -y output.mp4

使用VLC播放output.mp4(15fps),然后打开窗口 -> 媒体信息。你会发现FPS在14.8fps左右波动,而不是完全准确的15fps。
这种偏差是因为RTMP/FLV的TBN固定为1000(1k tbn,每帧大约为66.67毫秒)。当将MP4发布到RTMP流时引入了这种偏差。这不是由DVR引起的,而是由RTMP/FLV TBN引起的。

注意:对于SRS来说,使用固定的1k TBN可能不是最佳选择,因为它对于MP4的持续时间并不理想。问题srs#2790已重新打开。

总之,帧率/FPS不是一个固定值,它只是流的指示器。播放器依靠DTS/PTS来确定何时以及如何渲染图像。

谢谢,你的回答非常有帮助!我坚信SRS项目可能是最好的。 - Bling Bling Bytes

1

使用-r

ffmpeg -i 1639444871684_copy.mp4 -r 15 out.mp4

谢谢!我已经尝试过了。无法同步。 - Bling Bling Bytes

0

回答自己。这是我的方法:使用OpenCV读取并将帧以15FPS的速度写入新文件。它们将被同步。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接