为什么 FFMpeg 输出错误的 NAL 单元类型? (javascript h264 直播)

Why is FFMpeg outputting wrong NAL unit types? (javascript h264 livestream)

我正在尝试使用 h264 编码在浏览器中设置直播,其中 javascript 解码 h264 帧并将其绘制在 Canvas-element 上(或使用 WebGL)。

Broadway 和 Prism 都实现了对类型 1、5、7 和 8 的 NAL 单元的解码。

我目前的设置如下:

我正在使用这个 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 单元之一的 header,在 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 中字符和字节之间的 encoding/decoding 问题。我已经为可能想要做类似事情的其他人设置了 working code on github

关于 NAL 单元,事实证明,FFMpeg 输出的原始视频包含只有几个字节的类型 6,然后是具有帧数据的类型 1。类型 6 可以丢弃。感谢评论和接受的答案,以便深入了解这一点。

"jsmpeg library decodes MPEG-TS into separate NAL units"中有一个误解,因为它真的将传输流解码为PES数据包。 PES 数据包可以包含 多个 NAL 单元

删除访问单元定界符很容易,因为它们实际上只有一个字节长。所以你可以跳过 0x0000000109f0(从你的第一个转储)并处理偏移量 6 处的下一个 NAL 单元。

那个是6型,意思是补充增强信息。它也需要被跳过,因为你的解码器不支持它(它不是解码所必需的)。 SEI NAL 单元通常也很短,大约 10-50 字节。所以只要寻找下一个起始码 0x00000001...