【发布时间】:2018-12-18 16:57:20
【问题描述】:
我正在尝试使用 h264 编码在浏览器中设置直播,其中 javascript 解码 h264 帧并将其绘制在 Canvas 元素(或使用 WebGL)上。
Broadway 和 Prism 都实现了解码类型 1、5、7 和 8 的 NAL 单元。
我目前的设置如下:
- FFMpeg 输出带有 h264 数据的 MPEG-TS 流
- 流通过管道传送到侦听端口 8084 的 netcat
- NodeJS 中的 websocket 服务器将数据从端口 8084 管道传输到 8085 上的客户端
- jsmpeg 库将 MPEG-TS 解码为单独的 NAL 单元
- 独立的 NAL 单元由 Broadway 或 Prism 解码,输出到画布
我正在使用这个 FFMpeg 命令:
ffmpeg -f v4l2 -i /dev/video0 -r 15 -c:v h264_nvenc -pix_fmt yuv420p -b:v 500k -profile:v baseline -tune zerolatency -f mpegts - | nc -l -p 8084 127.0.0.1
问题是我得到的 NAL 单元是类型 9(或者可能是 6?),这是 javascript 正在接收的 NAL 单元之一的标头,采用 Base64 和二进制格式:
echo "AAAAAQnwAAAAAQYBBAAECBCAAAAAAWHg" | base64 -d | xxd -b
00000000: 00000000 00000000 00000000 00000001 00001001 11110000 ......
00000006: 00000000 00000000 00000000 00000001 00000110 00000001 ......
0000000c: 00000100 00000000 00000100 00001000 00010000 10000000 ......
00000012: 00000000 00000000 00000000 00000001 01100001 11100000 ....a.
Broadway 和 Prism 都不支持这些 NAL 单元类型。如何将 FFMpeg 配置为仅输出类型 1、5、7 和 8 的 NAL 单元?
编辑:我也尝试了以下命令:
ffmpeg -f v4l2 -i /dev/video0 -r 15 -c:v h264_nvenc -pix_fmt yuv420p \
-b:v 500k -profile:v baseline -tune zerolatency \
-movflags frag_keyframe+empty_moov -g 52 -f mp4 - \
| nc -l -p 8084 127.0.0.1
它编码为 mp4,然后我尝试从三个零字节开始解析 NAL 单元。这些行看起来都类似于以下内容:
echo "AAAACAYBBABOCBCAAAARemHk4f8df1Su" | base64 -d | xxd -b
00000000: 00000000 00000000 00000000 00001000 00000110 00000001 ......
00000006: 00000100 00000000 01001110 00001000 00010000 10000000 ..N...
0000000c: 00000000 00000000 00010001 01111010 01100001 11100100 ...za.
00000012: 11100001 11111111 00011101 01111111 01010100 10101110 ....T.
即类型 6(第 5 个字节中的 00110),仍然不是所需的 NAL 单元类型。
更新:它对我不起作用的原因是 Javascript 中字符和字节之间的编码/解码问题。我已将working code on github 提供给其他可能想做类似事情的人。
关于 NAL 单元,事实证明 FFMpeg 输出的原始视频包含只有几个字节的类型 6,然后是具有帧数据的类型 1。类型 6 可以丢弃。感谢 cmets 并接受了对此的洞察力。
【问题讨论】:
-
这些是 MPEG-TS 所需的访问单元分隔符 NALU。由于您的解码器不支持它们,因此您需要将它们去掉。
-
或输出并使用原始 H264 比特流。
-
@Gyan 这些是流中唯一的数据包,没有其他类型。但是,我确实注意到,在标头 6 个字节之后,标头似乎又开始了,作为类型 6?我对这个了解不够。如果它们都是 9 型或 6 型,我该如何进行剥离?
-
@Gyan 我已经尝试在没有 MPEG-TS 解复用器的情况下使用
... -f h264 - | nc ...使用原始 264 流,但是,这也不是开箱即用的,因此它可能不包含正确的类型(我可能需要仔细检查)。它应该适用于-f mp4,但不适用于流式传输。 -
您可以使用
-movflags +empty_moov流式传输mp4
标签: ffmpeg video-streaming h.264