FLV协议简介

FLV(Flash Video)是一种流媒体格式,因其体积小、协议相对简单,很快便流行开来,并得到广泛的支持。

常见的HTTP-FLV直播协议,就是使用HTTP流式传输通过FLV封装的音视频数据。对想要了解HTTP-FLV的同学来说,了解FLV协议很有必要。

概括地说,FLV 由 FLV header 跟 FLV file body 两部分组成,而 FLV file body 又由多个 FLV tag组成。

FLV = FLV header + FLV file body FLV file body = PreviousTagSize0 + Tag1 + PreviousTagSize1 + Tag2 + ... + PreviousTagSizeN-1 + TagN

FLV tag又分为3种类型:

  • Video Tag:存放视频相关数据;
  • Audio Tag:存放音频相关数据;
  • Script Tag:存放音视频元数据;

在实际讲解FLV协议前,首先对单位进行约定:

类型 定义
0x... 16进制数据
SI8 有符号8位整数
SI16 有符号16位整数
SI24 有符号24位整数
SI32 有符号32位整数
STRING Sequence of Unicode 8-bit characters (UTF-8), terminated with 0x00 (unless otherwise specified)
UI8 无符号8位整数
UI16 无符号16位整数
UI24 无符号24位整数
UI32 无符号32位整数
xxx [ ] 类型为xxx的数组
xxx [n] 类型为xxx的数组,数组长度为n

FLV header

FLV header由如下字段组成,其中:

  1. 前三个字节内容固定是FLV
  2. 最后4个字节内容固定是9(对FLV版本1来说)
字段 字段类型 字段含义
Signature UI8 签名,固定为'F' (0x46)
Signature UI8 签名,固定为'L' (0x4c)
Signature UI8 签名,固定为'V' (0x56)
Version UI8 版本,比如 0x01 表示 FLV 版本 1
TypeFlagsReserved UB[5] 全为0
TypeFlagsAudio UB[1] 1表示有audio tag,0表示没有
TypeFlagsReserved UB[1] 全为0
TypeFlagsVideo UB[1] 1表示有video tag,0表示没有
DataOffset UI32 FLV header的大小,单位是字节

FLV file body

FLV file body很有规律,由一系列的TagSize和Tag组成,其中:

  1. PreviousTagSize0 总是为0;
  2. tag 由tag header、tag body组成;
  3. 对FLV版本1,tag header固定为11个字节,因此,PreviousTagSize(除第1个)的值为 11 + 前一个tag 的 tag body的大小;
字段 字段类型 字段含义
PreviousTagSize0 UI32 总是0
Tag1 FLVTAG 第1个tag
PreviousTagSize1 UI32 前一个tag的大小,包括tag header
Tag2 FLVTAG 第2个tag
... ... ...
PreviousTagSizeN-1 UI32 第N-1个tag的大小
TagN FLVTAG 第N个tag
PreviousTagSizeN UI32 第N个tag的大小,包含tag header

FLV tags

FLV tag由 tag header + tag body组成。

tag header如下,总共占据11个字节:

字段 字段类型 字段含义
TagType UI8 tag类型
8:audio
9:video
18:script data
其他:保留
DataSize UI24 tag body的大小
Timestamp UI24 相对于第一个tag的时间戳(单位是毫秒)
第一个tag的Timestamp为0
TimestampExtended UI8 时间戳的扩展字段,当 Timestamp 3个字节不够时,会启用这个字段,代表高8位
StreamID UI24 总是0
Data 取决于根据TagType TagType=8,则为AUDIODATA
TagType=9,则为VIDEODATA
TagType=18,则为SCRIPTDATAOBJECT

In playback, the time sequencing of FLV tags depends on the FLV timestamps only. Any timing mechanisms built into the payload data format are ignored.

Audio tags

定义如下所示:

字段 字段类型 字段含义
SoundFormat UB[4] 音频格式,重点关注 **10 = AAC **
0 = Linear PCM, platform endian
1 = ADPCM
2 = MP3
3 = Linear PCM, little endian
4 = Nellymoser 16-kHz mono
5 = Nellymoser 8-kHz mono
6 = Nellymoser
7 = G.711 A-law logarithmic PCM 8 = G.711 mu-law logarithmic PCM 9 = reserved
10 = AAC
11 = Speex
14 = MP3 8-Khz
15 = Device-specific sound
SoundRate UB[2] 采样率,对AAC来说,永远等于3
0 = 5.5-kHz
1 = 11-kHz
2 = 22-kHz
3 = 44-kHz
SoundSize UB[1] 采样精度,对于压缩过的音频,永远是16位
0 = snd8Bit
1 = snd16Bit
SoundType UB[1] 声道类型,对Nellymoser来说,永远是单声道;对AAC来说,永远是双声道;
0 = sndMono 单声道
1 = sndStereo 双声道
SoundData UI8[size of sound data] 如果是AAC,则为 AACAUDIODATA;
其他请参考规范;

