Reference
- video_file_format_spec_v10_1.pdf
- FLV 文件格式简析
- FLV文件的第一个Tag: onMetaData
- H.264/AVC编码的FLV文件的第二个Tag: AVCDecoderConfigurationRecord
- 《FFmpeg 从入门到精通》
FLV 封装格式
FLV header
定义
翻译:
字段 | 占用位数 | 说明 |
---|---|---|
Signature | 8 | 签名字段,字符 F(0x46) |
Signature | 8 | 签名字段,字符 L(0x4C) |
Signature | 8 | 签名字段,字符 V(0x56) |
Version | 8 | 文件版本(例如 0x01 为 FLV 版本 1) |
TypeFlagsReserved | 5 | 保留标记类型,固定为 0 |
TypeFlagsAudio | 1 | 音频标记类型,1 为显示音频标签 |
TypeFlagsReserved | 1 | 保留标记类型,固定为 0 |
TypeFlagsVideo | 1 | 视频标记类型,1 为显示视频标签 |
DataOffset | 32 | 这个头的字节数 |
FLV body
字段 | 类型/大小 | 说明 |
---|---|---|
保留字段 | 4 字节 | 一直是 0 |
TAG0 | FLV TAG | 第一个 TAG |
Tag0Size | 4 字节 | TAG0 的大小,包括 TAG0 的 header+body,TAG 的 header 大小为 11 字节,所以这个字段大小为 11 字节+body 的大小 |
TAG1 | FLV TAG | 第二个 TAG |
…… | …… | …… |
TagN-1Size | 4 字节 | TagN-1 的大小,包括 TagN-1 的 header+body,TAG 的 header 大小为 11 字节,所以这个字段大小为 11 字节+body 的大小 |
TAGN | FLV TAG | 第 N 个 TAG |
FLV TAG
翻译:
字段 | 类型/大小 | 说明 |
---|---|---|
Reserved | 2 位 | 为 FMS 保留,应该是 0 |
Filter | 1 位 | 主要用于做文件内容加密处理: 0:不预处理 1:预处理 |
TagType | 5 位 | 8(0x08):音频 TAG 9(0x09):视频 TAG 18(0x12):脚本数据,例如 Metadata |
DataSize | 24 位 | TAG 的 DATA 部分的大小 |
Timestamp | 24 位 | 以毫秒为单位的展示时间 0x000000 |
TimestampExtended | 8 位 | 针对时间戳增加的补充时间戳 |
StreamID | 24 位 | 一直是 0 |
AudioTagHeader | ||
VideoTagHeader | ||
EncryptionHeader | ||
FilterParam | ||
Data | 音频数据/视频数据/脚本数据 | 包含 startcode |
每个 TAG 都和前面的 TAG 之间存在 4 个字节(用于表示前一个 TAG 长度)。
4 个字节后,首先是 11 个字节的FLV TAG header
,然后是音频/视频/脚本的header
,最后是音频/视频/脚本的body
。
TAG header
脚本 TAG 的 header
1个字节的2
+ 12个字节的onMetaData
字符串。
视频 TAG 的 header
翻译:
字段 | 类型/大小 | 说明 |
---|---|---|
FrameType | 4 位 | 视频帧的类型: 1:关键帧(H264使用,可以 seek 的帧) 2:P 或 B 帧(H264 使用,不可以 seek 的帧) 3:仅应用于 H263 4:生成关键帧(服务器端使用) 5:视频信息/命令帧 |
CodecID | 4 位 | Codec 类型: 2:Sorenson H263 3:Screen Video 4:On2 VP6 5:带 Alpha 通道的 On2 VP6 6:Screen Video 2 7:H264 |
AVCPacketType | 当 Codec 为 H264 编码时占用这个 8 位 | 当 H264 编码封装在 FLV 中时,需要三类 H264 的数据: 0:H264 的 Sequence Header 1:NALU 2:H264 的 Sequence 的 end |
CompositionTime | 当 Codec 为 H264 编码时占用这个 24 位 | 当编码使用 B 帧时,DTS 和 PTS 不相等,CTS 用于表示 PTS 和 DTS 之间的差值 |
音频 TAG 的 header
翻译:
字段 | 类型/大小 | 说明 |
---|---|---|
SoundFormat | 4 位 | 0:线性 PCM,大小端取决于平台 1:ADPCM 音频格式 2:MP3 3:线性 PCM,小端 4:Nellymoser 16kHz Mono 5:Nellymoser 8kHz Mono 6:Nellymoser 7:G711 A-law 8:G711 mu-law 9:保留 10:AAC 11:Speex 14:MP3 8kHz 15:设备支持的声音 格式 7、8、14、15 均为保留;使用频率非常高的为 AAC、MP3、Speex |
SoundRate | 2 位 | 0:5.5 kHz 1:11 kHz 2:22 kHz 3: 44 kHz 有些音频为 48 kHz 的 AAC 也可以被包含进来,不过也是采用 44 kHz 的方式存储,因为音频采样率在标准中只用 2 位来表示不同的采样率,所以一般为 4 种 |
SoundSize | 1 位 | 0:8 位采样 1:16 位采样 |
SoundSize | 1 位 | 0:Mono sound 1:Stereo sound |
AACPacketType | 当音频为 AAC 时占用这 8 位 | 0:AAC Sequence Header 1:AAC raw 数据 |
TAG body
脚本 TAG 的 body
将数据按照写入规则排在header
后面。
参数包括:
其中,audiocodecid
范围:
videocodecid
范围:
参数写入规则根据数据类型而定。
数据类型包括:
数据类型 | 参数写入规则 |
---|---|
String | 1个字节的2 + 2个字节的value长度 + value长度个字节的value |
ECMA array | 4个字节的8 + 每个元素(key长度个字节的key + 1个字节的数据类型 + value长度个字节的value) |
onMetaData
结尾是 3 个字节的0x00 0x00 0x09
。
视频 TAG 的 body(AVC 编码格式)
翻译:
字段 | 说明 |
---|---|
Data | AVC 序列头或视频数据 |
AVCDecoderConfigurationRecord
定义
|
|
从报文看结构
图中阴影部分对应了header
全部数据
数据 | 数据位置的说明 |
---|---|
0x61 0x76 0x63 0x43 | 字符avcC |
0x01 | configurationVersion |
0x42 | AVCProfileIndication |
0x00 | profile_compatibility |
0x1F | AVCLevelIndication |
0xFF | 6bit的reserved + 2bit的lengthSizeMinusOne(0x03 表示使用 4 个字节表示 NALU 的长度) |
0xE1 | 3bit的reserved + 5bit的numOfSequenceParameterSets |
0x00 0x09 | SPS 的长度 |
0x67 0x42 0x00 0x1f 0xe9 0x02 0xc1 0x2c 0x80 | SPS 的内容(和长度对应) |
0x01 | numOfPictureParameterSets |
0x00 0x04 | PPS 的长度 |
0x68 0xce 0x06 0xf2 | PPS 的内容(和长度对应) |
音频 TAG 的 body(AAC 编码格式)
翻译:
字段 | 说明 |
---|---|
Data | AAC 序列头或音频数据 |
AudioSpecificConfig
RTMP 与 FLV 相比特殊的地方
1、FLV body 的第一个 TAG 必须是 onMetaData
2、如果有 AVC,FLV body 下一个 TAG 必须是 AVCDecoderConfigurationRecord
首先是 11 个字节的FLV TAG header
(其中TagType=0x09
),然后是AVC
编码格式的header
(其中AVCPacketType=0x00
),最后是AVCDecoderConfigurationRecord
。
3、如果有 AAC,FLV body 下一个 TAG 必须是 AudioSpecificConfig
首先是 11 个字节的FLV TAG header
(其中TagType=0x08
),然后是AAC
编码格式的header
(其中AACPacketType=0x00
),最后是AudioSpecificConfig
。
将 FLV 文件按字节转十六进制
参考【MP4 封装格式#将 MP4 文件按字节转十六进制】
实际 FLV 文件的数据结构
FLV header
|
|
FLV body
|
|
保留字段
|
|
第 1 个 FLV TAG(onMetadata)
|
|
onMetadata header
|
|
onMetadata body
|
|
第 1 个 TAG 的长度
|
|
第 2 个 FLV TAG(AudioTag)
|
|
AudioTagHeader
|
|
AUDIODATA
|
|
第 2 个 TAG 的长度
|
|
第 3 个 FLV TAG(VideoTag)
|
|
VideoTagHeader
|
|
VIDEODATA
|
|
第 3 个 TAG 的长度
|
|
第 4 个 FLV TAG(AudioTag)
|
|
AudioTagHeader
|
|
AUDIODATA
|
|
第 4 个 TAG 的长度
|
|
第 5 个 FLV TAG(VideoTag)
|
|
VideoTagHeader
|
|
VIDEODATA
|
|
第 5 个 TAG 的长度
|
|
第 6 个 FLV TAG(AudioTag)
|
|
AudioTagHeader
|
|
AUDIODATA
|
|
第 6 个 TAG 的长度
|
|
第 7 个 FLV TAG(AudioTag)
|
|
AudioTagHeader
|
|
AUDIODATA
|
|
第 7 个 TAG 的长度
|
|
第 8 个 FLV TAG(VideoTag)
|
|
VideoTagHeader
|
|
VIDEODATA
|
|
第 8 个 TAG 的长度
|
|
第 9 个 FLV TAG(AudioTag)
|
|
AudioTagHeader
|
|
AUDIODATA
|
|
第 9 个 TAG 的长度
|
|
第 10 个 FLV TAG(VideoTag)
|
|
VideoTagHeader
|
|
VIDEODATA
|
|
第 10 个 TAG 的长度
|
|
第 11 个 FLV TAG(AudioTag)
|
|
第 11 个 TAG 的长度
|
|
第 12 个 FLV TAG(AudioTag)
|
|
第 12 个 TAG 的长度
|
|
第 13 个 FLV TAG(VideoTag)
|
|
第 13 个 TAG 的长度
|
|
第 14 个 FLV TAG(AudioTag)
|
|
第 14 个 TAG 的长度
|
|
第 15 个 FLV TAG(VideoTag)
|
|
第 15 个 TAG 的长度
|
|
第 16 个 FLV TAG(AudioTag)
|
|
第 16 个 TAG 的长度
|
|
第 17 个 FLV TAG(AudioTag)
|
|
第 17 个 TAG 的长度
|
|
第 18 个 FLV TAG(VideoTag)
|
|
第 18 个 TAG 的长度
|
|
第 19 个 FLV TAG(AudioTag)
|
|
第 19 个 TAG 的长度
|
|
第 20 个 FLV TAG(VideoTag)
|
|
第 20 个 TAG 的长度
|
|
(中间部分省略)
最后的 FLV TAG(VideoTag)
|
|
最后的 TAG 的长度
|
|
(暂不清楚这个 d0 的意义)
|
|
FFmpeg 封装 FLV
参数 | 类型 | 说明 |
flvflags | ||
flag | 设置生成 FLV 时使用的 flag | aac_seq_header_detect | 添加 AAC 音频的 Sequence Header |
no_sequence_end | 生成 FLV 结束时不写入 Sequence End | |
no_metadata | 生成 FLV 时不写入 metadata | |
no_duration_filesize | 用于直播时不在 metadata 中写入 duration 与 filesize | |
add_keyframe_index | 生成 FLV 时自动写入关键帧索引信息到 metadata 头 |
MP4 转封装 FLV
1、输入命令:
|
|
2、输出结果:
生成带关键索引的 FLV
将 FLV 文件中的关键帧建立索引,并将索引写入 Metadata 头中。
1、输入命令:
|
|
2、输出结果:
3、使用 FLV analyzer 对比察看:
(1)原文件:
(2)带关键索引的文件: