在 FFMPEG 中创建分段 MP4 的刷新和延迟问题
Posted
技术标签:
【中文标题】在 FFMPEG 中创建分段 MP4 的刷新和延迟问题【英文标题】:Flush & Latency Issue with Fragmented MP4 Creation in FFMPEG 【发布时间】:2015-09-01 08:19:23 【问题描述】:我正在使用以下命令为 html5 流式传输创建分段 mp4:
-i rtsp://172.20.28.52:554/h264 -vcodec copy -an -f mp4 -reset_timestamps 1 -movflags empty_moov+default_base_moof+frag_keyframe -loglevel quiet -
-
"-i rtsp://172.20.28.52:554/h264" 因为源是来自 ip 摄像机的 rtp 数据包流中的 h264。
为了测试,相机的 GOP 设置为 1(即所有帧都是关键帧)
“-vcodec copy”因为我不需要转码,只需要remux到mp4。
“-movflags empty_moov+default_base_moof+frag_keyframe”根据媒体源扩展规范创建分段的mp4。
“-”在末尾,以便将 mp4 输出到标准输出。我正在获取输出并通过网络套接字将其发送到网络客户端。
一切正常,期待我正在尝试解决的延迟问题。 如果我每次从标准输出输入数据时都在记录,并带有到达的时间戳,我会得到以下输出:
16/06/2015 15:40:45.239 得到数据大小 = 24
16/06/2015 15:40:45.240 得到数据大小 = 7197
16/06/2015 15:40:45.241 得到数据大小 = 32768
16/06/2015 15:40:45.241 得到数据大小 = 4941
16/06/2015 15:40:45.241 得到数据大小 = 12606
16/06/2015 15:40:45.241 得到数据大小 = 6345
16/06/2015 15:40:45.241 得到数据大小 = 6339
16/06/2015 15:40:45.242 得到数据大小 = 6336
16/06/2015 15:40:45.242 得到数据大小 = 6361
16/06/2015 15:40:45.242 得到数据大小 = 6337
16/06/2015 15:40:45.242 得到数据大小 = 6331
16/06/2015 15:40:45.242 得到数据大小 = 6359
16/06/2015 15:40:45.243 得到数据大小 = 6346
16/06/2015 15:40:45.243 得到数据大小 = 6336
16/06/2015 15:40:45.243 得到数据大小 = 6338
16/06/2015 15:40:45.243 得到数据大小 = 6357
16/06/2015 15:40:45.243 得到数据大小 = 6357
16/06/2015 15:40:45.243 得到数据大小 = 6322
16/06/2015 15:40:45.243 得到数据大小 = 6359
16/06/2015 15:40:45.244 得到数据大小 = 6349
16/06/2015 15:40:45.244 得到数据大小 = 6353
16/06/2015 15:40:45.244 得到数据大小 = 6382
16/06/2015 15:40:45.244 得到数据大小 = 6403
16/06/2015 15:40:45.304 得到数据大小 = 6393
16/06/2015 15:40:45.371 得到数据大小 = 6372
16/06/2015 15:40:45.437 得到数据大小 = 6345
16/06/2015 15:40:45.504 得到数据大小 = 6352
16/06/2015 15:40:45.571 得到数据大小 = 6340
16/06/2015 15:40:45.637 得到数据大小 = 6331
16/06/2015 15:40:45.704 得到数据大小 = 6326
16/06/2015 15:40:45.771 得到数据大小 = 6360
16/06/2015 15:40:45.838 得到数据大小 = 6294
16/06/2015 15:40:45.904 得到数据大小 = 6328
16/06/2015 15:40:45.971 得到数据大小 = 6326
16/06/2015 15:40:46.038 得到数据大小 = 6326
16/06/2015 15:40:46.105 得到数据大小 = 6340
16/06/2015 15:40:46.171 得到数据大小 = 6341
16/06/2015 15:40:46.238 得到数据大小 = 6332
如您所见,前 23 行(包含大约 1.5 秒视频的数据)几乎是立即到达的,然后每 2 行连续的行之间的延迟约为 70 毫秒,这是有道理的,因为视频是每帧 15 帧秒。 这种行为会导致大约 1.5 秒的延迟。
这看起来像是一个刷新问题,因为我看不出 ffmpeg 需要在内存中保存前 23 帧的任何理由,特别是因为每一帧都是它自己在 mp4 中的片段。 但是,我找不到任何可以使 ffmpeg 更快地刷新这些数据的方法。
有人有建议吗?
我想指出,这是对此问题的后续问题: Live streaming dash content using mp4box
【问题讨论】:
我突然想到,您可以控制用于缓冲输出的blocksize
。检查ffmpeg.org/ffmpeg-all.html#toc-pipe,看看调整该值是否可以帮助您。
@PabloMontilla 我尝试使用一些不同的 blocksize 值,虽然它以某种方式影响输出,但它并没有解决初始延迟。
你好@galbarm!我无法使用您的ffmpeg
参数在页面上运行视频,总是得到Skipping unrecognized top-level box: ftyp
。 (h264 网络摄像机)。我还尝试将-vcodec
更改为libx264
,这种情况下我得到Skipping unrecognized top-level box: mdat
。您能否更多地描述您的代码或在某处提供要点?最有趣的部分是.addSourceBuffer
参数,即编解码器字符串。提前致谢!
嗨,@zarkone 我也看到“跳过 ftyp”错误,但它似乎没有任何功能效果。这是客户端代码的要点,我相信它会对您有所帮助:gist.github.com/galbarm/8cb1b684652de648ded3
感谢您的 sn-p!
【参考方案1】:
消除延迟的关键是使用 -probesize 参数:
探测整数(输入)
以字节为单位设置探测大小,即 要分析的数据以获取流信息。更高的价值将 启用检测更多信息,以防它分散到 流,但会增加延迟。必须是不小于的整数 32. 默认为5000000。
默认值为 5,000,000 字节,相当于约 1.5 秒的视频。 通过将值减小到 200,000,我几乎可以完全消除延迟。
【讨论】:
我参加聚会有点晚了,但我正在努力做同样的事情。除了我打算用 RTCDataChannel(本质上是 UDP)而不是 WebSockets 发送数据,这在技术上应该会给我更好的延迟。我对所有这些视频内容都很陌生,我很难理解所有这些关于moof
、mdat
和moov
的讨论,以及在通过它们之前我需要对收到的 mp4 块做什么在 SourceBuffer 上。你能提供一些指导吗?【参考方案2】:
在控制台输出的情况下,通常会禁用标准输出的缓冲。如果您从代码中运行 ffmpeg,则会启用缓冲,因此只有在缓冲区已满或命令结束时才能获取数据。
您必须消除操作系统的标准输出缓冲。在 Windows 上它是不可能的 imo,但在 ubuntu 上是 ex。有http://manpages.ubuntu.com/manpages/maverick/man1/stdbuf.1.html
【讨论】:
【参考方案3】:我通过使用 -g 选项设置组中的帧数解决了延迟问题。就我而言,我使用了-g 2
。我怀疑如果您不明确说明,片段要么等待源提供关键帧,要么使用非常大的默认值生成关键帧,然后关闭片段并将其转储到标准输出。
【讨论】:
我猜您正在对视频进行转码,以便您可以控制输出 GOP 的大小。我在“vcodec 复制”模式下使用 ffmpeg,因此只能将其重新混合到碎片化的 mp4 中。我尝试将视频源(IP 摄像头)设置为仅提供关键帧,但对初始延迟没有帮助。以上是关于在 FFMPEG 中创建分段 MP4 的刷新和延迟问题的主要内容,如果未能解决你的问题,请参考以下文章