备注:

If the SoundFormat indicates AAC, the SoundType should be set to 1 (stereo) and the SoundRate should be set to 3 (44 kHz). However, this does not mean that AAC audio in FLV is always stereo, 44 kHz data. Instead, the Flash Player ignores these values and extracts the channel and sample rate data is encoded in the AAC bitstream.

AACAUDIODATA

当 SoundFormat 为10时,表示音频采AAC进行编码,此时,SoundData的定义如下:

字段 字段类型 字段含义
AACPacketType UI8 0: AAC sequence header
1: AAC raw
Data UI8[n] 如果AACPacketType为0,则为AudioSpecificConfig
如果AACPacketType为1,则为AAC帧数据

The AudioSpecificConfig is explained in ISO 14496-3. Note that it is not the same as the contents of the esds box from an MP4/F4V file. This structure is more deeply embedded.

关于AudioSpecificConfig

伪代码如下:参考这里

5 bits: object type
if (object type == 31)6 bits + 32: object type
4 bits: frequency index
if (frequency index == 15)24 bits: frequency
4 bits: channel configuration
var bits: AOT Specific Config

定义如下:

字段 字段类型 字段含义
AudioObjectType UB[5] 编码器类型,比如2表示AAC-LC
SamplingFrequencyIndex UB[4] 采样率索引值,比如4表示44100
SamplingFrequencyIndex UB[4] 采样率索引值,比如4表示44100
ChannelConfiguration UB[4] 声道配置,比如2代表双声道,front-left, front-right

Video tags

定义如下:

字段 字段类型 字段含义
FrameType UB[4] 重点关注1、2:
1: keyframe (for AVC, a seekable frame) —— 即H.264的IDR帧;
2: inter frame (for AVC, a non- seekable frame) —— H.264的普通I帧;
3: disposable inter frame (H.263 only)
4: generated keyframe (reserved for server use only)
5: video info/command frame
CodecID UB[4] 编解码器,主要关注 7(AVC)
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
VideoData 取决于CodecID 实际的媒体类型,主要关注 7:AVCVIDEOPACKE
2: H263VIDEOPACKET
3: SCREENVIDEOPACKET
4: VP6FLVVIDEOPACKET
5: VP6FLVALPHAVIDEOPACKET
6: SCREENV2VIDEOPACKET
7: AVCVIDEOPACKE

AVCVIDEOPACKE

当 CodecID 为 7 时,VideoData 为 AVCVIDEOPACKE,也即 H.264媒体数据。

AVCVIDEOPACKE 的定义如下:

字段 字段类型 字段含义
AVCPacketType UI8 0: AVC sequence header
1: AVC NALU
2: AVC end of sequence
CompositionTime SI24 如果AVCPacketType=1,则为时间cts偏移量;否则,为0
Data UI8[n] 1、如果如果AVCPacketType=1,则为AVCDecoderConfigurationRecord
2、如果AVCPacketType=1=2,则为NALU(一个或多个)
3、如果AVCPacketType=2,则为空

这里有几点稍微解释下:

  1. NALU:H.264中,将数据按照特定规则格式化后得到的抽象逻辑单元,称为NALU。这里的数据既包括了编码后的视频数据,也包括视频解码需要用到的参数集(PPS、SPS)。
  2. AVCDecoderConfigurationRecord:H.264 视频解码所需要的参数集(SPS、PPS)
  3. CTS:当B帧的存在时,视频解码呈现过程中,dts、pts可能不同,cts的计算公式为 pts - dts/90,单位为毫秒;如果B帧不存在,则cts固定为0;

PPS、SPS这里先不展开。

Script Data Tags

Script Data Tags通常用来存放跟FLV中音视频相关的元数据信息(onMetaData),比如时长、长度、宽度等。它的定义相对复杂些,采用AMF(Action Message Format)封装了一系列数据类型,比如字符串、数值、数组等。

字段 字段类型 字段含义
Objects SCRIPTDATAOBJECT[] 任意数目的 SCRIPTDATAOBJECT
SCRIPTDATAOBJECTEND UI24 永远是9,标识着Script Data的结束

SCRIPTDATAOBJECT 定义如下:

字段 字段类型 字段含义
ObjectName SCRIPTDATASTRING 对象的名字
ObjectData SCRIPTDATAVALUE 对象的值

SCRIPTDATAVALUE 的定义如下:

字段 字段类型 字段含义
Type SCRIPTDATASTRING 变量类型:
0 = Number type
1 = Boolean type
2 = String type
3 = Object type
4 = MovieClip type
5 = Null type
6 = Undefined type
7 = Reference type 8 = ECMA array type 10 = Strict array type 11 = Date type
12 = Long string type
ECMAArrayLength 如果Type为8(数组),则为UI32 数组长度
ScriptDataValue If Type == 0 DOUBLE
If Type == 1 UI8
If Type == 2 SCRIPTDATASTRING
...(有点长,可以参考规范)
变量的值
ScriptDataValueTerminator 如果Type==3,则为SCRIPTDATAOBJECTEND
如果 Type==8,则为SCRIPTDATAVARIABLEEND
Object、Array的结束符

可以看到,Script Data Tag 的定义相对复杂,下面通过onMetaData进行进一步讲解。

onMetaData

onMetaData中包含了音视频相关的元数据,封装在Script Data Tag中,它包含了两个AMF。

第一个AMF:

  • 第1个字节:0x02,表示字符串类型
  • 第2-3个字节:UI16类型,值为0x000A,表示字符串的长度为10(onMetaData的长度);
  • 第4-13个字节:字符串onMetaData对应的16进制数字(0x6F 0x6E 0x4D 0x65 0x74 0x61 0x44 0x61 0x74 0x61);

第二个AMF:

  • 第1个字节:0x08,表示数组类型;
  • 第2-5个字节:UI32类型,表示数组的长度,onMetaData中具体包含哪些属性是不固定的。
  • 第6个字节+:比如duration,则:
    • 第6-9个字节:0x0008,表示长度为8个字节;
    • 第10-17个字节:0x6475 7261 7469,表示 duration 这个字符串;
    • 第18个字节:0x00,表示为数值类型;
    • 第19-26个字节:0x...,表示具体的时长;

更多onMetaData字段的定义:

字段 字段类型 字段含义
duration DOUBLE 文件的时长
width DOUBLE 视频宽度(px)
height DOUBLE 视频高度(px)
videodatarate DOUBLE 视频比特率(kb/s)
framerate DOUBLE 视频帧率(帧/s)
videocodecid DOUBLE 视频编解码器ID(参考Video Tag)
audiosamplerate DOUBLE 音频采样率
audiosamplesize DOUBLE 音频采样精度(参考Audio Tag)
stereo BOOL 是否立体声
audiocodecid DOUBLE 音频编解码器ID(参考Audio Tag)
filesize DOUBLE 文件总得大小(字节)

写在后面

FLV协议本身不算复杂,理解上的困难,更多时候来自音视频编解码相关的知识,比如H.264、AAC相关知识,建议不懂的时候自行查下。此外,FLV的字节序为大端序,在做协议解析的时候一定要注意。

本文为讲解方便,部分内容可能不够严谨,如有错漏敬请指出。

相关链接

video_file_format_spec_v10.pdf www.adobe.com/content/dam…

MPEG-4 Part 3 en.wikipedia.org/wiki/MPEG-4…

flv文件分析 www.jianshu.com/p/e290dca02…

H.264再学习 -- 详解 H.264 NALU语法结构 blog.csdn.net/qq_29350001…

转载于:https://juejin.im/post/5d50b5176fb9a06b2116dae9

