多媒體文件格式(三):M3U8 格式

1、M3U8 格式標準介紹

M3U8文件是指UTF-8編碼格式的M3U文件。M3U文件是記錄了一個索引純文本文件,打開它時播放軟件並非播放它,而是根據它的索引找到對應的音視頻文件的網絡地址進行在線播放。緩存

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

下面是CCTV6直播播放地址:http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8的M3U8的文件列表:網絡

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:35232
#EXT-X-TARGETDURATION:10
#EXTINF:10.000,
cctv6hd-1549272376000.ts
#EXTINF:10.000,
cctv6hd-1549272386000.ts
#EXTINF:10.000,
cctv6hd-1549272396000.ts
#EXTINF:10.000,
cctv6hd-1549272406000.ts
#EXTINF:10.000,
cctv6hd-1549272416000.ts
#EXTINF:10.000,
cctv6hd-1549272426000.ts

下面咱們來分別說明一下相關的幾個字段:性能

  • EXTM3U:這個是M3U8文件必須包含的標籤,而且必須在文件的第一行,全部的M3U8文件中必須包含這個標籤。
  • EXT-X-VERSION:M3U8文件的版本,常見的是3(目前最高版本應該是7)。
  • EXT-X-TARGETDURATION:該標籤指定了媒體文件持續時間的最大值,播放文件列表中的媒體文件在EXTINF標籤中定義的持續時間必須小於或者等於該標籤指定的持續時間。該標籤在播放列表文件中必須出現一次。
  • EXT-X-MEDIA-SEQUENCE:M3U8直播是的直播切換序列,當播放打開M3U8時,以這個標籤的值做爲參考,播放對應的序列號的切片。
  • EXTINF:EXTINF爲M3U8列表中每個分片的duration,如上面例子輸出信息中的第一片的duration爲10秒。在EXTINF標籤中,除了duration值,還能夠包含可選的描述信息,主要爲標註切片信息,使用逗號分隔開。

關於客戶端播放M3U8的標準還有更多的講究,下面咱們來介紹一些:優化

  1. 分片必須是動態改變的,序列不能相同,而且序列必須是增序的。
  2. 當M3U8沒有出現EXT-X-ENDLIST標籤時,不管這個M3U8列表中有多少分片,播放分片都是從倒數第三片開始播放,若是不滿三片則不該該播放。固然若是有些播放器作了特別定製了,則能夠不遵守這個原則。
  3. 以播放當前分片的duration時間刷新M3U8列表,而後作對應的加載動做。
  4. 前一片分片和後一片分片有不連續的時候,播放可能會出錯,那麼須要X-DISCONTINUTY標籤來解決這個錯誤。
  5. 若是播放列表在刷新以後與以前的列表相同,那麼在播放當前分片duration一半的時間內在刷新一次。

在上面,咱們提到了,一些上面例子沒有出現的一些標籤字段,下面咱們針對一些額外的標籤作一些補充說明:ui

  • EXT-X-ENDLIST:若出現EXT-X-ENDLIST標籤,則代表M3U8文件不會再產生更多的切片,能夠理解爲該M3U8已中止更新,而且播放分片到這個標籤後結束。M3U8不只僅是能夠做爲直播,也能夠做爲點播存在,在M3U8文件中保存全部切片信息最後使用EXT-X-ENDLIST結尾,這個M3U8即爲點播M3U8。EXT-X-ENDLIST標籤可能會出如今播放列表文件的任何地方,可是不能出現兩次或以上。
  • EXT-X-STREAM-INF:EXT-X-STREAM-INF標籤出如今M3U8時,主要是出如今多級M3U8文件中時,例如M3U8中包含子M3U8列表,或者主M3U8中包含多碼率M3U8時;該標籤後須要跟一些屬性,下面就來逐一說明一下這些屬性:
    1. BANDWIDTH:BANDWIDTH的值爲最高碼率值,當播放EXT-X-STREAM-INF下對應的M3U8時佔用的最大碼率(必要參數)。
    2. AVERAGE-BANDWIDTH:AVERAGE-BANDWIDTH的值爲平均碼率值,當播放EXT-X-STREAM-INF下對應的M3U8時佔用的平均碼率。(可選參數)。
    3. CODECS:CODECS的值用於聲明EXT-X-STREAM-INF下面對應M3U8裏面的音視頻編碼、視頻編碼的信息(可選參數)。
    4. RESOLUTION:M3U8中視頻的寬高信息描述(可選參數)。
    5. FRAME-RATE:子M3U8中的視頻幀率(可選參數)。

2、HLS 與 M3U8 

HLS(全稱:Http Live Streaming)是由Apple公司定義的用於實時流傳輸的協議,HLS基於HTTP協議實現,傳輸內容包括兩部分,一是M3U8描述文件,二是TS媒體文件。編碼

HLS的優點爲:自適應碼率流播(adaptive streaming)。效果就是客戶端會根據網絡情況自動選擇不一樣碼率的視頻流,條件容許的狀況下使用高碼率,網絡繁忙的時候使用低碼率,而且可以自動在兩者之間隨意切換。這對移動設備網絡情況不穩定的狀況下保障流暢播放很是有幫助。實現方法是服務器端提供多碼率視頻流,而且在列表文件中註明,播放器根據播放進度和下載速度進行自動調整。url

爲何要用 TS 而不是 MP4?這是由於兩個 TS 片斷能夠無縫拼接,播放器能連續播放,而 MP4 文件因爲編碼方式的緣由,兩段 MP4 不能無縫拼接,播放器連續播放兩個 MP4 文件會出現破音和畫面間斷,影響用戶體驗。並且若是要在一段長達一小時的視頻中跳轉,若是使用單個 MP4 格式的視頻文件,而且也是用 HTTP 協議,那麼須要代理服務器支持 HTTP range request 獲取大文件中的一部分。這樣的話,對於代理服務器的性能來講要求較高。而 HTTP Live Streaming 則只須要根據列表文件中的時間軸找出對應的 TS 片斷下載便可,不須要 range request,對代理服務器的要求小不少。全部代理服務器都支持小文件的高效緩存。spa

3、FFmpeg轉HLS文件(M3U8)實戰

1. FFmpeg轉MP4爲HLS(M3U8)文件

將MP4文件轉換成HLS(M3U8)命令行:命令行

ffmpeg -re -i 好漢歌.mp4 -c copy -f hls -bsf:v h264_mp4toannexb output.m3u8

能夠看到生成的M3U8及相應的ts文件:

查看一下生成的M3U8文件:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:19
#EXTINF:10.000000,
output19.ts
#EXTINF:10.000000,
output20.ts
#EXTINF:9.280000,
output21.ts
#EXTINF:4.120000,
output22.ts
#EXTINF:2.440000,
output23.ts
#EXT-X-ENDLIST

細心的人可能發現一個問題,就是生成的m3u8文件裏只有最後的五個片斷的信息。這是由於ffmpeg 默認的list size 爲5,因此只得到最後的5個片斷。爲了解決這個問題,須要指定參數-hls_list_size 0,這樣就能包含全部的片斷。

下面是優化後的命令行:

ffmpeg -re -i 好漢歌.mp4 -c copy -f hls -hls_list_size 0 -bsf:v h264_mp4toannexb output.m3u8

這時,咱們能夠看到從output0.ts到output23.ts的文件列表了。

可能有人會發現,不管是優化以前的命令行,仍是優化後的命令行都有一個參數-bsf:v h264_mp4toannexb,這個參數的做用是將MP4中的H.264數據轉換成爲H.264 AnnexB標準的編碼,AnnexB標準的編碼常見於實時傳輸流中。若是源文件爲FLV、TS等能夠做爲直播傳輸流的視頻,則不須要這個參數。

下面咱們逐一介紹下使用FFmpeg生成HLS時還能夠配置的其餘參數。

4、FFmpeg 轉 HLS (M3U8) 文件命令參數

1. start_number 參數

start_number 參數用於設置M3U8列表中的第一片的序列數。

下面的例子中,咱們使用start_number參數設置M3U8中的第一片序列書爲100,命令行以下:

ffmpeg -re -i huijia.mp4 -c copy -f hls -start_number 100 -hls_list_size 0 -bsf:v h264_mp4toannexb output.m3u8

輸出的M3U8內容以下:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:100
#EXTINF:3.000000,
output100.ts
#EXTINF:3.000000,
output101.ts
#EXTINF:3.000000,
output102.ts
#EXTINF:3.000000,
output103.ts
#EXTINF:3.000000,
output104.ts
#EXTINF:3.000000,
output105.ts
#EXTINF:3.000000,
output106.ts
#EXTINF:1.000000,
output107.ts
#EXT-X-ENDLIST

從輸出能夠看出,切片的第一片編號是100,上面的命令行參數的-start_number參數已生效。

2. hls_time 參數

hls_time參數用於設置M3U8列表中切片的duration。

下面的例子中,咱們使用hls_time參數設置M3U8的TS文件的每一片時長爲9秒左右。命令行以下:

ffmpeg -re -i huijia.mp4 -c copy -f hls -hls_time 9 -hls_list_size 0 -bsf:v h264_mp4toannexb output.m3u8 

而後查看輸出的M3U8內容以下:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:9
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:9.000000,
output0.ts
#EXTINF:9.000000,
output1.ts
#EXTINF:4.000000,
output2.ts
#EXT-X-ENDLIST

能夠看到TS的文件每一片的時常都是9秒左右,hls_time參數生效。

( 注意:hls_time設置後效果不必定準確,會受到關鍵幀大小及其餘因素影響。)

若是須要相對很是準確的切片,能夠添加hls_flags的子參數split_by_time來保證生成的切片可以與hls_time設置的切片時長差很少。

( 注意:split_by_time參數必須與hls_time配合使用,而且使用split_by_time參數有可能會影響首畫面體驗,例如花屏或者首畫面顯示慢的問題,由於視頻的第一幀不必定是關鍵幀。)

3. hls_list_size 參數

hls_list_size參數用於爲M3U8列表中的TS切片的個數。其中設置爲0的時候,將包含全部。

這個命令,咱們在第3節優化MP4轉HLS文件的命令行時使用到了。

下面的例子中,咱們使用hls_list_size參數設置只保留2片TS切片。命令行以下:

ffmpeg -re -i huijia.mp4 -c copy -f hls -hls_list_size 2 -bsf:v h264_mp4toannexb output.m3u8 

查看輸出的M3U8內容以下:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:6
#EXTINF:3.000000,
output6.ts
#EXTINF:1.000000,
output7.ts
#EXT-X-ENDLIST

從輸出的M3U8內容能夠看出,在M3U8文件中只保留了2片TS的文件信息,能夠看出hls_list_size設置生效了。

4. hls_base_url參數

hls_base_url 參數用於爲M3U8列表的文件路徑設置前置基本路徑參數,由於在FFmpeg中生成M3U8時寫入的TS切片路徑默認爲M3U8生成的路徑相同,可是實際上TS所存儲的路徑既能夠爲本地絕對路徑,也能夠爲相對路徑,還能夠爲網絡路徑,所以使用hls_base_url參數能夠達到該效果,命令行以下:

ffmpeg -re -i huijia.mp4 -c copy -f hls -hls_base_url /Users/renhui/Desktop/test/ -bsf:v h264_mp4toannexb output.m3u8

查看輸出的M3U8內容以下:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:3
#EXTINF:3.000000,
/Users/renhui/Desktop/test/output3.ts
#EXTINF:3.000000,
/Users/renhui/Desktop/test/output4.ts
#EXTINF:3.000000,
/Users/renhui/Desktop/test/output5.ts
#EXTINF:3.000000,
/Users/renhui/Desktop/test/output6.ts
#EXTINF:1.000000,
/Users/renhui/Desktop/test/output7.ts
#EXT-X-ENDLIST

能夠看到,TS的路徑變爲絕對路徑了,使用ffplay output.m3u8播放,看到播放是可以正常播放的。這樣就能夠說明hls_base_url生效了。

相關文章
相關標籤/搜索