M3U8背景介紹
M3U8,用 UTF-8 編碼。"M3U" 和 "M3U8" 文件都是蘋果公司使用的 HTTP Live Streaming(HLS) 協議格式的基礎;是 Unicode 版本的 M3U。
M3U8文件是M3U文件的一種,只不過它的編碼格式是UTF-8。M3U使用Latin-1字符集編碼。M3U的全稱是Moving Picture Experts Group Audio Layer 3 Uniform Resource Locator,即mp3 URL。M3U是純文本文件;
所以UTF-8編碼的M3U文件也簡稱為 M3U8;
HLS 是一個由蘋果公司提出的基于 HTTP 的流媒體網絡傳輸協議。M3U8只是它具體的表現形式,下面我們都稱為HLS格式。
HLS 的工作原理是把整個流分成一個個小的基于 HTTP 的文件來下載,每次只下載一些。當媒體流正在播放時,客戶端可以選擇從許多不同的備用源中以不同的速率下載同樣的資源,允許流媒體會話適應不同的數據速率。在開始一個流媒體會話時,客戶端會下載一個包含元數據的 extended M3U (m3u8) playlist文件,用于尋找可用的媒體流。
HLS 只請求基本的 HTTP 報文,與實時傳輸協議(RTP)不同,HLS 可以穿過任何允許 HTTP 數據通過的防火墻或者代理服務器。它也很容易使用內容分發網絡來傳輸媒體流。這是HLS應用在直播上的一大優勢。
如果在直播中使用HLS技術,那么執行流程如下:圖片來源于蘋果官網;
我們播放一個HLS,首先要對HLS流對應的M3U8文件進行解析,解析M3U8文件,首先要搞清楚M3U8的封裝格式。
音視頻開發資料包:音視頻流媒體高級開發
FFmpegWebRTCRTMPRTSPHLSRTP播放器
M3U8格式解析
HLS流可以用于直播,也可以用于點播;這點很重要,開頭的那張圖千萬別讓你誤會,M3U8是可以用作點播的。
M3U8 文件實質是一個播放列表(playlist),其可能是一個媒體播放列表(Media Playlist),或者是一個主列表(Master Playlist)。
1.M3U8類型
當 M3U8 文件作為媒體播放列表(Media Playlist)時,其內部信息記錄的是一系列媒體片段資源,順序播放該片段資源,即可完整展示多媒體資源。其格式如下所示:
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXTINF:9.009,
http://media.example.com/first.ts
#EXTINF:9.009,
http://media.example.com/second.ts
#EXTINF:3.003,
http://media.example.com/third.ts
#EXT-X-ENDLIST
當 M3U8 作為主播放列表(Master Playlist)時,其內部提供的是同一份媒體資源的多份流列表資源。其格式如下所示:
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=150000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/low/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=240000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/lo_mid/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=440000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/hi_mid/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=640000,RESOLUTION=640x360,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/high/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=64000,CODECS="mp4a.40.5"
http://example.com/audio/index.m3u8
#EXT-X-ENDLIST
2.M3U8基本字段
#EXTM3U M3U8文件頭,必須放在第一行;
#EXT-X-MEDIA-SEQUENCE 第一個TS分片的序列號,一般情況下是0,但是在直播場景下,這個序列號標識直播段的起始位置; #EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION 每個分片TS的最大的時長; #EXT-X-TARGETDURATION:10 每個分片的最大時長是 10s
#EXT-X-ALLOW-CACHE 是否允許cache; #EXT-X-ALLOW-CACHE:YES #EXT-X-ALLOW-CACHE:NO 默認情況下是YES
#EXT-X-ENDLIST M3U8文件結束符;
#EXTINF extra info,分片TS的信息,如時長,帶寬等;一般情況下是 #EXTINF:<duration>,[<title>] 后面可以跟著其他的信息,逗號之前是當前分片的ts時長,分片時長 移動要小于 #EXT-X-TARGETDURATION 定義的值;
#EXT-X-VERSION M3U8版本號
#EXT-X-DISCONTINUITY 該標簽表明其前一個切片與下一個切片之間存在中斷。下面會詳解
#EXT-X-PLAYLIST-TYPE 表明流媒體類型;
#EXT-X-KEY 是否加密解析, #EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=52" 加密方式是AES-128,秘鑰需要請求 https://priv.example.com/key.php?r=52 ,請求回來存儲在本地;
3.如何判斷M3U8是否直播
- 1.判斷是否存在 #EXT-X-ENDLIST
對于一個M3U8文件,如果結尾不存在 #EXT-X-ENDLIST,那么一定是 直播,不是點播;
- 2.判斷 #EXT-X-PLAYLIST-TYPE 類型
'#EXT-X-PLAYLIST-TYPE' 有兩種類型,
VOD 即 Video on Demand,表示該視頻流為點播源,因此服務器不能更改該 M3U8 文件;
EVENT 表示該視頻流為直播源,因此服務器不能更改或刪除該文件任意部分內容(但是可以在文件末尾添加新內容)(注:VOD 文件通常帶有 EXT-X-ENDLIST 標簽,因為其為點播片源,不會改變;而 EVEVT 文件初始化時一般不會有 EXT-X-ENDLIST 標簽,暗示有新的文件會添加到播放列表末尾,因此也需要客戶端定時獲取該 M3U8 文件,以獲取新的媒體片段資源,直到訪問到 EXT-X-ENDLIST 標簽才停止)。
4.M3U8多碼率
上面的Master Playlist 就是會提供 多碼率的列表資源,如下:
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=150000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/low/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=240000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/lo_mid/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=440000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/hi_mid/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=640000,RESOLUTION=640x360,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/high/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=64000,CODECS="mp4a.40.5"
http://example.com/audio/index.m3u8
#EXT-X-ENDLIST
'#EXT-X-STREAM-INF' 字段后面有:
BANDWIDTH 指定碼率
RESOLUTION 分辨率
PROGRAM-ID 唯一ID
CODECS 指定流的編碼類型
碼率、碼流是同一個概念,是數據傳輸時單位時間傳送的數據量,一般用單位kbps表示。
視頻碼率就是指視頻文件在單位時間內使用的數據量。簡單理解就是要播放一秒的視頻需要多少數據,從這個角度就不難理解通常碼率越高視頻質量也越好,相應的文件體積也會越大。碼率、視頻質量、文件體積是正相關的。但當碼率超過一定數值后,對圖像的質量影響就不大了。幾乎所有的編碼算法都在追求用最低的碼率達到最少的失真(最好的清晰度)。
5.如何在M3U8中插入廣告
M3U8文件中插入廣告,要想靈活的控制廣告,則廣告可以插入任何視頻中,那么無法保證廣告的編碼格式和碼率等信息和原視頻的編碼格式等信息保持一致,就必須告知播放器,在插入廣告的地方,ts片段發生的信息變更,需要播放器適配處理。
'#EXT-X-DISCONTINUITY' 該標簽表明其前一個切片與下一個切片之間存在中斷。說明有不連續的視頻出現,這個視頻絕大多數情況下就是廣告; '#EXT-X-DISCONTINUITY' 這個字段就是來做這個事情的;
下面展示一個插入廣告的例子:
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
movieA.ts
#EXTINF:10.0,
movieB.ts
...
#EXT-X-ENDLIST
想在開頭插入廣告:
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
ad0.ts
#EXTINF:8.0,
ad1.ts
#EXT-X-DISCONTINUITY
#EXTINF:10.0,
movieA.ts
#EXTINF:10.0,
movieB.ts
...
#EXT-X-ENDLIST
當然你可以在任意位置插入廣告。
HLS協議草案:HLS協議中還有很多字段,但是有些字段其實就是協議,在實際應用中并不大;大家可以參考看看;
https://tools.ietf.org/html/rfc8216
M3U8實戰
將一個mp4視頻轉化為m3u8視頻:
ffmpeg -re -i test.mp4 -c copy -f hls -bsf:v h264_mp4toannexb test.m3u8
生成了一個m3u8和很多ts分片:
但是生成的test.m3u8發現了問題,如下,才有5個分片。這是因為ffmpeg 默認的list size 為5,所以只獲得最后的5個片段。
要想解決這個問題,需要指定參數-hls_list_size 0,這樣就能包含所有的片段。加上 -hls_list_size 0
ffmpeg -re -i test.mp4 -c copy -f hls -hls_list_size 0 -bsf:v h264_mp4toannexb test.m3u8
為什么還要加上參數-bsf:v h264_mp4toannexb ?
這個參數的作用是將MP4中的H.264數據轉換成為H.264 AnnexB標準的編碼,AnnexB標準的編碼常見于實時傳輸流中。如果源文件為FLV、TS等可以作為直播傳輸流的視頻,則不需要這個參數。
這也非常強烈地說明了MP4不是流式文件,不能作為直播使用。
學習思考
1.視頻廣告
目前M3U8視頻占我們線上視頻的比例是近60%,量非常大,我們可以在M3U8視頻中任意位置插入一些廣告,為探索商業化開辟新的路。
2.為什么M3U8中分片使用TS不用MP4
這是因為兩個 TS 片段可以無縫拼接,播放器能連續播放,而 MP4 文件由于編碼方式的原因,兩段 MP4 不能無縫拼接,播放器連續播放兩個 MP4 文件會出現破音和畫面間斷,影響用戶體驗。而且如果要在一段長達一小時的視頻中跳轉,如果使用單個 MP4 格式的視頻文件,如果也用 HTTP 協議,那么需要代理服務器支持 HTTP range request 獲取大文件中的一部分。這樣的話,對于代理服務器的性能來說要求較高。而 HTTP Live Streaming 則只需要根據列表文件中的時間軸找出對應的 TS 片段下載即可,不需要 range request,對代理服務器的要求小很多。所有代理服務器都支持小文件的高效緩存。