M3U8 格式詳解

1. M3U 協(xié)議解析

??M3U8文件是指UTF-8編碼格式的M3U文件。M3U文件是記錄了一個索引純文本文件,打開它時播放軟件并不是播放它,而是根據(jù)它的索引找到對應(yīng)的音視頻文件的網(wǎng)絡(luò)地址進(jìn)行在線播放。

??M3U8是一種常見的流媒體格式,主要以文件列表的形式存在,既支持直播又支持點播,尤其在Android、iOS等平臺最為常用。


#EXTM3U

#EXT-X-VERSION:3

#EXT-X-MEDIA-SEQUENCE:0

#EXT-X-ALLOW-CACHE:YES

#EXT-X-TARGETDURATION:3

#EXTINF:1.969

https://test.com/test0.ts

#EXTINF:1.972

https://test.com/test1.ts

#EXTINF:1.109

https://test.com/test2.ts

#EXT-X-DISCONTINUITY

#EXTINF:2.969

https://test.com/test3.ts

#EXT-X-ENDLIST

tag說明

下面我們說明一下比較常用和關(guān)鍵的幾個字段:
  ? EXTM3U:這個是M3U8文件必須包含的標(biāo)簽,并且必須在文件的第一行,所有的M3U8文件中必須包含這個標(biāo)簽。
  ? EXT-X-VERSION:M3U8文件的版本,常見的是3(目前最高版本應(yīng)該是7)。
  ?EXT-X-TARGETDURATION:該標(biāo)簽指定了單個媒體文件持續(xù)時間的最大值,播放文件列表中的媒體文件在EXTINF標(biāo)簽中定義的持續(xù)時間必須小于或者等于該標(biāo)簽指定的持續(xù)時間。該標(biāo)簽在播放列表文件中必須出現(xiàn)一次。
  ?EXT-X-MEDIA-SEQUENCE:M3U8直播是的直播切換序列,當(dāng)播放打開M3U8時,以這個標(biāo)簽的值作為參考,播放對應(yīng)的序列號的切片。
  ?EXTINF:EXTINF為M3U8列表中每一個分片的duration,如上面例子輸出信息中的第一片的duration為2.969秒。在EXTINF標(biāo)簽中,除了duration值,還可以包含可選的描述信息,主要為標(biāo)注切片信息,使用逗號分隔開。
  ?EXT-X-DISCONTINUITY:需要特別說明的就是這個tag了,表示前一片分片和后一片分片有不連續(xù)。
  ?EXT-X-ENDLIST:若出現(xiàn)EXT-X-ENDLIST標(biāo)簽,則表明M3U8文件不會再產(chǎn)生更多的切片,可以理解為該M3U8已停止更新,并且播放分片到這個標(biāo)簽后結(jié)束。M3U8不僅僅是可以作為直播,也可以作為點播存在,在M3U8文件中保存所有切片信息最后使用EXT-X-ENDLIST結(jié)尾,這個M3U8即為點播M3U8。EXT-X-ENDLIST標(biāo)簽可能會出現(xiàn)在播放列表文件的任何地方,但是不能出現(xiàn)兩次或以上。
  ?EXT-X-STREAM-INF:EXT-X-STREAM-INF標(biāo)簽出現(xiàn)在M3U8時,主要是出現(xiàn)在多級M3U8文件中時,例如M3U8中包含子M3U8列表,或者主M3U8中包含多碼率M3U8時;該標(biāo)簽后需要跟一些屬性,下面就來逐一說明一下這些屬性:
????BANDWIDTH:BANDWIDTH的值為最高碼率值,當(dāng)播放EXT-X-STREAM-INF下對應(yīng)的M3U8時占用的最大碼率(必要參數(shù))。
????AVERAGE-BANDWIDTH:AVERAGE-BANDWIDTH的值為平均碼率值,當(dāng)播放EXT-X-STREAM-INF下對應(yīng)的M3U8時占用的平均碼率。(可選參數(shù))。
????CODECS:CODECS的值用于聲明EXT-X-STREAM-INF下面對應(yīng)M3U8里面的音視頻編碼、視頻編碼的信息(可選參數(shù))。
????RESOLUTION:M3U8中視頻的寬高信息描述(可選參數(shù))。
????FRAME-RATE:子M3U8中的視頻幀率(可選參數(shù))。
  ?#EXT-X-KEY:表示怎么對media segments進(jìn)行解碼。其作用范圍是下次該tag出現(xiàn)前的所有media URI,格式如下:
????#EXT-X-KEY:<attribute-list>:NONE 或者 AES-128。如果是NONE,則URI以及IV屬性必須不存在,如果是AES-128(Advanced EncryptionStandard),則URI必須存在,IV可以不存在。
????對于AES-128的情況,keytag和URI屬性共同表示了一個key文件,通過URI可以獲得這個key,如果沒有 IV(Initialization Vector),則使用序列號作為IV進(jìn)行編解碼,將序列號的高位賦到16個字節(jié)的buffer中,左邊補0;如果 有IV,則將改值當(dāng)成16個字節(jié)的16進(jìn)制數(shù)。
  ?#EXT-X-PROGRAM-DATE-TIME:將一個絕對時間或是日期和一個媒體段中的第一個sample相關(guān)聯(lián),只對下一個meida URI有效,格式如下:
????#EXT-X-PROGRAM-DATE-TIME:<YYYY-MM-DDThh:mm:ssZ>
????For example:
????#EXT-X-PROGRAM-DATE-TIME:2010-02-19T14:54:23.031+08:00
  ?#EXT-X-ALLOW-CACHE:是否允許做cache,這個可以在PlayList文件中任意地方出現(xiàn),并且最多出現(xiàn)一次,作用效果是所有的媒體段。格式如下:
????#EXT-X-ALLOW-CACHE:<YES|NO>
  ?#EXT-X-PLAYLIST-TYPE: 提供關(guān)于PlayList的可變性的信息, 這個對整個PlayList文件有效,是可選的,格式如下:
????#EXT-X-PLAYLIST-TYPE:<EVENT|VOD> :如果是VOD,則服務(wù)器不能改變PlayList 文件;如果是EVENT,則
服務(wù)器不能改變或是刪除PlayList文件中的任何部分,但是可以向該文件中增加新的一行內(nèi)容。

2. HLS 與 M3U8

??HLS(全稱:Http Live Streaming)是由Apple公司定義的用于實時流傳輸?shù)膮f(xié)議,HLS基于HTTP協(xié)議實現(xiàn),傳輸內(nèi)容包括兩部分,一是M3U8描述文件,二是TS媒體文件。

??HLS的優(yōu)勢為:自適應(yīng)碼率流播(adaptive streaming)。效果就是客戶端會根據(jù)網(wǎng)絡(luò)狀況自動選擇不同碼率的視頻流,條件允許的情況下使用高碼率,網(wǎng)絡(luò)繁忙的時候使用低碼率,并且能夠自動在二者之間隨意切換。這對移動設(shè)備網(wǎng)絡(luò)狀況不穩(wěn)定的情況下保障流暢播放非常有幫助。實現(xiàn)方法是服務(wù)器端提供多碼率視頻流,并且在列表文件中注明,播放器根據(jù)播放進(jìn)度和下載速度進(jìn)行自動調(diào)整。

??為什么要用 TS 而不是 MP4?這是因為兩個 TS 片段可以無縫拼接獨立解碼,播放器能連續(xù)播放,而 MP4 文件由于編碼方式的原因,兩段 MP4 不能無縫拼接,播放器連續(xù)播放兩個 MP4 文件會出現(xiàn)破音和畫面間斷,影響用戶體驗。而且如果要在一段長達(dá)一小時的視頻中跳轉(zhuǎn),如果使用單個 MP4 格式的視頻文件,并且也是用 HTTP 協(xié)議,那么需要代理服務(wù)器支持 HTTP range request 獲取大文件中的一部分。這樣的話,對于代理服務(wù)器的性能來說要求較高。而 HTTP Live Streaming 則只需要根據(jù)列表文件中的時間軸找出對應(yīng)的 TS 片段下載即可,不需要 range request,對代理服務(wù)器的要求小很多。所有代理服務(wù)器都支持小文件的高效緩存。

