FFMPEG 中碎片化 MP4 创建的刷新和延迟问题
Flush & Latency Issue with Fragmented MP4 Creation in FFMPEG
我正在使用以下命令为 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" 因为来源是来自网络摄像机的 rtp 数据包流中的 h264。
为了测试,相机设置GOP为1(即所有帧都是关键帧)
- "-vcodec copy"因为我不需要转码,只需要转成mp4。
- "-movflags empty_moov+default_base_moof+frag_keyframe" 根据媒体源扩展规范创建片段 mp4。
- "-" 在末尾以便将 mp4 输出到标准输出。我正在抓取输出并通过网络套接字将其发送到网络客户端。
一切正常,期待我正在尝试解决的延迟问题。
如果每次从 stdout 传入数据时我都进行记录,并带有到达时间戳,我会得到以下输出:
16/06/2015 15:40:45.239 got data size = 24
16/06/2015 15:40:45.240 got data size = 7197
16/06/2015 15:40:45.241 got data size = 32768
16/06/2015 15:40:45.241 got data size = 4941
16/06/2015 15:40:45.241 got data size = 12606
16/06/2015 15:40:45.241 got data size = 6345
16/06/2015 15:40:45.241 got data size = 6339
16/06/2015 15:40:45.242 got data size = 6336
16/06/2015 15:40:45.242 got data size = 6361
16/06/2015 15:40:45.242 got data size = 6337
16/06/2015 15:40:45.242 got data size = 6331
16/06/2015 15:40:45.242 got data size = 6359
16/06/2015 15:40:45.243 got data size = 6346
16/06/2015 15:40:45.243 got data size = 6336
16/06/2015 15:40:45.243 got data size = 6338
16/06/2015 15:40:45.243 got data size = 6357
16/06/2015 15:40:45.243 got data size = 6357
16/06/2015 15:40:45.243 got data size = 6322
16/06/2015 15:40:45.243 got data size = 6359
16/06/2015 15:40:45.244 got data size = 6349
16/06/2015 15:40:45.244 got data size = 6353
16/06/2015 15:40:45.244 got data size = 6382
16/06/2015 15:40:45.244 got data size = 6403
16/06/2015 15:40:45.304 got data size = 6393
16/06/2015 15:40:45.371 got data size = 6372
16/06/2015 15:40:45.437 got data size = 6345
16/06/2015 15:40:45.504 got data size = 6352
16/06/2015 15:40:45.571 got data size = 6340
16/06/2015 15:40:45.637 got data size = 6331
16/06/2015 15:40:45.704 got data size = 6326
16/06/2015 15:40:45.771 got data size = 6360
16/06/2015 15:40:45.838 got data size = 6294
16/06/2015 15:40:45.904 got data size = 6328
16/06/2015 15:40:45.971 got data size = 6326
16/06/2015 15:40:46.038 got data size = 6326
16/06/2015 15:40:46.105 got data size = 6340
16/06/2015 15:40:46.171 got data size = 6341
16/06/2015 15:40:46.238 got data size = 6332
如您所见,前 23 行(包含大约 1.5 秒视频的数据)几乎是立即到达,然后每 2 行连续行之间的延迟约为 70 毫秒,这是有道理的,因为视频是 15每秒帧数
此行为引入了大约 1.5 秒的延迟。
这看起来像是一个刷新问题,因为我看不出有任何理由为什么 ffmpeg 需要在内存中保存前 23 帧,尤其是因为每个帧都是它自己在 mp4 中的一个片段。
但是,我找不到任何方法可以使 ffmpeg 更快地刷新此数据。
有人有什么建议吗?
我想指出这是这个问题的后续问题:
我通过使用 -g 选项设置组中的帧数解决了延迟问题。在我的例子中,我使用了 -g 2
。我怀疑如果你不明确说明,片段要么等待源提供关键帧,要么使用非常大的默认值来生成关键帧,然后关闭片段并将其转储到标准输出。
通常在控制台输出的情况下禁用标准输出的缓冲。如果您从代码中 运行 ffmpeg,则启用缓冲,因此只有当缓冲区已满或命令结束时,您才会获取数据。
您必须消除 os 的标准输出缓冲。在 windows 它的 impossible imo,但在 ubuntu for ex。有http://manpages.ubuntu.com/manpages/maverick/man1/stdbuf.1.html
消除延迟的关键是使用 -probesize 参数:
probesize integer (input)
Set probing size in bytes, i.e. the size of
the data to analyze to get stream information. A higher value will
enable detecting more information in case it is dispersed into the
stream, but will increase latency. Must be an integer not lesser than
32. It is 5000000 by default.
默认值为 5,000,000 字节,相当于约 1.5 秒的视频。
通过将值减少到 200,000,我几乎可以完全消除延迟。
我正在使用以下命令为 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" 因为来源是来自网络摄像机的 rtp 数据包流中的 h264。 为了测试,相机设置GOP为1(即所有帧都是关键帧)
- "-vcodec copy"因为我不需要转码,只需要转成mp4。
- "-movflags empty_moov+default_base_moof+frag_keyframe" 根据媒体源扩展规范创建片段 mp4。
- "-" 在末尾以便将 mp4 输出到标准输出。我正在抓取输出并通过网络套接字将其发送到网络客户端。
一切正常,期待我正在尝试解决的延迟问题。 如果每次从 stdout 传入数据时我都进行记录,并带有到达时间戳,我会得到以下输出:
16/06/2015 15:40:45.239 got data size = 24
16/06/2015 15:40:45.240 got data size = 7197
16/06/2015 15:40:45.241 got data size = 32768
16/06/2015 15:40:45.241 got data size = 4941
16/06/2015 15:40:45.241 got data size = 12606
16/06/2015 15:40:45.241 got data size = 6345
16/06/2015 15:40:45.241 got data size = 6339
16/06/2015 15:40:45.242 got data size = 6336
16/06/2015 15:40:45.242 got data size = 6361
16/06/2015 15:40:45.242 got data size = 6337
16/06/2015 15:40:45.242 got data size = 6331
16/06/2015 15:40:45.242 got data size = 6359
16/06/2015 15:40:45.243 got data size = 6346
16/06/2015 15:40:45.243 got data size = 6336
16/06/2015 15:40:45.243 got data size = 6338
16/06/2015 15:40:45.243 got data size = 6357
16/06/2015 15:40:45.243 got data size = 6357
16/06/2015 15:40:45.243 got data size = 6322
16/06/2015 15:40:45.243 got data size = 6359
16/06/2015 15:40:45.244 got data size = 6349
16/06/2015 15:40:45.244 got data size = 6353
16/06/2015 15:40:45.244 got data size = 6382
16/06/2015 15:40:45.244 got data size = 6403
16/06/2015 15:40:45.304 got data size = 6393
16/06/2015 15:40:45.371 got data size = 6372
16/06/2015 15:40:45.437 got data size = 6345
16/06/2015 15:40:45.504 got data size = 6352
16/06/2015 15:40:45.571 got data size = 6340
16/06/2015 15:40:45.637 got data size = 6331
16/06/2015 15:40:45.704 got data size = 6326
16/06/2015 15:40:45.771 got data size = 6360
16/06/2015 15:40:45.838 got data size = 6294
16/06/2015 15:40:45.904 got data size = 6328
16/06/2015 15:40:45.971 got data size = 6326
16/06/2015 15:40:46.038 got data size = 6326
16/06/2015 15:40:46.105 got data size = 6340
16/06/2015 15:40:46.171 got data size = 6341
16/06/2015 15:40:46.238 got data size = 6332
如您所见,前 23 行(包含大约 1.5 秒视频的数据)几乎是立即到达,然后每 2 行连续行之间的延迟约为 70 毫秒,这是有道理的,因为视频是 15每秒帧数 此行为引入了大约 1.5 秒的延迟。
这看起来像是一个刷新问题,因为我看不出有任何理由为什么 ffmpeg 需要在内存中保存前 23 帧,尤其是因为每个帧都是它自己在 mp4 中的一个片段。 但是,我找不到任何方法可以使 ffmpeg 更快地刷新此数据。
有人有什么建议吗?
我想指出这是这个问题的后续问题:
我通过使用 -g 选项设置组中的帧数解决了延迟问题。在我的例子中,我使用了 -g 2
。我怀疑如果你不明确说明,片段要么等待源提供关键帧,要么使用非常大的默认值来生成关键帧,然后关闭片段并将其转储到标准输出。
通常在控制台输出的情况下禁用标准输出的缓冲。如果您从代码中 运行 ffmpeg,则启用缓冲,因此只有当缓冲区已满或命令结束时,您才会获取数据。
您必须消除 os 的标准输出缓冲。在 windows 它的 impossible imo,但在 ubuntu for ex。有http://manpages.ubuntu.com/manpages/maverick/man1/stdbuf.1.html
消除延迟的关键是使用 -probesize 参数:
probesize integer (input)
Set probing size in bytes, i.e. the size of the data to analyze to get stream information. A higher value will enable detecting more information in case it is dispersed into the stream, but will increase latency. Must be an integer not lesser than 32. It is 5000000 by default.
默认值为 5,000,000 字节,相当于约 1.5 秒的视频。 通过将值减少到 200,000,我几乎可以完全消除延迟。