MP4 文件是一种基于 ISO/IEC 14496-12 (MPEG-4 Part 12) 定义的多媒体容器格式,也称为 ISO Base Media File Format (ISOBMFF) 。它可以包含音频、视频、字幕等多种流,并使用不同的编码格式压缩存储这些内容。MP4 文件格式使用称为 盒子(box) 或 原子(atom) 的层次结构,每个盒子包含特定类型的信息。
MP4 文件格式结构
MP4 文件是由多个 盒子 (Box)组成的,每个盒子包含不同的信息。这些盒子可以嵌套,每个盒子都有一个 4 字节的标识符(通常是4个ASCII字符,如 ftyp
、moov
)。盒子的结构大体如下:
rust
[box size] [box type] [box data]
- box size:盒子的大小,包括所有内容。
- box type:盒子的类型(4 字节字符)。
- box data:盒子的数据内容,依赖于盒子的类型。
常见的 MP4 盒子类型及其作用
以下是 MP4 文件中常见的盒子及其功能:
1. ftyp
(File Type Box)
- 这是 MP4 文件的头部盒子,描述文件格式的兼容性和版本。
- 它包含 MP4 文件所使用的品牌(格式类型)以及所支持的兼容品牌。
- 常见的兼容品牌有
isom
(ISO Base Media)、mp41
(MP4 v1)、mp42
(MP4 v2)等。
2. moov
(Movie Box)
-
存放媒体元数据的盒子。所有和媒体信息相关的元数据(视频、音频的时间戳、样本表等)都存储在这个盒子内。
-
这个盒子是解析 MP4 文件的关键。
-
moov
盒子通常由多个子盒子组成:-
mvhd
(Movie Header Box) :包含整个媒体文件的全局信息,比如时间长度和时间单位。 -
trak
(Track Box) :每个trak
盒子描述一个媒体轨道(如视频、音频、字幕)。每个trak
盒子又包含:-
tkhd
(Track Header Box) :包含该轨道的标头信息,比如轨道ID、宽高、时间等。 -
mdia
(Media Box) :描述该轨道的媒体信息,包括媒体类型、解码时间等。 -
mdhd
(Media Header Box) :该轨道的时间基(timescale)、持续时间(duration)等信息。 -
minf
(Media Information Box) :存储与该轨道的媒体数据相关的信息,具体的解码、合成、播放等。stbl
(Sample Table Box) :包含该轨道的样本表,帮助定位和解析样本数据(如视频帧、音频帧)。
-
-
3. mdat
(Media Data Box)
- 存储实际的音视频数据。所有媒体数据(例如视频帧、音频帧)都保存在这个盒子中。
mdat
盒子可能会非常大,因为它存储了所有的实际媒体内容(如音频流、视频帧)。- 它的内容通常与
moov
盒子中的元数据相对应。例如,moov
中的样本表会指向mdat
中的实际数据位置。
4. free
和 skip
(Free Space Boxes)
- 这些盒子通常用于占位,它们不存储实际的数据,只是为了方便文件调整大小或进行编辑操作。
5. udta
(User Data Box)
- 这是用户定义的数据区,可以包含一些额外的信息,比如版权信息或其他自定义数据。
6. mvex
(Movie Extends Box)
- 在分段 MP4 文件中,
mvex
盒子用来支持片段式播放。
7. moof
(Movie Fragment Box)
- 这是用于分段播放的 MP4 文件结构的一部分。与
moov
类似,但moof
盒子用于描述文件的分段部分。
8. stbl
(Sample Table Box)
-
存储有关如何访问
mdat
中的媒体数据的信息,包括:stts
(Time to Sample Box) :存储时间戳信息,用于将解码时间戳 (DTS) 转换为展示时间戳 (PTS)。stsc
(Sample to Chunk Box) :说明样本如何分块。stsz
(Sample Size Box) :说明每个样本的大小。stco
或co64
(Chunk Offset Box) :提供块在mdat
中的偏移量。
9. ctts
(Composition Time to Sample Box)
- 提供样本的 CTS(Composition Time Stamp,合成时间戳)信息,帮助正确同步视频播放。
- 它将 DTS(解码时间戳)转换为 PTS(展示时间戳),用于处理视频帧的顺序。
10. sidx
(Segment Index Box)
- 在分段 MP4 文件中,
sidx
盒子包含分段信息,用于 DASH(动态自适应流式传输)等技术。
常见时间戳:CTS 和 DTS
在 MP4 文件中,视频和音频流中的每个帧都有两个时间戳:
- DTS(Decoding Time Stamp,解码时间戳) :指示解码器何时应该解码这一帧。DTS 用于处理帧的解码顺序。
- CTS(Composition Time Stamp,合成时间戳) :指示这一帧在时间轴上的实际展示时间。CTS 用于播放顺序。
帧可以按照 DTS 的顺序被解码,但它们按照 CTS 的顺序被展示。这在视频中帧间重排时尤为重要(例如使用 B-帧的场景)。
盒子总括
javascript
BASIC_BOXES: [ "mdat", "idat", "free", "skip", "meco", "strk" ],
FULL_BOXES: [ "hmhd", "nmhd", "iods", "xml ", "bxml", "ipro", "mere" ],
CONTAINER_BOXES: [
[ "moov", [ "trak", "pssh" ] ],
[ "trak" ],
[ "edts" ],
[ "mdia" ],
[ "minf" ],
[ "dinf" ],
[ "stbl", [ "sgpd", "sbgp" ] ],
[ "mvex", [ "trex" ] ],
[ "moof", [ "traf" ] ],
[ "traf", [ "trun", "sgpd", "sbgp" ] ],
[ "vttc" ],
[ "tref" ],
[ "iref" ],
[ "mfra", [ "tfra" ] ],
[ "meco" ],
[ "hnti" ],
[ "hinf" ],
[ "strk" ],
[ "strd" ],
[ "sinf" ],
[ "rinf" ],
[ "schi" ],
[ "trgr" ],
[ "udta", ["kind"] ],
[ "iprp", ["ipma"] ],
[ "ipco" ],
[ "grpl" ],
[ "j2kH" ],
[ "etyp", [ "tyco"] ]
],
如何解析?
- 使用ffmpeg
- js中可以使用MP4box.js解析gpac.github.io/mp4box.js/t... (裂墙推荐这个库 很牛回复问题也很快。js中学习MP4的必备库)
总结
比较棘手,但是需要一点一点吃透,才能是前端音视频入门。