mp4格式轉(zhuǎn)換為ts格式

如果是mp4格式,則可以通過ffmpeg轉(zhuǎn)換為ts格式,命令如下所示:


ffmpeg -i output20.mp4 -codec copy  -hls_list_size 0  -hls_wrap 0 -strict -2  -vbsf h264_mp4toannexb -absf aac_adtstoasc -f hls -hls_base_url https://test.com/ test.m3u8

命令參數(shù)說明:
  ? -hls_time n: 設(shè)置每片的長度,默認(rèn)值為2。單位為秒。即EXTINF tag對應(yīng)的值。hls_time設(shè)置后效果不一定準(zhǔn)確,會受到關(guān)鍵幀大小及其他因素影響。如果需要相對非常準(zhǔn)確的切片,可以添加hls_flags的子參數(shù)split_by_time來保證生成的切片能夠與hls_time設(shè)置的切片時長差不多。split_by_time參數(shù)必須與hls_time配合使用,并且使用split_by_time參數(shù)有可能會影響首畫面體驗,例如花屏或者首畫面顯示慢的問題,因為視頻的第一幀不一定是關(guān)鍵幀。
  ? -hls_list_size n:設(shè)置播放列表保存的最多條目,設(shè)置為0會保存有所片信息,默認(rèn)值為5。為了解決這個問題,需要指定參數(shù)-hls_list_size 0,這樣就能包含所有的片段。
  ? -hls_wrap n:設(shè)置多少片之后開始覆蓋,如果設(shè)置為0則不會覆蓋,默認(rèn)值為0.這個選項能夠避免在磁盤上存儲過多的 片,而且能夠限制寫入磁盤的最多的片的數(shù)量。
  ? -hls_start_number n:設(shè)置播放列表中sequence number的值為number,默認(rèn)值為0。注意:播放列表的sequence number 對每個segment來說都必須是唯一的,而且它不能和片的文件名(當(dāng)使用wrap選項時,文件名有可能會重復(fù)使用)混淆。
  ?h264_mp4toannexb: h264有兩種封裝,一種是annexb模式,傳統(tǒng)模式,有startcode,SPS和PPS是在ES中,vlc里打開編碼器信息中顯示h264;一種是mp4模式,一般mp4 ,mkv會有,沒有startcode,SPS和PPS以及其它信息被封裝在container中,每一個frame前面是這個frame的長度,vlc里打開編碼器信息中顯示avc1。很多解碼器只支持annexb這種模式,因此需要將mp4做轉(zhuǎn)換。
  ?aac_adtstoasc:將AAC編碼器編碼后的原始碼流(ADTS頭 + ES流)封裝為MP4或者FLV或者M(jìn)OV等格式時,需要先將ADTS頭轉(zhuǎn)換為MPEG-4 AudioSpecficConfig (將音頻相關(guān)編解碼參數(shù)提取出來),并將原始碼流中的ADTS頭去掉(只剩下ES流);相反,從MP4或者FLV或者M(jìn)OV等格式文件中解封裝出AAC碼流(只有ES流)時,需要在解析出的AAC碼流前添加ADTS頭(含音頻相關(guān)編解碼參數(shù))。
  ?hls_base_url 參數(shù)用于為M3U8列表的文件路徑設(shè)置前置基本路徑參數(shù),因為在FFmpeg中生成M3U8時寫入的TS切片路徑默認(rèn)為M3U8生成的路徑相同,但是實際上TS所存儲的路徑既可以為本地絕對路徑,也可以為相對路徑,還可以為網(wǎng)絡(luò)路徑,因此使用hls_base_url參數(shù)可以達(dá)到該效果。

ts格式拼接命令


ffmpeg -i 1.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 1.ts
ffmpeg -i 2.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb 2.ts
ffmpeg -i "concat:1.ts|2.ts" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4

歡迎關(guān)注公眾號“音視頻開發(fā)之旅”,一起學(xué)習(xí)成長。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容