使用 FFMPEG 创建无限 MP4(不循环)
Creating an infinite MP4 with FFMPEG (not looping)
我知道 mp4 流媒体是禁忌,这个项目只是为了播放视频:)
我有一个 Raspberry Pi 相机提供的无限 h264 流,我想将它包装在一个无限 mp4 中,以便我可以在浏览器中观看。
(来源)raspivid -t 0 -w 1640 -h 1232 -fps 20 -b 500000 -vf -hf -o -
(ffmpeg)ffmpeg -r 20 -i - -vcodec copy -movflags "frag_keyframe+empty_moov" -f mp4 pipe:1
我所做的是将 (source) 通过管道传输到 (ffmpeg),然后将 (ffmpeg) 传输到我的程序,该程序会缓冲、上传到服务器、进行身份验证等。
效果很好,我可以通过浏览器观看流。
问题: 问题是 (ffmpeg) 在 6 分钟后停止输出数据。
当视频达到 6:00 时,(ffmpeg) 命令就停止向其 stdout
写入数据。
我尝试更改帧率、比特率、分辨率等,但没有什么不同,它总是停在 6:00。
我检查了(源)命令,它仍在写入自己的 stdout
。
问题:我缺少什么吗?为什么它在 6 分钟后就停止写入 stdout
?该命令是否缺少一些允许无限 mp4 的标志?
编辑:在下面添加了-report
的输出。
ffmpeg started on 2017-12-26 at 19:59:13
Report written to "ffmpeg-20171226-195913.log"
Command line:
ffmpeg -report -r 20 -i - -vcodec copy -movflags frag_keyframe+empty_moov -f mp4 pipe:1
ffmpeg version git-2017-12-10-eaff5fc Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 6.3.0 (Raspbian 6.3.0-18+rpi1) 20170516
configuration: --arch=armel --target-os=linux --enable-gpl --enable-nonfree
libavutil 56. 5.100 / 56. 5.100
libavcodec 58. 6.103 / 58. 6.103
libavformat 58. 3.100 / 58. 3.100
libavdevice 58. 0.100 / 58. 0.100
libavfilter 7. 7.100 / 7. 7.100
libswscale 5. 0.101 / 5. 0.101
libswresample 3. 0.101 / 3. 0.101
libpostproc 55. 0.100 / 55. 0.100
Splitting the commandline.
Reading option '-report' ... matched as option 'report' (generate a report) with argument '1'.
Reading option '-r' ... matched as option 'r' (set frame rate (Hz value, fraction or abbreviation)) with argument '20'.
Reading option '-i' ... matched as input url with argument '-'.
Reading option '-vcodec' ... matched as option 'vcodec' (force video codec ('copy' to copy stream)) with argument 'copy'.
Reading option '-movflags' ... matched as AVOption 'movflags' with argument 'frag_keyframe+empty_moov'.
Reading option '-f' ... matched as option 'f' (force format) with argument 'mp4'.
Reading option 'pipe:1' ... matched as output url.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option report (generate a report) with argument 1.
Successfully parsed a group of options.
Parsing a group of options: input url -.
Applying option r (set frame rate (Hz value, fraction or abbreviation)) with argument 20.
Successfully parsed a group of options.
Opening an input file: -.
[NULL @ 0x2e7d450] Opening 'pipe:' for reading
[pipe @ 0x2e7db70] Setting default whitelist 'crypto'
[h264 @ 0x2e7d450] Format h264 probed with size=2048 and score=51
[h264 @ 0x2e7d450] Before avformat_find_stream_info() pos: 0 bytes read:4096 seeks:0 nb_streams:1
[AVBSFContext @ 0x2e8f3e0] nal_unit_type: 7, nal_ref_idc: 1
[AVBSFContext @ 0x2e8f3e0] nal_unit_type: 8, nal_ref_idc: 1
[AVBSFContext @ 0x2e8f3e0] nal_unit_type: 5, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 7, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 8, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 5, nal_ref_idc: 1
[h264 @ 0x2e7fa60] Format yuv420p chosen by get_format().
[h264 @ 0x2e7fa60] Reinit context to 1648x1232, pix_fmt: yuv420p
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7d450] max_analyze_duration 5000000 reached at 5000000 microseconds st:0
[h264 @ 0x2e7d450] After avformat_find_stream_info() pos: 395264 bytes read:397312 seeks:0 frames:127
Input #0, h264, from 'pipe:':
Duration: N/A, bitrate: N/A
Stream #0:0, 127, 1/1200000: Video: h264 (High), yuv420p(progressive), 1640x1232, 25 fps, 25 tbr, 1200k tbn, 50 tbc
Successfully opened the file.
Parsing a group of options: output url pipe:1.
Applying option vcodec (force video codec ('copy' to copy stream)) with argument copy.
Applying option f (force format) with argument mp4.
Successfully parsed a group of options.
Opening an output file: pipe:1.
[pipe @ 0x2e8ef70] Setting default whitelist 'crypto'
Successfully opened the file.
[mp4 @ 0x2e80680] Empty MOOV enabled; disabling automatic bitstream filtering
Output #0, mp4, to 'pipe:1':
Metadata:
encoder : Lavf58.3.100
Stream #0:0, 0, 1/10240: Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1640x1232, q=2-31, 25 fps, 25 tbr, 10240 tbn, 20 tbc
Stream mapping:
Stream #0:0 -> #0:0 (copy)
cur_dts is invalid (this is harmless if it occurs once at the start per stream)
[mp4 @ 0x2e80680] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
frame= 140 fps=0.0 q=-1.0 size= 352kB time=00:00:06.95 bitrate= 415.4kbits/s speed=11.8x
frame= 152 fps=128 q=-1.0 size= 352kB time=00:00:07.55 bitrate= 382.4kbits/s speed=6.35x
frame= 164 fps= 94 q=-1.0 size= 352kB time=00:00:08.15 bitrate= 354.3kbits/s speed=4.69x
frame= 174 fps= 78 q=-1.0 size= 352kB time=00:00:08.65 bitrate= 333.8kbits/s speed=3.86x
.....
frame= 7342 fps= 20 q=-1.0 size= 22381kB time=00:06:07.05 bitrate= 499.5kbits/s speed=1.02x
frame= 7354 fps= 20 q=-1.0 size= 22381kB time=00:06:07.65 bitrate= 498.7kbits/s speed=1.02x
frame= 7366 fps= 20 q=-1.0 size= 22381kB time=00:06:08.25 bitrate= 497.9kbits/s speed=1.02x
如您所见,它在 运行 上的 6:08 处停止工作。然后它闲置了几分钟,我不得不终止进程。
事实证明这就是我处理流程的方式。
ffmpeg
将类似于 -report
的内容写到 stderr
:
// This line over and over:
frame= 8237 fps= 20 q=-1.0 Lsize= 25192kB time=00:06:51.80 bitrate= 501.2kbits/s speed=1.02x
我没有考虑到这一点,完全忽略了 stderr
直到它备份了流并且进程卡住了:(
由于 stderr
的日志记录遵循恒定速率(不依赖于比特率、帧率等),该过程总是同时卡住,在我的情况下大约 6:00。
解决方案:不要忘记阅读或重定向stderr
!!
我知道 mp4 流媒体是禁忌,这个项目只是为了播放视频:)
我有一个 Raspberry Pi 相机提供的无限 h264 流,我想将它包装在一个无限 mp4 中,以便我可以在浏览器中观看。
(来源)raspivid -t 0 -w 1640 -h 1232 -fps 20 -b 500000 -vf -hf -o -
(ffmpeg)ffmpeg -r 20 -i - -vcodec copy -movflags "frag_keyframe+empty_moov" -f mp4 pipe:1
我所做的是将 (source) 通过管道传输到 (ffmpeg),然后将 (ffmpeg) 传输到我的程序,该程序会缓冲、上传到服务器、进行身份验证等。
效果很好,我可以通过浏览器观看流。
问题: 问题是 (ffmpeg) 在 6 分钟后停止输出数据。
当视频达到 6:00 时,(ffmpeg) 命令就停止向其 stdout
写入数据。
我尝试更改帧率、比特率、分辨率等,但没有什么不同,它总是停在 6:00。
我检查了(源)命令,它仍在写入自己的 stdout
。
问题:我缺少什么吗?为什么它在 6 分钟后就停止写入 stdout
?该命令是否缺少一些允许无限 mp4 的标志?
编辑:在下面添加了-report
的输出。
ffmpeg started on 2017-12-26 at 19:59:13
Report written to "ffmpeg-20171226-195913.log"
Command line:
ffmpeg -report -r 20 -i - -vcodec copy -movflags frag_keyframe+empty_moov -f mp4 pipe:1
ffmpeg version git-2017-12-10-eaff5fc Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 6.3.0 (Raspbian 6.3.0-18+rpi1) 20170516
configuration: --arch=armel --target-os=linux --enable-gpl --enable-nonfree
libavutil 56. 5.100 / 56. 5.100
libavcodec 58. 6.103 / 58. 6.103
libavformat 58. 3.100 / 58. 3.100
libavdevice 58. 0.100 / 58. 0.100
libavfilter 7. 7.100 / 7. 7.100
libswscale 5. 0.101 / 5. 0.101
libswresample 3. 0.101 / 3. 0.101
libpostproc 55. 0.100 / 55. 0.100
Splitting the commandline.
Reading option '-report' ... matched as option 'report' (generate a report) with argument '1'.
Reading option '-r' ... matched as option 'r' (set frame rate (Hz value, fraction or abbreviation)) with argument '20'.
Reading option '-i' ... matched as input url with argument '-'.
Reading option '-vcodec' ... matched as option 'vcodec' (force video codec ('copy' to copy stream)) with argument 'copy'.
Reading option '-movflags' ... matched as AVOption 'movflags' with argument 'frag_keyframe+empty_moov'.
Reading option '-f' ... matched as option 'f' (force format) with argument 'mp4'.
Reading option 'pipe:1' ... matched as output url.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option report (generate a report) with argument 1.
Successfully parsed a group of options.
Parsing a group of options: input url -.
Applying option r (set frame rate (Hz value, fraction or abbreviation)) with argument 20.
Successfully parsed a group of options.
Opening an input file: -.
[NULL @ 0x2e7d450] Opening 'pipe:' for reading
[pipe @ 0x2e7db70] Setting default whitelist 'crypto'
[h264 @ 0x2e7d450] Format h264 probed with size=2048 and score=51
[h264 @ 0x2e7d450] Before avformat_find_stream_info() pos: 0 bytes read:4096 seeks:0 nb_streams:1
[AVBSFContext @ 0x2e8f3e0] nal_unit_type: 7, nal_ref_idc: 1
[AVBSFContext @ 0x2e8f3e0] nal_unit_type: 8, nal_ref_idc: 1
[AVBSFContext @ 0x2e8f3e0] nal_unit_type: 5, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 7, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 8, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 5, nal_ref_idc: 1
[h264 @ 0x2e7fa60] Format yuv420p chosen by get_format().
[h264 @ 0x2e7fa60] Reinit context to 1648x1232, pix_fmt: yuv420p
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7fa60] nal_unit_type: 1, nal_ref_idc: 1
[h264 @ 0x2e7d450] max_analyze_duration 5000000 reached at 5000000 microseconds st:0
[h264 @ 0x2e7d450] After avformat_find_stream_info() pos: 395264 bytes read:397312 seeks:0 frames:127
Input #0, h264, from 'pipe:':
Duration: N/A, bitrate: N/A
Stream #0:0, 127, 1/1200000: Video: h264 (High), yuv420p(progressive), 1640x1232, 25 fps, 25 tbr, 1200k tbn, 50 tbc
Successfully opened the file.
Parsing a group of options: output url pipe:1.
Applying option vcodec (force video codec ('copy' to copy stream)) with argument copy.
Applying option f (force format) with argument mp4.
Successfully parsed a group of options.
Opening an output file: pipe:1.
[pipe @ 0x2e8ef70] Setting default whitelist 'crypto'
Successfully opened the file.
[mp4 @ 0x2e80680] Empty MOOV enabled; disabling automatic bitstream filtering
Output #0, mp4, to 'pipe:1':
Metadata:
encoder : Lavf58.3.100
Stream #0:0, 0, 1/10240: Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 1640x1232, q=2-31, 25 fps, 25 tbr, 10240 tbn, 20 tbc
Stream mapping:
Stream #0:0 -> #0:0 (copy)
cur_dts is invalid (this is harmless if it occurs once at the start per stream)
[mp4 @ 0x2e80680] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
frame= 140 fps=0.0 q=-1.0 size= 352kB time=00:00:06.95 bitrate= 415.4kbits/s speed=11.8x
frame= 152 fps=128 q=-1.0 size= 352kB time=00:00:07.55 bitrate= 382.4kbits/s speed=6.35x
frame= 164 fps= 94 q=-1.0 size= 352kB time=00:00:08.15 bitrate= 354.3kbits/s speed=4.69x
frame= 174 fps= 78 q=-1.0 size= 352kB time=00:00:08.65 bitrate= 333.8kbits/s speed=3.86x
.....
frame= 7342 fps= 20 q=-1.0 size= 22381kB time=00:06:07.05 bitrate= 499.5kbits/s speed=1.02x
frame= 7354 fps= 20 q=-1.0 size= 22381kB time=00:06:07.65 bitrate= 498.7kbits/s speed=1.02x
frame= 7366 fps= 20 q=-1.0 size= 22381kB time=00:06:08.25 bitrate= 497.9kbits/s speed=1.02x
如您所见,它在 运行 上的 6:08 处停止工作。然后它闲置了几分钟,我不得不终止进程。
事实证明这就是我处理流程的方式。
ffmpeg
将类似于 -report
的内容写到 stderr
:
// This line over and over:
frame= 8237 fps= 20 q=-1.0 Lsize= 25192kB time=00:06:51.80 bitrate= 501.2kbits/s speed=1.02x
我没有考虑到这一点,完全忽略了 stderr
直到它备份了流并且进程卡住了:(
由于 stderr
的日志记录遵循恒定速率(不依赖于比特率、帧率等),该过程总是同时卡住,在我的情况下大约 6:00。
解决方案:不要忘记阅读或重定向stderr
!!