FLV协议5分钟入门浅析相关推荐

  1. Azure IoT Hub 十分钟入门系列 (1)- 10分钟带你了解Azure IoT Hub 并创建IoT Hub

    建议您先对<Azure 上 IoT 整体解决方案概览 >进行了解. 本文主要分享一个案例: 10分钟-了解Azure IoT Hub并创建Azure IoT Hub 本文主要有如下内容: ...

  2. Objective-C 30分钟入门教程

    Objective-C 30分钟入门教程 我第一次看OC觉得这个语言的语法有些怪异,为什么充满了@符号,[]符号,函数调用没有()这个,但是面向对象的高级语言也不外乎类,接口,多态,封装,继承等概念. ...

  3. python 三分钟入门_Cython 三分钟入门教程

    作者:perrygeo 译者:赖勇浩(http://laiyonghao.com) 原文:http://www.perrygeo.net/wordpress/?p=116 我最喜欢的是Python,它 ...

  4. 技术19期:1分钟入门数据治理!必看!【技术篇】

    1分钟入门数据治理!必看![技术篇] 前言: 在进行大数据开发过程中,数据调研和开发规范都是必不可少的.数据调研便于理清数据源之间的关系,梳理出哪些数据是符合当下的业务场景以及确定所要用到的加工口径等 ...

  5. 可下载:60分钟入门PyTorch(中文翻译全集)

    来源:机器学习初学者本文约9500字,建议阅读20分钟官网教程翻译:60分钟入门PyTorch(全集) 前言 原文翻译自:Deep Learning with PyTorch: A 60 Minute ...

  6. 30分钟入门Java8之默认方法和静态接口方法

    2019独角兽企业重金招聘Python工程师标准>>> 30分钟入门Java8之默认方法和静态接口方法 作者:@JohnTsai 本文为作者原创,转载请注明出处:http://www ...

  7. 高级篇:独立开发者 5 分钟入门 ASO

    这是接上一篇初级篇:独立开发者 5 分钟入门 App 营销的后续,如果有没看上一篇文章的,建议先看上一篇,再回来继续看. "营销" 这个概念自始至终会贯穿我们的专栏,以后会展开说其 ...

  8. 转载:正则表达式30分钟入门教程

    正则表达式30分钟入门教程 版本:v2.21 (2007-8-3) 作者:deerchao 来源:unibetter大学生社区 转载请注明来源 目录 本文目标 如何使用本教程 正则表达式到底是什么? ...

  9. hive hql文档_30分钟入门 Hive SQL(HQL 入门篇)

    Hive SQL 几乎是每一位互联网分析师的必备技能,相信每一位面试过大厂的童鞋都有被面试官问到 Hive 优化问题的经历.所以掌握扎实的 HQL 基础尤为重要,既能帮分析师在日常工作中"如 ...

最新文章

  1. 10月份机房技术指标
  2. spring的jar各包作用
  3. LeetCode Elimination Game(递推法)
  4. php中0与NULL,False,“0”,\0的区别
  5. oracle每一行的hash值,Hash分区表分区数与数据分布的测试
  6. 如何用苹果手机生成扫描件
  7. boost::outcome模块containers相关的测试程序
  8. php判断ie版本,PHP获取浏览器版本信息
  9. [tarjan][树形dp] 洛谷 P2515 软件安装
  10. 设计师吃饭的家伙还问别人要?必要软件、效率工具、插件搜集给你
  11. [转帖]备忘:CentOS-7 使用systemctl 管理的服务,文件打开数上限1024要改
  12. linux nginx环境下,网站不显示字体和图形.(图形变成了方框),解决nginx下加载eot|otf|ttf|woff|svg等404 错误问题
  13. 转一个国外程序员辞职自己做广告应用的经历贴
  14. 剖析矩阵的本质及其意义
  15. Vue中使用微信JSDK实现图片上传
  16. Python test1
  17. [EOS源码分析]7.EOS智能合约开发实践之合约调用合约(inline action)
  18. 5.1低噪放的基本指标
  19. 地信、遥感专业各类官网收集(持续更新)
  20. Python-4.6 查看进程的pid和ppid

热门文章

  1. Linux 命令之 pwconv -- 开启用户的投影密码
  2. File类、递归、字节流
  3. 学维修电脑要多久_学厨师要多久才出师
  4. php中符号 的作用是什么意思,PHP中@符号的用途是什么?
  5. c mysql 地址池_FreeRadius 根据mysql 下发指定地址池的地址...
  6. 【WebRTC---入门篇】(十一)STUN协议
  7. python所有的父类_object代表所有类的父类吗??
  8. python xlutils函数,python3:xlrd、xlwt、xlutils处理excel文件
  9. linux lvm 系统快照,系统运维|在 LVM中 录制逻辑卷快照并恢复(第三部分)
  10. 产线数字化软件源码_品质笔记⑥丨卢宇聪:把握数字化趋势,坚定创新发展道路...