我通过JavaScript中的MPEG-TS传输来生成MP4文件(具有h.264视频和AAC音频),以通过blob URL在浏览器中播放。在Chrome中一切正常,如果我从开发者控制台中获取blob URL并下载它们,那么生成的文件也可以在Windows Media Player上正常运行。然而,Firefox声称它们已损坏。
我已将问题缩小到音频元数据中ESDS框的问题。如果我通过其他方式(如ffmpeg)重新打包源MPEG-TS文件,并在十六进制编辑器中手动编辑我生成的文件,以便从其他软件生成的等效文件粘贴到ESDS框中,那么Firefox很高兴。 / p> 构建ESDS框的
我试图通过一个非常简单的转录 - 来自MPEG规范的过程来编写它,但这并不能保证我没有搞砸它。由于Chrome和Windows Media播放我的文件很好,我不确定我的文件中是否真的是一个错误,它们在某种程度上无法忽略,或者它是否与Firefox有关。我怀疑前者,但我不确定。
对于如何构建合适的ESDS盒子,任何人都有任何见解,或者可能是一个简单易懂的参考资料?
编辑:以下是针对同一输入文件生成的一些不同的ESDS部分(作为十六进制字节,从我的十六进制编辑器中复制):
我是: 00 00 00 27 65 73 64 73 00 00 00 00 03 22 00 00
02 04 14 40 15 00 00 00 00 00 3a f1 00 00 2d e6
05 02 12 10 06 01 02
00 00 00 33 65 73 64 73 00 00 00 00 03 80 80 80
22 00 02 00 04 80 80 80 14 40 15 00 00 00 00 00
00 00 00 00 00 00 05 80 80 80 02 12 10 06 80 80
80 01 02
ffmpeg:
00 00 00 2c 65 73 64 73 00 00 00 00 03 80 80 80
1b 00 02 00 04 80 80 80 0d 40 15 00 00 00 00 01
5f 42 00 00 00 00 06 80 80 80 01 02
奇怪的是,我之前没有注意到这一点,Firefox将使用ffmpeg的输出播放视频,但Firefox和Windows Media都不会实际播放声音(Chrome确实如此)。不过,Firefox和Windows Media都很乐意使用mpegts的输出来播放带声音的视频。有了我的,Chrome和Windows Media将播放带声音的视频,但Firefox根本不播放,并声称视频已损坏。
答案 0 :(得分:1)
好吧,我找到了自己问题的答案。在思考我的ESDS盒与其他软件产生的差异之后,最明显的差异是这些0x80填充字节的存在 - 其中三个在每个ES Descriptor标签号之后。添加这些内容,其他大多数内容都排成一行,看起来几乎相同。
我在MP4文件或ISOBMFF的MPEG规范中没有提到为什么那些字节应该存在,但添加它们使它工作 - Firefox不再认为文件已损坏。
答案 1 :(得分:1)
您现在已经通过在ES描述符标记号后面添加三个字节0x80 来找到您的解决方案。很高兴为所有浏览器解决了问题。
让我分享一些可以帮助您或您未来的代码用户的见解:
" ..我在MPEG规范中没有提到MP4文件或ISOBMFF 为什么那些字节应该在那里,但添加它们使它工作.."
仔细查看mp4ESDSbox.java的这个链接,我们看到ESDS原子分为五个部分,每个部分都填充了字节80 80 80
。这三个字节被描述为"可选的扩展描述符类型标记字符串" ,可能的类型值为.. 80 或 81 或 FE
你是在正确的道路上,但你只填充了第一部分。
MP4Muxer.js
:(A)您目前拥有的......
00 00 00 27 65 73 64 73 00 00 00 00 03 80 80 80
22 00 00 02 04 14 40 15 00 00 00 00 00 3A F1 00
00 2D E6 05 02 12 10 06 01 02
MP4Muxer.js
:(B)应该是什么......
00 00 00 33 65 73 64 73 00 00 00 00 03 80 80 80
22 00 00 02 04 80 80 80 14 40 15 00 00 00 00 00
3A F1 00 00 2D E6 05 80 80 80 02 12 10 06 80 80
80 01 02
FFMpeg ESDS for random AAC track
:与新(B)版本进行比较
00 00 00 33 65 73 64 73 00 00 00 00 03 80 80 80
22 00 01 00 04 80 80 80 14 40 15 00 00 00 00 01
F4 74 00 01 F4 74 05 80 80 80 02 12 10 06 80 80
80 01 02
将版本B的字节结构与FFMpeg的字节结构进行比较,我们现在看到有完美的对齐方式。有些值略有不同,因为它们不是来自相同的音频数据。
注意我们已经将原来的x33
的前四个字节(大小整数)更改为x27
(十进制= = 51字节长度),这是(十进制= = 39字节长度)
答案 2 :(得分:1)
0x80字节不属于它之前的标签,而是属于它之后的长度值。 ISO规范的版本2更改了长度值的解释,因此可以通过将其设置为“ VarInt32”类型来包装超过255个字节。每个字节中的高位表示后面还有另一个长度字节,低7位对值进行编码。
您可以使用它来编码任意大值,但是ISO规范将此值限制为最多4个字节,即0 ... 2 ^(4 * 7)-1。
即:
0x80,0x80,0x80,0x0E = 0x80,0x0E = 0x0E => 14
0x80,0x80,0x84,0x7f = 0x84,0x7f => 0x4 << 7 + 0x7f = 0x27f = 639
例如,相同的编码由Google的protobuf使用,名为Base128 Varint。