之前介绍过多媒体文件格式剖析:MP4篇 MP4的多媒体格式,在这篇为文章中剖析了为什么MP4不是流式媒体格式,是因为MP4的BOX结构决定的,本文介绍一种常用的流式媒体格式,就是FLV,FLV全称为Flash Video,一听就知道是Adobe 公司推出的一种媒体封装格式。下面我们剖析一下FLV媒体的格式内容。
FLV分析工具
计算机上面的数据,最终写入就是bytes数据,二进制信息,还是需要可视化的工具来查看。FLV查看的工具是FlvAnalyzer,回复FLV得到多媒体查看分析的一整套工具。下面使用FlvAnalyzer来分析FLV文件。
FlvAnalyzer解析出来的FLV文件是一种树状的排列,分为两大部分:
- FLV Header:包含版本信息和音频、视频的排位信息;
- FLV Body:这里能看到交替的Video Tag和Audio Tag信息;
里面可以直接看到二进制信息,当然这些二进制数据都有具体的含义,下面会重点阐述。
除了FlvAnalyzer,还有一个工具推荐一下,是雷神开发的一个工具,是SpecialFFlv工具,真的相当赞的工具,回复FLV得到多媒体查看分析的一整套工具。大大优化了可视化的功能,界面交互更加优化。它还提供了分离视频流和音频流的功能。
test.flv分离出来的视频test_0.flv 和音频 test_0.mp3
代码语言:javascript复制ffprobe test.flv
Input #0, flv, from 'test.flv':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf57.83.100
Duration: 00:01:19.69, start: 0.084000, bitrate: 950 kb/s
Stream #0:0: Video: h264 (High), yuv420p(progressive), 960x540, 23.98 fps, 23.98 tbr, 1k tbn, 47.95 tbc
Stream #0:1: Audio: mp3, 44100 Hz, stereo, s16p, 128 kb/s
现在解析一下test_0.flv
代码语言:javascript复制ffprobe test_0.flv
Input #0, flv, from 'test_0.flv':
Duration: 00:01:19.54, start: 0.084000, bitrate: 819 kb/s
Stream #0:0: Video: h264 (High), yuv420p(progressive), 960x540, 24.42 fps, 23.98 tbr, 1k tbn, 47.95 tbc
FLV格式分析
上面使用工具解析出FLV文件的具体结构,下面我们要分析一下FLV格式的各个字段代表什么意思。
FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag组成。FLV文件的结构如下图:
1.FLV Header
Header 部分记录了FLV的类型、版本等信息,是FLV的开头。一般差不多占9个字节。具体格式如下:
可以看出来,其中包含,签名信息,版本信息,保留位,音频和视频信息,还有header size;
文件标识:占3位,总是FLV,0x46 0x4c 0x56
版本号:占1位,目前默认为0x01
流信息:占1位,文件的标志说明,前5位保留,必须为0;第6位为音频Tag:1 表示有音频;第七位保留,为0;第8位为视频Tag:1 表示有视频。
Header长度:占4位,整个Header的长度,一般为9(版本为0x01时);大于9表示下面还有扩展信息。即0x00000009。
2.FLV Body
文件体由一系列的Tag组成。其中,每个Tag前面还包含了Previous Tag Size字段,表示前面一个Tag的大小。Tag的类型可以是视频、音频和Script,每个Tag只能包含以上三种类型的数据中的一种。
3.Tag信息
每个Tag由也是由两部分组成的:Tag Header和Tag Data。Tag Header里存放的是当前Tag的类型、数据区(Tag Data)长度等信息,具体如下:
Tag类型:占1位,0x08:音频; 0x09:视频; 0x12:脚本; 其他:保留。
数据区长度:占3位,表示数据区的长度。
时间戳:占3位,整数,单位是毫秒。对于脚本型的tag总是0 (CTS)
时间戳扩展:占1位,加上之前的时间戳3位,将时间戳扩展为4bytes,代表高8位。很少用到。
StreamsID:占1位,总是0
数据区(由数据区长度决定):数据实体
下面是三个Tag类型说明:
- Audio Tag Data结构(音频类型) :音频Tag Data区域开始的第一个字节包含了音频数据的参数信息,从第二个字节开始为音频流数据。
- Video Tag Data结构(视频类型):视频Tag Data开始的第一个字节包含视频数据的参数信息,从第二个字节开始为视频流数据。
- Script Tag Data结构(脚本类型、帧类型):该类型Tag又被称为MetaData Tag,存放一些关于FLV视频和音频的元信息,比如:duration、width、height等。通常该类型Tag会作为FLV文件的第一个tag,并且只有一个,跟在File Header后。
上面是Script Tag 的结构信息。
其实从FLV的结构信息来看,比较清晰的看出来FLV就是流式格式,因为音频和视频分别对应出现,不会出现视频和音频完全分离,播放的时候再次同步拉取很麻烦。
FLV相关实践
将一个MP4文件转化为FLV文件:
代码语言:javascript复制ffmpeg -i test.mp4 -c:v libx264 -crf 24 test.flv
如何将FLV格式中设置关键帧索引?FLV标准格式中并没有关键帧索引这一说法,但是我们在实际应用中,特别是现在直播的应用中,我们往往需要向FLV格式中写入关键帧索引,并将这些索引文件写在Metadata 中,这些我们再次播放的时候,可以很快通过这些关键帧索引站到对应的位置,然后准确快速渲染播放。
代码语言:javascript复制ffmpeg -i test.mp4 -c copy -f flv -flvflags add_keyframe_index key.flv
之后查看key.flv
代码语言:javascript复制ffprobe -v trace -i key.flv