一、概述
FLV 是FLASH VIDEO的简称,FLV流媒体格式是随着Flash MX的推出发展而来的视频格式。由于它形成的文件极小、加载速度极快,使得网络观看视频文件成为可能,它的出现有效地解决了视频文件导入Flash后,使导出的SWF文件体积庞大,不能在网络上很好的使用等问题。
二、标准FLV文件结构

三、FLV大体解析框架

四、FLV格式
FLV封装格式由一个头部(header)和 主体(body)组成。body由许多个(Previous Tag size: FLV-Tag) 对组成。Previous Tag size(4 Byte)在前面,是上一个tag的大小,用于逆向读取。FLV header后的第一个Previous Tag size为0,因为前面没有Tag。
Tag分为3种类型:脚本(帧)数据类型、⾳频数据类型、视频数据。FLV数据以⼤端序进⾏存储。
| FLV Header | signature: 3个字节的文件标识,总为”F” ,”L” ,”V”(0x46,0x4c,0x56)Version: 1个字节的版本号,当前为0x01TypeFlags: 1个字节,前5位为保留位,必须为0,第6位表示是否存在音频tag,第7位为保留位,0。第8位表示是否存在视频tag。DataOffset: 4个字节,表示从File Header起始位置到File Body起始位置的字节数(header 的大小),版本1中为9。 | ||||
| FLV Body | Previous Tag size:4个字节,表示前一个tag的长度 | ||||
| Tag1 | Tag Header | Tag Type:1个字节,表示Tag的类型 | |||
| Data Size:3个字节,表示此Tag的data大小 | |||||
| Timestamp:3个字节,表示该Tag的时间戳 | |||||
| TimestampExtended:1个字节,表示时间戳的扩展字节,当24位数值不够时,以该字节为最高位将时间戳扩展为32位 | |||||
| SteamID:3个字节,总为0 | |||||
| Tag Data | Data: 不同类型的Data结构不同。Header总是相同的 | ||||
| Previous Tag size2 | 和1是一致的 … | ||||
| Tag2 | |||||
(一) FLV Header
FLV版本为1的头部固定9个字节。
| Field | Type | Comment |
| 魔数 | U8 | F (0x46) |
| 魔数 | U8 | L(0x4C) |
| 魔数 | U8 | V(0x56) |
| version | U8 | 0x01 |
| reserve | UB5 | 0 |
| audio flag | UB1 | 1表示存在,0不存在 |
| reserver | UB1 | 0 |
| video flag | UB1 | 1表示存在,0不存在 |
| header size | U32 | FLV版本1时填写9,表明FLV头的大小,为后期的FLV版本扩展使用。包括这个四个字节。数据的起始位置就是从文件开头偏移这多的大小。 |
(二) FLV Body
1. FLV Tag
每个tag由一个Header和一个Data组成,Heade里面存放当前tag的类型,数据区长度等信息。
一、Tag Header
tag header⼀般占11个字节的内存空间。
| Field | Type | Comment |
| Type | U8 | 8: audio,9:video,18:Script dataall others:reserved |
| Data Size | U24 | 当前tag的大小,不包含Header |
| TimeStamp | U24 | 当前时间戳,单位是MS。相对值,第一个Tag的时间戳总是0 |
| TimestampExtend ed | U8 | 如果时间戳大于0xFFFFFF,将使用这个字节。这个字节是最高8位。 |
| Stream id | U24 | 总是0 |
TimeStamp是dts(解码时间),TimeStampExtended拼接也是dts,如果没有B帧,pts = dts。
二、Tag Data
(一) Script Tag Data(脚本类型,帧类型)
该Tag又成为MetaData Tag,存放一些关于FLV视频和音频的元信息,比如:fps,宽,高。通常该Tag作为第一个Tag,并且只有一个,跟在FLV header后面。
| Field | Value |
| Type | 0x02 |
| Value size: | 0x0A |
| Value | OneMetaData |
第一个字节是AMF包的类型,一般总是0x02,表示字符串。第2,3个字节是U16类型,表示字符串的长度,一般总是0x0A(”OneMetaData”)的长度。同时这个包一般也是首个AMF包。
| Field | Value | |||
| Type | 0x08 | |||
| ECMAArrayLength | 0x10 | |||
| ECMAArray | Stringlength | StringData | type | Value |
| 0x8 | duration | 0x00 | 210.732 | |
| 0x5 | width | 0x00 | 768.000 |
这是一个AMF的数组类型(0x08),第2-5个字节是U16类型,表示数组的个数。数组的内容由一个个键值对组成。前面2个是键的长度和键值,后面两个是值的类型和值。具体什么值代表什么类型这里就不过多介绍了,可以查下官方的文档。
(二) Audio Tag Data
当FLV数据中音频的类型是AAC时,前2个字节构成Audio Tag Header。第一个字节包含音频数据的参数信息
| Field | Type | Comment |
| SoundFormat(⾳频格式) | UB4 | 0 = Linear PCM, platform endian1 =ADPCM2 = MP33 = Linear PCM, little endian4 = Nellymoser 16-kHz mono5 = Nellymoser 8-kHz mono6 = Nellymoser7 = G.711 A-law logarithmic PCM8 = G.711 mu-law logarithmic PCM 9 = reserved10 = AAC11 = Speex 14 = MP3 8-Khz15 = Device-specific sound |
| SoundRate(采样率) | UB2 | 0 = 5.5kHz1 = 11kHz2 = 22.05kHz3 = 44.1kHz |
| SoundSize(采样精度) | UB1 | 0 = snd8Bit1 = snd16Bit |
| SoundType(⾳频声道) | UB1 | 0 = sndMono 单声道1 = sndStereo ⽴体声,双声道 |
第二个字节是数据:
| Field | Type | Comment |
| 音频数据 | UI[8*n] | if SoundFormat == 10 (AAC类型)AACAUDIODATAelseSound data—varies by format |
| AAC AUDIO DATA | ||
| Field | Type | Comment |
| AACPacketType | UI8 | 0: AAC sequence header1: AAC raw |
| Data | UI8[n] | if AACPacketType == 0 AudioSpecificConfigelse if AACPacketType == 1 Raw AAC frame data |
The AudioSpecificConfig is explained in ISO 14496-3. AAC sequence header存放的是AudioSpecificConfig结构,该结构则在“ISO-14496-3 Audio”中描述。如果是AAC数据,如果他是AAC RAW, tag data[3] 开始才是真正的AAC frame data。


