點直播流媒體傳輸協議之 —— HLS(HTTP Live Streaming)
- HLS
- TS
- M3u8
在最近一年的工作中接觸比較多的是視頻點播和直播,也瞭解到了一些點直播的後端技術,這段時間希望將瞭解到的一些技術總結下來,這篇文章主要介紹流媒體協議 HLS
流媒體協議
常用的流媒體協議主要有 HTTP 漸進下載和基於 RTSP/RTP 的實時流媒體協議,這兩種協議是完全不同的實現方式。主要區別如下:
- 一種是分段漸近下載,一種是基於實時流來實現播放
- 協議不同,HTTP 協議的漸近下載意味着你可以在一臺普通的 HTTP 的應用服務器上就可以直接提供點播和直播服務
- 延遲有差異,HTTP 漸近下載的方式的延遲理論上會略高於實時流媒體協議的播放
- 漸近下載會生成索引文件,所以需要考慮存儲,對 I/O 要求較高
HLS簡介
HLS (HTTP Live Streaming)是蘋果公司實現的基於 HTTP 的流媒體協議,可以實現流媒體的點播和直播播放。當然,起初是隻支持蘋果的設備,目前大多數的移動設備也都實現了該功能。HTML5 直接支持該協議。
實現原理
HLS 點播是常見的分段 HTTP 點播,就是將視頻流分成不同的片段,客戶端不斷的去下載該片段,由於片段之間的分段間隔時間非常短,所以看起來是一條完整的播放流,實現的重點是對於媒體文件的分割。同時,HLS 還支持多碼率的切換,客戶端可以選擇從許多不同的備用源中以不同的速率下載同樣的資源,允許流媒體會話適應不同的數據速率。多清晰度就是這樣實現的。
爲了播放媒體流,客戶端首先需要獲得播放列表文件,也就是根據 HLS 生成的片段列表,該列表中包含每個流媒體的文件,客戶端以類似輪詢的方式不斷重複加載播放列表文件並將片段追加實現流媒體的播放。
播放列表文件就是通常我們所說的 m3u8 文件,是以後綴 .m3u8 Content-Type是”application/vnd.apple.mpegurl” 的文件。
m3u8 介紹與分析
m3u8 文件本質說其實是採用了編碼是 UTF-8 的 m3u 文件。
它只是一個純索引文件,一個文件片段的列表,客戶單打開它並不是播放它,而是根據它裏面的文件片段找到視頻文件的網路地址進行播放
這裏抓包抓了一個 m3u8 文件打開看一下究竟是什麼:
#EXTM3U
#EXT-X-VIDEO-INF:VIDEO=559ac1317682fa1fcdc67ed2774e4e1a980e0c264cefceb5c.....
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=245760
https://*******.com/video/cif/hNAQ0_jbip4j-0o_BhcdqMwyQxwtwbo1k3vVZhtjbcQ.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=491520
https://******.com/video/sd/hNAQ0_jbip4j-0o_BhcdqMwyQxwtwbo1k3vVZhtjbcQ.m3u8
分析該 m3u8 文件:
#EXTM3U:擴展標記 ,意思是我是 m3u 文件
#EXT-X-VIDEO-INF:VIDEO :這個應該是自己定義的一個標籤,指名是視頻文件,後面可能跟的是視頻標題之類的
#EXT-X-STREAM-INF
指定一個包含多媒體信息的 media URI 作爲PlayList,一般做M3U8的嵌套使用,它只對緊跟後面的URI有效,#EXT-X-STREAM-INF:有以下屬性:
BANDWIDTH:帶寬,491520
PROGRAM-ID:該值是一個十進制整數,惟一地標識一個在PlayList文件範圍內的特定的描述。一個PlayList 文件中可能包含多個有相同ID的此tag。
CODECS:不是必須的。
RESOLUTION:分辨率。
AUDIO:這個值必須和AUDIO類別的“EXT-X-MEDIA”標籤中“GROUP-ID”屬性值相匹配。
這裏 PlayList 的地址我們發現還是個 m3u8 文件
https://*******.com/video/cif/hNAQ0_jbip4j-0o_BhcdqMwyQxwtwbo1k3vVZhtjbcQ.m3u8
https://******.com/video/sd/hNAQ0_jbip4j-0o_BhcdqMwyQxwtwbo1k3vVZhtjbcQ.m3u8
可以觀察發現,這其實是 cif 和 sd 兩種不同清晰度的 m3u8 文件,客戶端根據網絡或者選項去選擇不同的清晰度的 m3u8 文件。
上面的 m3u8 文件爲一級 m3u8 文件,這兩個 m3u8 就稱爲二級 m3u8 文件,那麼我們就順着二級 m3u8 文件繼續查看,將其中一個下載到本地打開分析:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:11
#EXTINF:12.400,
http://*************/**/M00/00/BB/Cn1GQlfWRFaACQaQAAvsEEMIWI42131.ts
#EXTINF:10.000,
http://*************/**/M00/00/BB/Cn1GQlfWRFaAJO1mAAaTMDz8P4E9292.ts
#EXTINF:10.000,
http://*************/**/M00/00/BB/Cn1GQlfWRFaAZ2fyAAVQEM22iWA2544.ts
#EXTINF:11.120,
http://*************/**/M00/00/BB/Cn1GQlfWRFaAIfwHAAirSMgfpx03176.ts
#EXTINF:17.240,
http://*************/**/M00/00/BB/Cn1GQlfWRFaAaiz6AAn0SHY1csA7539.ts
#EXTINF:3.720,
http://*************/**/M00/00/BB/Cn1GQlfWRFaARLJ2AAGYUIIpGKA7707.ts
#EXT-X-ENDLIST
#EXT-X-VERSION:3 : 版本
#EXT-X-TARGETDURATION:11
指定最大的媒體段時間長(秒)。所以#EXTINF中指定的時間長度必須小於或是等於這個最大值。這個tag在整個PlayList文件中只能出現一 次(在嵌套的情況下,一般有真正ts url 的m3u8纔會出現該tag)
#EXTINF: duration 指定每個媒體段(ts)的持續時間(秒),僅對其後面的URI有效,title是下載資源的url
#EXT-X-ENDLIST 結束列表
這裏我們看到了真正播放的流片段,ts 片,客戶端拿到的就是這個 ts 片,然後不斷下載請求到該片段並連續播放。
有些人可能要問了,那 ts 文件又到底是個什麼東西呢,那就下載來看看,拿着其中的一個 ts 文件瀏覽器打開保存到本地:
發現保存到本地的文件就可以直接打開,其實就是真正的流媒體文件,但是這個文件只是片段,大概只有 10s 的時間。
HLS播放實現時序圖
HLS 直播
HLS 直播原理上還是按點播的方式實現的,通過 http 協議傳輸,生成 ts 索引文件以及 m3u8 索引文件。直播的複雜在於先要採集視頻源和音頻源的數據,然後再進行 H264 編碼和音頻 ACC 編碼,並封裝成 ts 包,其中還要考慮 ts 的分段生成策略。
下一篇我會介紹一篇關於 rtmp 協議的文章。
歡迎指正,Thanks…