介绍 Thumbcoil
一个转封装器(transmuxer)获取包含在某种文件格式中的媒体,从中提取原始的压缩视频和音频(这个过程称为解复用),然后将压缩数据重新打包成另一种格式(称为重复用),而无需进行任何重新压缩。
最初
在构建 Mux.js——作为 videojs-contrib-hls 核心的转封装器——时,我们面临一个问题:如何确定 Mux.js 的输出是否正确?
早期,我们设法弄清楚如何诱导 FFmpeg 从 MPEG2-TS 片段创建 MP4,使其能够在支持 媒体源扩展 (MSE) 的浏览器中播放,当时这意味着只有 Chrome。然而,我们需要一种简单的方法来比较我们的转封装器与 FFmpeg 产生的输出。由于这两种输出极不可能字节完全相同,因此比较必须了解 MP4 格式。
MP4 文件由Box组成——它们是分层的逻辑单元,方便的是,都以32位长度和32位Box类型开始。Box通常会包含其他子Box。
解决这个问题的答案是构建一个“MP4 检测器”——一个能够解析 MP4 并显示所有相关 Box 及其内容的 JSON 式转储的工具。通过生成 Mux.js 输出的转储,并将其与 FFmpeg 生成的已知良好片段进行比较,我们可以看到我们的转封装器的输出在哪里不同。
“MP4 检测器”被构建成一个网页,这样我们可以得到两个片段的图形化颜色编码差异。随着时间的推移,该页面增加了一个视频元素,我们开始将转封装片段的结果直接附加到视频元素的 MediaSource 中,以帮助即时反馈和验证对 Mux.js 的更改。
一个勇敢的新世界
像 MP4 这样的媒体容器封装了视频和音频流。它包含描述流的元数据、每个帧的时序信息以及流数据本身。
随着开发的继续,我们有时会遇到以新的、有趣的方式失败的流。其中一些失败,无可否认,是由于 Mux.js 中的错误。随着 Mux.js 本身变得更加健壮,失败越来越多地是由流本身的问题或 MSE 规范 的特定实现引起的问题。
我们最终意识到,我们确实需要更多地了解这些视频内部发生的事情。我们不仅需要了解媒体容器层面发生的情况,还需要深入了解——我们需要查看视频数据本身。为此,我们创建了 Thumbcoil。
在容器内部,视频和音频包含在名为比特流的数据中。比特流是编码器为表示音频信号或视频帧而产生的数据。一些常见的比特流有用于音频的 AAC 和用于视频的 H.264。
Thumbcoil
Thumbcoil 是一套工具,旨在让您深入了解包含在 MP4 或 MPEG2-TS 容器文件中的 H.264 视频比特流的内部结构。使用 Thumbcoil 中的工具,您可以详细查看两种支持的媒体容器格式的内部结构。
此外,这些工具能够向您展示构成 H.264 比特流的最重要 NAL 单元中包含的信息。您是否曾好奇视频编码器为解码器保留了哪些秘密信息?现在,有了 Thumbcoil,您终于可以亲眼看到了!
动机
H.264 编码的比特流由所谓的 NAL(网络抽象层)单元组成。NAL 是一种简单的包格式,旨在尽可能高效地使用比特。
信不信由你,目前很少有好的工具能够以某种图形化方式显示媒体容器的结构及其包含的数据。调试视频播放问题通常是一项繁琐的任务,涉及各种深奥的 FFmpeg 和 FFprobe 命令。不幸的是,FFprobe 即使在最佳状态下也只能打印出我们感兴趣的一小部分数据。
例如,各种参数集内部的精确数据无法通过命令行获取。在 FFprobe 内部,这些数据被解析和存储,但没有简单的方法以人类可读的形式转储这些信息。
在 H.264 中,有两种特殊类型的 NAL 单元——SPS 或序列参数集(seq_parameter_set)和 PPS 或图像参数集(pic_parameter_set)。这两种 NAL 单元包含大量信息。解码器需要这些信息来重建视频。
Thumbcoil 不仅极其详细地提供了参数集信息,而且还将其信息与其周围的上下文(它所包含的 Box 或它所指定的帧)保持在一起。这种上下文对于理解流中的问题或特殊性通常非常重要。
基于高级技术构建
Thumbcoil 解析参数集的一个更有趣的地方在于,它为每种 NAL 单元类型构建了内部称为“编解码器”的东西。这些编解码器本质上是使用一种高级的解析器组合子式的设置来指定的。
两个参数集中的大部分数据都使用一种称为指数哥伦布编码(exponential-golomb encoding)的方法存储。该方法使用可变数量的比特来存储数字,特别适用于倾向于较小的值。
用于构建编解码器的每个函数都返回一个包含两个函数(解码和编码)的对象。这意味着我们可以只指定一次序列参数集 NAL 单元的格式,然后就可以对该特定 NAL 单元的比特流进行解析和写入。
用于指定 NAL 单元编解码器的“语法”与 H.264 规范(ISO/IEC 14496-10)中使用的语法非常相似。Thumbcoil 中编解码器理解的数据类型,在进行了一些扩展后,仅仅是规范中定义的相同类型,例如有符号和无符号的指数哥伦布编码整数。
除了参数集,Thumbcoil 还通过解析 slice_header 数据,提供了对切片层本身结构的深入洞察,尽管我们没有进一步解析任何实际的 slice_data,因为当你深入到那种复杂性中时,事情会迅速变得更加困难且用处不大。
那这个名字有什么来头?
“Thumbcoil”其实没有任何意义。它是一个内部笑话,只有世界上三个人(包括我自己)觉得好笑。这个奇怪的名字确实有一个好处,那就是它构成了一个简短且易于记忆的域名:thumb.co.il。
与所有 Video.js 项目一样,Thumbcoil 是开源软件,我们欢迎在 https://github.com/videojs/thumbcoil 提出建议、问题和贡献。