(三) Video Tag Data
第一个字节包含视频数据的参数信息
| Field | Type | Comment |
| 帧类型 | UB4 | Keyframe -H264的IDR帧inter frame -H264普通帧disposable inter frame(H263 only)generated key frame (reserved for server use only)video info / command frame |
| 编码ID | UB4 | JPEG (currently unused)Sorenson H.263Screen videoOn2 VP6On2 VP6 with alpha channelScreen video version 2AVC |
第二个字节是数据:
| Field | Type | Comment |
| 视频数据 | UI[8 * n] | If CodecID == 2H263VIDEOPACKETIf CodecID == 3SCREENVIDEOPACKETIf CodecID == 4VP6FLVVIDEOPACKETIf CodecID == 5VP6FLVALPHAVIDEOPACKETIf CodecID == 6SCREENV2VIDEOPACKETif CodecID == 7 (AVC格式)AVCVIDEOPACKET |
| AVCVIDEOPACKET | ||
| Field | Type | Comment |
| AVCPacketType | UI8 | 0: AVC sequence header1: AVC NALU2: AVC end of sequence(Low level NALU sequence ender is not required or supported) |
| CompositionTime | SI24 | if AVCPacketType == 1 Composition time offsetelse 0 |
| Data | UI8[n] | if AVCPacketType == 0AVCDecoderConfigurationRecord else if AVCPacketType == 1 One or more NALUs (can be individual slices per FLV packets; this is, full frames are not strictly required)else if AVCPacketType == 2 Empty |
- CompositionTime 单位ms
CompositionTime 每个视频Tag (整个tag) 的第14-16个字节(如果Tag data偏移[3]~[5],[0],[1][2:AVCPackettype] (表示PTS相对于DTS的偏移值)。CompositionTime: 显示时间 = 解码时间(tag的第5~8字节,位置索引[4]~[7])+ CompositionTime
- AVCDecoderConfigurationRecord
AVC sequence header就是AVCDecoderConfigurationRecord结构,该结构在标准⽂档“ISO-14496-15 AVC file format”


发表回复