传统的直播协议要么使用 Adobe 的基于 TCP 的 RTMP 协议,要么使用 Apple 的基于 HTTP 的 HLS 协议。
今天我要向你们介绍另一种结合了 RTMP 的低延时,以及能够复用现有 HTTP 分发资源的流式协议 HTTP-FLV。网络
首先介绍一下 FLV 文件格式的细节。ide
FLV 文件格式标准是写在 F4V/FLV file format spec v10.1 的附录 E 里面的 FLV File Format。工具
一般,FLV 的前 13 个字节(flv header + PreviousTagSize0)彻底相同,因此,程序中会单独定义一个常量来指定。优化
Timestamp 和 TimestampExtended 组成了这个 TAG 包数据的 PTS 信息,PTS = Timestamp | TimestampExtended << 24。编码
因为 AAC 编码的特殊性,这里着重说明了 AAC 编码的 Tag 格式。spa
AudioTagHeader 的第一个字节,也就是接跟着 StreamID 的 1 个字节包含了音频类型,采样率等的基本信息。
AudioTagHeader 以后跟着的就是 AUDIODATA 部分了。可是,这里有个特例,若是音频格式(SoundFormat)是 AAC,AudioTagHeader 中会多出 1 个字节的数据 AACPacketType,这个字段来表示 AACAUDIODATA 的类型:0 = AAC sequence header,1 = AAC raw。
AudioSpecificConfig 结构描述很是复杂,在标准文档中是用伪代码描述的,这里先假定要编码的音频格式,作一下简化。
音频编码为:AAC-LC,音频采样率为 44100。3d
在 FLV 的文件中,通常状况下 AAC sequence header 这种包只出现1次,并且是第一个 audio tag,为何须要这种 tag,由于在作 FLV demux 的时候,若是是 AAC 的音频,须要在每帧 AAC ES 流前边添加 7 个字节 ADST 头,ADST 是解码器通用的格式,也就是说 AAC 的纯 ES 流要打包成 ADST 格式的 AAC 文件,解码器才能正常播放。就是在打包 ADST 的时候,须要 samplingFrequencyIndex 这个信息,samplingFrequencyIndex 最准确的信息是在 AudioSpecificConfig 中,这样,你就彻底能够把 FLV 文件中的音频信息及数据提取出来,送给音频解码器正常播放了。code
因为 AVC(H.264) 编码的特殊性,这里着重说明了 AVC(H.264) 编码的 Tag 格式。orm
VideoTagHeader 的第一个字节,也就是接跟着 StreamID 的 1 个字节包含着视频帧类型及视频 CodecID 等最基本信息。
VideoTagHeader 以后跟着的就是 VIDEODATA 部分了。可是,这里有个特例,若是视频格式(CodecID)是 AVC,VideoTagHeader 会多出 4 个字节的信息。
AVCDecoderConfigurationRecord 包含着是 H.264 解码相关比较重要的 SPS 和 PPS 信息,在给 AVC 解码器送数据流以前必定要把 SPS 和 PPS 信息送出,不然的话,解码器不能正常解码。并且在解码器 stop 以后再次 start 以前,如 seek,快进快退状态切换等,都须要从新送一遍 SPS 和 PPS 的信息。AVCDecoderConfigurationRecord 在 FLV 文件中通常状况也只出现 1 次,也就是第一个 video tag。
AVCDecoderConfigurationRecord 长度为 sizeof(UI8) * (11 + sps_size + pps_size)。视频
ScriptTagBody 内容用 AMF 编码
一个 SCRIPTDATAVALUE 记录包含一个有类型的 ActionScript 值。
FLV metadata object 保存在 SCRIPTDATA 中, 叫 onMetaData。不一样的软件生成的 FLV 的 properties 不一样。
keyframes 索引信息
官方的文档中并无对 keyframes index 作描述,可是,flv 的这种结构每一个 tag 又不像 TS 有同步头,若是没有 keyframes index 的话,须要按顺序读取每个tag, seek 及快进快退的效果会很是差。后来在作 flv 文件合成的时候,发现网上有的 flv 文件将 keyframes 信息隐藏在 Script Tag 中。
keyframes 几乎是一个非官方的标准, 也就是民间标准。两个经常使用的操做 metadata 的工具是 flvtool2 和 FLVMDI,都是把 keyframes 做为一个默认的元信息项目。在 FLVMDI 的主页上有描述:
也就是说 keyframes 中包含着 2 个内容 “filepositions” 和 “times”分别指的是关键帧的文件位置和关键帧的 PTS。经过 keyframes 能够创建起本身的 Index,而后在 seek 和快进快退的操做中,快速有效地跳转到你想要找的关键帧位置进行处理。
HTTP-FLV,即将音视频数据封装成 FLV,而后经过 HTTP 协议传输给客户端。
HLS 实际上是一个 “文本协议”,而并不是流媒体协议。那么,什么样的协议才能称之为流媒体协议呢?
流(stream): 数据在网络上按时间前后次序传输和播放的连续音/视频数据流。之因此能够按照顺序传输和播放连续是由于在相似 RTMP、FLV 协议中,每个音视频数据都被封装成了包含时间戳信息头的数据包。而当播放器拿到这些数据包解包的时候可以根据时间戳信息把这些音视频数据和以前到达的音视频数据连续起来播放。MP四、MKV 等等相似这种封装,必须拿到完整的音视频文件才能播放,由于里面的单个音视频数据块不带有时间戳信息,播放器不能将这些没有时间戳信息数据块连续起来,因此就不能实时的解码播放。
理论上(除去网络延迟外),FLV 能够作到仅仅一个音视频 tag 的延迟。
相比 RTMP 的优势: