流媒體之HLS——綜述(二)


[時間:2018-03] [狀態:Open]
[關鍵詞:流媒體,stream,HLS]

本文是上一篇的后續部分,鏈接如下:HLS協議綜述

2 playlist(m3u8)介紹

HLS中的playlist是一個UTF-8編碼的文本文件,其中包含了URL和描述性標簽。一個常規的playlist如下所示:

#EXT-X-VERSION:3
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:1
 
# Old-style integer duration; avoid for newer clients.
#EXTINF:10,
http://media.example.com/segment0.ts
 
# New-style floating-point duration; use for modern clients.
#EXTINF:10.0,
http://media.example.com/segment1.ts
#EXTINF:9.5,
http://media.example.com/segment2.ts
#EXT-X-ENDLIST

其中以'#'打頭的行都是標簽,HLS標准規定對於標准中未定義的標簽,可以直接忽略;也就是說'#'也可以作為注釋行。這里說明下上面M3U8文件的構成:

  • #EXT-X-VERSION:<n> 表示協議的版本號,而且每個M3U8中只能出現一次該標簽。對於具體版本號的定義,可以參考標准的第7節。
  • #EXTM3U作為M3U文件的標識符,可以用於文件類型識別,這是必須的字段。
  • #EXT-X-TARGETDURATION:<s>表示最長分片的時長,這是必須的字段。
  • #EXT-X-MEDIA-SEQUENCE:<number>表示playlist文件中第一個分片的序列號(整數值)。如果M3U8文件中沒有該字段,則playlist中第一個分片的序列號必須是0。
  • #EXTINF:<duration>,[<title>]表示下一個分片的時長。對於每個分片,必須有該字段。 對於#EXT-X-VERSION小於3的情況下,duration必須是整數;其他情況下duration可以是浮點數和整數。title是一個可選字段,僅用於增強可讀性。
  • #EXT-X-ENDLIST 該字段表示分片結束,不會在playlist文件中添加新的分片。

上面介紹的是最常見的playlist,還有一種playlist,僅包含播放節目列表信息,在HLS中稱為master playlist。其示例如下:

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1, BANDWIDTH=1280000,AVERAGE-BANDWIDTH=1000000, RESOLUTION=720x480
http://example.com/low.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=2, BANDWIDTH=2560000,AVERAGE-BANDWIDTH=2000000, RESOLUTION=1080x720
http://example.com/mid.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=3, BANDWIDTH=7680000,AVERAGE-BANDWIDTH=6000000, RESOLUTION=1920x1080
http://example.com/high.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=4, BANDWIDTH=65000,CODECS="mp4a.40.5"
http://example.com/audio-only.m3u8

其中包含的標簽說明如下:
#EXT-X-STREAM-INF:<attribute-list>用於標識一個Variant Stream,這是由一系列的Redition組成的。該標簽的屬性列表中包含了Variant Stream的描述信息。例如:

  • BANDWIDTH表示Variant Stream中的峰值比特率,單位bits/s。
  • AVERAGE-BANDWIDTH表示Variant Stream中的平均比特率,單位bits/s。
  • CODECS包含Variant Stream中音視頻編碼格式相關的信息,比如上面的"mp4a.40.5"。
  • RESOLUTION包含Variant Stream中對應視頻流的分辨率。
  • FRAME-RATE表示Variant Stream中的視頻幀率。

M3U8中還有一個標簽需要關注下,EXT-X-PLAYLIST-TYPE。該標簽只有兩個值:EVENT、VOD。EVENT指的是分片工具只能在M3U8末尾添加新的分片的信息,但不能刪除老的分片,通常比較適用於直播+錄播的情況(既要提供給客戶端點播功能,也要對實時場景進行錄制,直播完成之后EVENT就自然退化為VOD)。但是對於M3U8中存在#EXT-X-ENDLIST標簽時,可以忽略EXT-X-PLAYLIST-TYPE
還有一種情況,如果M3U8中不存在#EXT-X-ENDLIST以及EXT-X-PLAYLIST-TYPE標簽,則服務器端可以任意更新playlist內容。

到此我們基本介紹了完了M3U8的格式。

3 服務器端和客戶端的主要實現邏輯

HLS之服務器端

在第一部分介紹過,HLS的服務器端包括三個部分:轉碼器、分片器、分發端。對於VOD而言,這三個部分是可以獨立工作的,並不需要太多的配合。但對於直播而言,三者需要密切配合,以保證直播的實時性和流暢度。典型的服務器端邏輯是這樣的:

  1. 將原始音視頻數據或者多媒體素材通過轉碼器編碼復用;
  2. 將復用后的文件切片,並生成對應的M3U8(注意切片應該符合HLS規范);
  3. 為每個切片生成對應的URL,並更新M3U8文件;
  4. 直播需要實時更新Playlist對應的M3U8,點播生成完成之后服務器端不得修改Playlist

HLS之客戶端

從邏輯上來講,HLS客戶端更為簡單。其典型處理邏輯如下:

  1. 通過給定URI獲取 Playlist。若是Master Playlist,客戶端需選擇一個Variant Stream來播放。
  2. 客戶端檢查#EXT-X-VERSION版本是否滿足。
  3. 客戶端應該忽略不可識別的 tags,忽略不可識別的屬性鍵值對。
  4. 加載Media Playlist file,並選擇一個segment開始播放;
  5. 播放完成一個segment之后,根據客戶端當前的具體情況選擇一個新的segment,並重復執行播放操作;
  6. 對於直播,需要定期刷新Media Playlist file,並選擇合適的segment播放。

4 碼率切換的基本邏輯

從HLS協議的定義來看,所有的碼率切換策略都是有客戶端定義的。服務器端僅僅提供幾種可供選擇的碼率。所以主要的碼率切換邏輯也是在客戶端完成。

客戶端判斷是否切換的主要因素如下:

  1. 設備實際下載速度
  2. 設備運行情況(CPU、內存、以及屏幕分辨率)

比較簡單的客戶端會直接根據實際下載速度和Variant Stream標稱的碼率做比較,如果滿足就上切,不滿足就下切。

當然在實際切換時還需要考慮播放器的用戶體驗,最好做到平滑切換,用戶沒有直接的可見的播放卡頓。

5 常見的開源HLS框架

到目前為止,我所遇到的HLS播放框架主要有:ffmpeg中的HLS模塊、AOSP中的HLS模塊。當然在Mac或iOS中原生就支持HLS,不過沒有源碼。

6 總結

后面的文章將中主要關注ffmpeg和AOSP中的HLS相關的實現。同時會給出一個基於ffmpeg搭建的HLS直播系統(本地文件模擬的直播源)。

本文主要簡單總結了HLS協議相關的基礎知識,以及HLS服務器端和客戶端的常規實現邏輯。僅供后續參考及查閱。

參考

  1. APPLE-HLS
  2. IETF-HTTP Live Streaming
  3. HLS 協議詳解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM