傳統的直播協議要麼使用 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 的優勢: