随着数字媒体的迅速发展,视频成为人们生活中不可或缺的一部分。MP4(Moving Picture Experts Group 4)作为一种常见的视频文件格式,被广泛应用于各种领域,包括电视、电影、广告和网络媒体等。然而,有时我们需要对MP4文件进行裁剪,以满足特定的需求,例如提取出一部电影中的某个片段,或者创建个性化的视频内容。
深入理解MP4文件裁剪原理,不仅可以帮助我们更好地理解MP4文件的内部结构和编码方式,还能够为我们提供有效的工具和技术,使我们能够准确、高效地进行MP4文件的裁剪操作。本文将通过介绍MP4文件的基本概念和组织结构,来详细解释MP4文件裁剪的原理和方法。
本文涉及的对MP4视频文件的裁剪只涉及MP4的封装层的内容,而不涉及CODEC层的音视频解码和编码的内容,裁剪完成后,不会对视频的画质有任何影响。
MP4的文件结构规范在ISO/IEC 14496-12标准中进行定义。以下是结合自己的理解,对MP4格式进行说明。 MP4文件以box(也叫做atom)作为基本单位来组织的,一个MP4本身是一个大的box,每个box又可以嵌套其他子box,形成一种大盒套小盒的套娃结构。
MP4包括两种box格式,一种是32位box格式,如图1,另外一种是64位box格式,如图2。当box的前面4个字节的32位整型值是1的时候,表示这是一个64位的box格式,另外用从第8到第15字节共8个字节表示box的大小,其他和32位box的格式是一样的。以下对各个部分进行说明:
在规范中,将带有version和flags两个字段的box称为fullbox,是不是fullbox是依赖于box的类型的,譬如mvhd box就是一个fullbox,而ftyp则不是一个fullbox。
图1 图2
2.1 MP4文件格式架构
从MP4文件的顶层来看,一般如下图3或者下图4所示,包括ftype、free、moov、mdat四种box。其中mdat和moov box的顺序可以颠倒,而free box则不是必须的。
图3 图4
下图是一个典型的MP4文件的整体架构,如下图5:
图5
在进行mp4裁剪的时候,我们主要关心的是对moov box中的内容,需要对它内部的box进行裁剪,调整索引等操作,特别是途中标出来的stbl box下面的那些box,另外就是对mdat按照裁剪需求将不需要的音视频帧进行丢弃。
下图6显示了两个trak的音视频帧的组织架构:
图6
其中trak1包含了4个chunk,每个chunk又包含数量不定的sample(即音视频帧), 而trak2包含了5个chunk,每个chunk也包含了数量不定的sample。
最终,各个trak的chunk会被interlace即交错排列存放到mat box中,这样有助于播放器按顺序读取并进行解码,而不需要同步播放不同的trak的时候,要在MP4文件中不断来回跳转。
经过interlace后,最后排列在mdat中的顺序可能如下图7所示:
图7
从上图可以看到,trak1和trak2的chunk已经被交错排列了。MP4采用chunk+sample的两层结构,虽然一定程度上增加了复杂性,但是有助于stbl中的数据压缩。
下面对裁剪过程中需要处理的box的格式进行重点说明,以下各个box的标题中,凡是标了*的都是需要在裁剪过程中进行调整的box,而没有标*的则只要将原来的内容直接拷贝输出即可。
ftyp body依次包括1个32位的major brand(4个字符)、1个32位的minor version(整数)和1个以32位(4个字符)为单位元素的数组compatible brands。对于mp4裁剪的需求,ftyp box基本上不需要太关心,只要复制原有的内容即可。
free box就是一个空的box,它的名字可以是free或者是skip,发现这个box,是可以直接跳过的。free box的作用包括:
free box在裁剪的过程中也基本上不用关心,只要复制原有的内容即可。
mdat box包含的就是音视频数据,而要访问mdat中的音视频数据,又必须通过moov box中记录的帧的偏移和大小来,才能读取该帧在mdat中音视频帧的数据。mdat box的格式也很简单,如下图8:
图8
图8列出了mdat的两个版本,分别对应32位box和64位box。mdat box需要根据需求对帧数据进行裁剪,重新组织出一个裁剪后的新的mdat box。
3.4 moov box*
moov box本身是一个容器,它包括其他子box。如下图9:
图9
moov box本身很简单,需要关注的是它的子box,而且由于它的子box可能会被裁剪而改变原始的大小,所以moov box本身的大小在裁剪后也需要跟着调整。
mvhd box是一个full box,即带有version和flags字段。详细结构如下图10,图11。
图10 图11
根据version字段的值的不同,用于表示时间的create_time、modification_time和duration三个字段可以是32位的或者是64位的,当version=0时,采用32位的版本,而当version!=0时,采用64位版本。 在裁剪MP4的时候,因为视频变短了,我们需要调整这个duration字段,调整duration字段的时候需要关注timescale设置的时间单位,将调整后的duration字段要变换为timescale规定的时间单位。
trak box本身是一个容器,它包括其他子box。如下图12:
图12
trak box本身很简单,需要关注的是它的子box,而且由于它的子box可能会被裁剪而改变原始的大小,所以trak box本身的大小在裁剪后也需要跟着调整。
在mp4文件中,每条音频或者视频流会对应一个 trak。
trak box本身很简单,需要关注的是它的子box,而且由于它的子box可能会被裁剪而改变原始的大小,trak box本身的大小在裁剪后也需要跟着调整。
tkhd box描述了trak的详细信息。tkhd box是一个full box,即带有version和flags字段。详细结构如下图13,图14。
图13 图14
根据version字段的值的不同,用于表示时间的create_time、modification_time和duration三个字段可以是32位的或者是64位的,当version=0时,采用32位的版本,而当version!=0时,采用64位版本。 在裁剪MP4的时候,因为视频变短了,我们需要调整这个duration字段,调整duration字段的时候需要关注mvhd box中的timescale设置的时间单位,将调整后的duration字段要变换为timescale规定的时间单位。
mdia box本身是一个容器,它包括其他子box。如下图15:
图15
mdia box本身很简单,需要关注的是它的子box,而且由于它的子box可能会被裁剪而改变原始的大小,mdia box本身的大小在裁剪后也需要跟着调整。
mdhd box描述了与媒体无关且与trak中媒体特性相关的总体信息。mdhd box是一个full box,即带有version和flags字段。详细结构如下图16,图17。
图16 图17
根据version字段的值的不同,用于表示时间的create_time、modification_time和duration三个字段可以是32位的或者是64位的,当version=0时,采用32位的版本,而当version!=0时,采用64位版本。
在裁剪MP4的时候,因为视频变短了,我们需要调整这个duration字段,调整duration字段的时候需要关注box中的timescale设置的时间单位,将调整后的duration字段要变换为timescale规定的时间单位。
3.10 hdlr box
hdlr box解释了媒体的播放过程信息,用来设置不同Track的处理方式,标识了该Track的类型,音频Track的handler为soun,视频Track的handler为video。对于MP4的裁剪来说不需要处理,直接拷贝即可。
minf box本身是一个容器,它包括其他子box。如下图18:
图18
minf box本身很简单,需要关注的是它的子box,而且由于它的子box可能会被裁剪而改变原始的大小,minf box本身的大小在裁剪后也需要跟着调整。
视频trak使用vmhd box来描述展示信息。这个box的内容在裁剪操作的时候不用关心,直接拷贝即可。
音频trak使用smhd box来描述展示信息。这个box的内容在裁剪操作的时候不用关心,直接拷贝即可。
dinf box是一个容器,包括一个或者多个子dref box,但是这个box的内容在剪裁操作的时候不用关心,所以也就不用解析其子dref box,直接拷贝即可。
stbl box本身很简单,需要关注的是它的子box,而且由于它的子box可能会被裁剪而改变原始的大小,stbl box本身的大小在裁剪后也需要跟着调整。
本box用来描述媒体轨道中每个样本的编解码器和参数。STSD Box包含了一个或多个Sample Entry,每个Sample Entry描述了一个媒体样本的编解码器和参数。STSD Box的作用是提供有关媒体样本的编解码器和参数的信息,以便解码器和播放器能够正确地解码和呈现媒体数据。通过解析STSD Box中的Sample Entry,可以了解媒体样本的格式和编码类型,从而选择正确的解码器和解码参数,以实现媒体的播放和展示。譬如存放H264的sps/pps帧的信息。
对于MP4文件的裁剪操作,这里不需要关心这个帧的内容,直接拷贝即可。
<未完待续>