在互联网常见的格式中,跨平台最好的应该就属MP4文件了。因为MP4文件既可以在PC平台的Flashplayer中播放,又可以在移动平台的Android、iOS等平台中进行播放,而且使用系统默认的播放器即可以播放。
MP4格式是最常见的多媒体文件格式。
一、MP4 格式标准介绍
MP4格式标准为ISO-14496 Part 12、ISO-14496 Part 14,标准内容不是很多,下面我们来介绍一下格式标准中一些重要的信息。
MP4是一种描述较为全面的容器格式,被认为可以在其中嵌入任何形式的数据,各种编码的视频、音频等都不在话下,常见的大部分的MP4文件存放的AVC(H.264)或MPEG-4(Part 2)编码的视频和AAC编码的音频。MP4格式的官方文件后缀名是“.mp4”,还有其他的以mp4为基础进行的扩展或者是阉割版的格式,如:M4V, 3GP, F4V等。
MP4是由一个个“Box”组成的,大Box中存放小Box,一级嵌套一级来存放媒体信息。下面我们来楚关于Box的几个概念:
- MP4文件由许多个Box与FullBox组成。
- 每个Box由Header和Data两部分组成。
- FullBox是Box的扩展,其在Box结构的基础上,在Header中增加8位version标志和24的flags标志。
- Header包含了整个Box的长度的大小(size)和类型(type),当size等于0时,代表这个Box是文件的最后一个Box。当size等于1时,说明Box长度需要更多的位来描述,在后面会自定义一个64位的largesize用来描述Box的长度。当type等于uuid时,说明这个Box中的数据是用户自定义扩展类型。
- Data为Box的实际数据,可以是纯数据,也可以是更多的子Box。
- 当一个Box中Data是一系列的子Box时,这个Box又可以称为Container(容器)Box。
MP4常用参考标准Box排列方式:https://github.com/renhui/Thinking-in-AV/tree/master/多媒体格式/MP4。
介绍了MP4的格式标准后,下面我们来介绍是三个MP4分析工具,为后续理解MP4文件一些关键信息做辅助工具。
二、MP4分析工具
可以用来分析MP4封装格式的工具比较多,除了FFmpeg、FFprobe之外,还有一些常用的工具,如Elecard StreamEye、mp4box、mp4info等;下面简单介绍一下这几款常用的工具:
1. Elecard StreamEye
Elecard StreamEye是一款非常强大的视频信息查看工具,能够查看帧的排列信息,将I帧、P帧、B帧以不同颜色的柱状展现出来,而且柱的长短将根据帧的大小展示。还能够通过Elecard StreamEye分析MP4的封装的内容信息,包括流信息、宏块的信息、文件头顶额信息、图像的信息以及文件的信息等。还能根据每一帧的顺序逐帧查看,可以看到每一帧的详细信息与状态。
示例如图:
2. mp4box
mp4box 是GPAC项目中的一个组件,可以通过mp4box针对媒体文件进行合成、拆解等操作。
官网地址:https://gpac.wp.imt.fr/mp4box/。
其使用时的常用命令如下:
1) mp4box -h 查看mp4box中的所有帮助信息 2) mp4box -h general 查看mp4box中的通用帮助信息 3) mp4box -info test.mp4 查看test.mp4文件是否有问题 4) mp4box -add test.mp4 test-new.mp4 修复test.mp4文件格式不标准的问题,并把新文件保存在test-new.mp4中 5) mp4box -inter 10000 test-new.mp4 解决开始播放test-new.mp4卡一下的问题,为HTTP下载快速播放有效,10000ms 6) mp4box -add file.avi new_file.mp4 把avi文件转换为mp4文件 7) mp4box -hint file.mp4 为RTP准备,此指令将为文件创建RTP提示跟踪信息。这使得经典的流媒体服务器像darwinstreamingserver或QuickTime的流媒体服务器通过RTSP/RTP传输文件 8) mp4box -cat test1.mp4 -cat test2.mp4 -new test.mp4 把test1.mp4和test2.mp4合并到一个新的文件test.mp4中,要求编码参数一致 9) mp4box -force-cat test1.mp4 -force-cat test2.mp4 -new test.mp4 把test1.mp4和test2.mp4强制合并到一个新的文件test.mp4中,有可能不能播放 10) mp4box -add video1.264 -cat video2.264 -cat video3.264 -add audio1.aac -cat audio2.aac -cat audio3.aac -new muxed.mp4 -fps 24 合并多段音视频并保持同步 11) mp4box -split *time_sec* test.mp4 切取test.mp4中的前面time_sec秒的视频文件 12) mp4box -split-size *size *test.mp4 切取前面大小为size KB的视频文件 13) mp4box -split-chunk *S:E* test.mp4 切取起始为S少,结束为E秒的视频文件 14) mp4box -add 1.mp4#video -add 2.mp4#audio -new test.mp4 test.mp4由1.mp4中的视频与2.mp4中的音频合并生成
而通过mp4box也可以查看mp4的信息,其输出内容格式非常类似ffprobe查看的信息,不过想对ffprobe更完善。
3. mp4info
mp4info是一个不错的MP4分析工具,而且是可视化的工具,可以将MP4中的各个Box解析出来,并将其中的数据展现出来。分析MP4文件内容时使用mp4info将会更方便。
结合着此工具,理解MP4的Box会更方便,更直观。
三、MP4格式重要Box
1. ftyp(File Type Box)
该Box有且只有1个,并且只能被包含在文件层,而不能被其他Box包含。该Box应该被放在文件的最开始,指示该MP4文件应用的相关信息。
“ftyp” body依次包括1个32位的major brand(4个字符),1个32位的minor version(整数)和1个以32位(4个字符)为单位元素的数组Compatible Brands。
2. moov(Movie Box)
该box包含了文件媒体的metadata信息,“moov”是一个container box,具体内容信息由子box诠释。同File Type Box一样,该box有且只有一个,且只被包含在文件层。一般情况下,“moov”会紧随“ftyp”出现。
moov定义了一个MP4文件中的数据信息,类型是moov,是一个容器Atom,其至少必须包含一下三种Atom中的一种:mvhd标签、cmov标签、rmra标签。
- mvhd标签:Movie Header Atom,存放未压缩过的影片信息的头容器。
- cmov标签:Compressed Movie Atom,压缩鬼哦的电影信息容器,此容器不常用。
- rmra标签:Reference Movie Atom,参考电影信息容器,此容器不常用。
一般情况下,“moov”中会包含1个“mvhd”和若干个“trak”。其中“mvhd”为Header Box,一般作为“moov”的第一个子Box出现(对于其他Container Box来说,Header Box都应作为首个子box出现)。“trak”包含了一个track的相关信息,是一个Container Box。
3. trak(Track Box)
“trak”也是一个container box,其子box包含了该track的媒体数据引用和描述(hint track除外)。一个MP4文件中的媒体可以包含多个track,且至少有一个track,这些track之间彼此独立,有自己的时间和空间信息。“trak”必须包含一个“tkhd”和一个“mdia”,此外还有很多可选的box(略)。其中“tkhd”为track header box,“mdia”为media box,该box是一个包含一些track媒体数据信息box的container box。
4. mdat(Meida Data Box)
该box包含于文件层,可以有多个,也可以没有(当媒体数据全部为外部文件引用时),用来存储媒体数据。数据直接跟在box type字段后面,具体数据结构的意义需要参考metadata(主要在sample table中描述)。
5. free或skip(Free Space Box)
“free”中的内容是无关紧要的,可以被忽略。该box被删除后,不会对播放产生任何影响。
6. stbl(Sample Table Box)
“stbl”几乎是普通的MP4文件中最复杂的一个box了,首先需要回忆一下sample的概念。sample是媒体数据存储的单位,存储在media的chunk中,chunk和sample的长度均可互不相同,如下图所示。
普通MP4文件的结构重要的部分就讲完了,理解起来可能比较乱,下面这张图是常见的box的树结构图,可以用来大致了解MP4文件的构造。
在MP4文件中,Box的结构与上图中所描述的一般没太大的差别。
四、MP4格式 与 FFmpeg实战
1. 在FFmpeg中的输出MP4的Demuxer信息
使用命令行 ffmpeg -h demuxder=mp4 查看MP4文件的Demuxer信息:
Demuxer mov,mp4,m4a,3gp,3g2,mj2 [QuickTime / MOV]:
Common extensions: mov,mp4,m4a,3gp,3g2,mj2.
2. 通过FFmepg faststart参数的使用,来理解mdat和moov的顺序的意义
正常情况下,ffmpeg生成的moov是在mdat写完成后再写入的。
下面是一个例子:
ffmpeg -i 好汉歌.flv -c copy -f mp4 好汉歌.mp4
使用mp4info查看容器出现的顺序,如图:
可以看出moov box是在mdat的下面。这时,我们可以使用faststart将上图的moov移动到mdat前面。
使用如下命令行:
ffmpeg -i 好汉歌.flv -c copy -f mp4 -movflags faststart 好汉歌.mp4
然后使用mp4info查看MP4的容器顺序,就可以看到moov被移动到mdat前面了。如下图所示:
因为MP4的标准中描述的moov与mdat的存放位置前后并没有强制要求,所有有些时候moov这个Box在mdat的后面,有时候在mdat的前面。
在互联网的视频点播中,如果希望MP4文件被快速打开,则需要moov存放在mdat的前面;如果放在后面,则需要将MP4文件下载完成后才可以进行播放。