在集体挺进HTML5的时代,来讨论Adobe Flash相关的话题似乎有点过时,但现如今还是有很多的视频网站采用的是Flash播放器,播放的文件也依然还有很多是FLV格式,而且仅从一个文件格式的角度去了解和分析FLV应该也还说的过去的。
FLV(Flash Video)是Adobe的一个免费开放的音视频格式,babala~~ 省略若干字的介绍,要看,到官网看吧,这里不赘述,我们主要来讨论下FLV文件格式的细节,在此之后,我们会进一步讨论下FLV的加密解密相关内容。
整体上,FLV分为Header
和Body
两大块。
Header: 记录FLV的类型,版本,当前文件类型等信息,这些信息可以让我们对当前FLV文件有个概括的了解。
Body: FLV的Body是Flv的数据区域,这些是FLV的具体内容,因为FLV中的内容有多种,并可同时存在,因此,Body也不是一整块的数据,而是由更细分的块来组成,这个细分的块叫Tag。
这就是整个FLV的大概结构,下面我们进入到比特/字节数据的世界,看看FLV的内部世界。
HEADER
Flv 文件的Header总共由9个字节组成,他们构成如下:
----------------------------------------------
字节序 | 46 | 4c | 56 | 01 | 05 | 00 | 00 | 00 | 09 |
----------------------------------------------
字符序 F L V 1 / \ 9
---------------------------------
bit序 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 |
---------------------------------
1/0 1/0
音频位 视频位
附注说明:字节序表示文件中的存放的字节流顺序,字符序是按照字节序展示出可见的字符数据,bit序此处为第5字节的bit位值.
FLV 文件Header的9字节意义如下:
- 第1-3字节:文件标志,FLV的文件标志为固定的“FLV",字节(0x46, 0x4C,0x56),见上面的字节序和字符序两行;
- 第4字节:当前文件版本,固定为1(0x01)
- 第5字节:此字节当前用到的只有第6,8两个bit位,分别标志当前文件是否存在音频,视频。参见上面bit序,即是第5字节的内容;
- 第6-9字节:此4字节共同组成一个无符号32位整数(使用大头序),表示文件从FLV Header开始到Flv Body的字节数,当前版本固定为9(0x00,0x00,0x00,0x09)
Header之后,即是FLV的Body了,Body定义了整个FLV的数据内容,他的结构又是如何的呢,让我们看下:
BODY
Body是由Tag Size
(4字节)和Tag
组成,其结构如下:
-------------------------
| Previous Tag Size |
-------------------------
| Tag |
-------------------------
| Previous Tag Size |
-------------------------
| Tag |
-------------------------
| Previous Tag Size |
-------------------------
| Tag |
-------------------------
| Previous Tag Size |
-------------------------
Previous Tag Size
这个比较好理解,就是前一个Tag的大小,这里同样存的是无符号32位整型数值。因为第一个Previous Tag Size是紧接着FLV Header的,因此,其值也是固定为0(0x00,0x00,0x00,0x00)。
TAG
FLV中的TAG不止一种,当前版本共有3种类型组成:音频(audio),视频(video),脚本数据(script data),这三种类型会在Tag内进行标志区分。其中:Audio Tag是音频数据,Video Tag是视频数据,Script Data存放的是关于FLV视频和音频的一些参数信息(亦称为Metadata Tag),通常该Tag会在FLV File Header后面作为第一个Tag出现,并且一个文件仅有一个Script Data Tag。
为了在Tag内存放不同的数据,并且能够方便区分,每个Tag被定义除了Tag Header
和Tag Data
两部分,他们的结构如下:
-------------------------
| Tag Header |
-------------------------
| Tag Data |
-------------------------
-------------------------
| Tag Header |
-------------------------
/ \
--------------------------------------------------------
| 08 | 00 | 00 | 18 | 00 | 00 | 00 | 00 | 00 | 00 | 00 |
--------------------------------------------------------
Tag Header由11字节组成:
- 第1字节:标志当前Tag的类型,音频(0x08),视频(0x09),Script Data(0x12),除此之外,其他值非法;
- 第2-4字节:表示一个无符号24位整型数值,表示当前Tag Data的大小;
- 第5-7字节:无符号24位整型数值(UI24),当前Tag的时间戳(单位为ms),第一个Tag的时间戳总为0;
- 第8字节:为时间戳的扩展字节,当前24位不够用时,该字节作为最高位,将时间戳扩展为32位无符号整数(UI32)
- 第9-11字节:UI24类型,表示Stream ID,总是0
Tag Data
Tag Data由Tag Header标志后,就被分成音频,视频,Script Data三类,分别如下:
1. Audio Tag Data
Audio Tag Data开始的第一个字节包含了音频数据的参数信息,第二个字节开始为音频流数据:
第1字节:
-
UB[4],前4位标识音频数据的格式,如:0x2表示的是MP3数据,当前合法的数值为0,1,2,3,4,5,6,7,8,9,10,11,14,15(7,8,14,15保留为内部使用)
-
UB[2],第5,6位bit表示采样率(AAC,总是3)
-
UB[1],采样精度, 0为8bits, 1为16bits
-
UB[1],音频类型,mono=0, stereo=1
2. Video Tag Data
和音频一样,其第一个字节包含的是视频参数信息,第二字节开始为视频流数据。
第1字节:
-
UB[4],前4位标识帧类型。1: keyframe (for AVC, a seekable frame); 2: inter frame (for AVC, a nonseekable frame); 3: disposable inter frame (H.263 only); 4: generated keyframe (reserved for server use only); 5: video info/command frame
-
UB[4],后4位标识视频编码。1: JPEG (currently unused) ;2: Sorenson H.263; 3: Screen video; 4: On2 VP6; 5: On2 VP6 with alpha channel; 6: Screen video version 2; 7: AVC
第二字节开始的数据有以下规律:
If CodecID == 2
H263VIDEOPACKET
If CodecID == 3
SCREENVIDEOPACKET
If CodecID == 4
VP6FLVVIDEOPACKET
If CodecID == 5
VP6FLVALPHAVIDEOPACKET
If CodecID == 6
SCREENV2VIDEOPACKET
if CodecID == 7
AVCVIDEOPACKET
3. Script Tag Data
这个Tag Data里面在未加密的时候,是ScriptTagBody类型,里面的SCRIPTDATA编码为AMF(Action Message Format)。ScriptTagBody由Name和Value两个字段组成(类型均为SCRIPTDATAVALUE)。
----------------------------------
| Name (SCRIPTDATAVALUE) |
----------------------------------
| Value (SCRIPTDATAVALUE) |
----------------------------------
SCRIPTDATAVALUE类型比较多,它使用UI8(1个字节)来表示类型,可用的类型如下:
每种类型有对应的定义,这个比较多,不加详述,可以参看官方文档。
这里需要特别提出的一个是onMetaData
,在SCRIPTDATA Tag中,它名称即为onMetaData
,它提供一系列可用于AS编程的变量(通过NetStream.onMetaData
属性获取)。由于每种软件创建的FLV文件,均可有不同的变量,无法一一列出,但一般包含:FLV的音频,视频还有文件相关的基本信息,如:文件大小,时长,视频宽高等。
onMetaData的一般结构如下:
-------------------------------------
| Name (SCRIPTDATAVALUE) |
-------------------------------------
/ \
------------------------------------------------------------------
| 02 | 00 | 0a | 6f | 6e | 4d | 65 | 74 | 61 | 44 | 61 | 74 | 61 |
------------------------------------------------------------------
后面的Value由于每个软件产生的不同,但类型是0x08,ECMA ARRAY。大概结构如下:
----------------------------------
| ECMAArray Length(UI32) |
----------------------------------
| Variables Array[] |
----------------------------------
| SCRIPTDATAOBJECTEND |
----------------------------------
其中Variables Array为SCRIPTDATAOBJECTPROPERTY类型数组,最后用3字节的SCRIPTDATAOBJECTEND结束VALUE值。这个值固定为:0x00,0x00,0x09
到此,FLV的基本文件格式就讲解完成了,基于这个结构作为基石,我们可以对FLV进行校验,解析数据,当然,还有加密/解密。
注意:: FLV文件中,使用的是大头序字节
感谢
由于本人对于AS3零基础,对于FLV更是门外汉,特别感谢Merry引荐的Colin让我在Flv文件的研究少走很多弯路(包含Specification文档),并在短时间内出色的完成了工作中对FLV文件的析构任务。
参考
1. Adobe Video File Format specification V10
2. Video File Format Spcification V10.1