iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
Software Development

下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練系列 第 9

Day 09:Master playlist vs Media playlist——為什麼有時候要多繞一層

  • 分享至 

  • xImage
  •  

前言:「抓到清單」不代表「抓到片段列表」

昨天講的是最單純的情況:一份 M3U8 清單裡直接列著片段網址。但實務上常常打開一份 M3U8,裡面沒有任何 #EXTINF 或片段網址,只有幾行指向「其他 M3U8 清單」的連結——第一次遇到這種情況,很容易誤以為解析邏輯壞了。

今日目標

  • 分清楚 Master playlist 跟 Media playlist 的差別
  • 理解為什麼會有這種兩層結構
  • 看懂怎麼判斷拿到的是哪一種、該不該再往下多繞一層

兩種清單,兩種用途

  • Master playlist:列出「同一段內容的不同版本」(例如不同畫質、不同碼率),本身不包含任何片段,只包含指向各個版本各自 Media playlist 的連結
  • Media playlist:真正列出片段網址跟長度的那份清單,就是昨天講的結構

一份典型的 Master playlist 長這樣:

#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1280000,RESOLUTION=640x360
low/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2560000,RESOLUTION=1280x720
high/index.m3u8

這份清單本身沒有任何片段,low/index.m3u8high/index.m3u8 才是真正的 Media playlist。

判斷邏輯:有沒有片段,決定要不要再往下繞

async def get_playlist(url: str):
    while True:
        content = await fetch(url)
        parsed = parse_m3u8(content, url)

        if len(parsed.segments) > 0:
            return parsed  # 這是 Media playlist,可以直接用

        # 沒有片段,代表這是 Master playlist,取第一個版本繼續往下解析
        url = resolve_url(parsed.playlists[0])

這段邏輯的關鍵判斷準則很單純:解析出來的清單裡有沒有實際的片段。有,代表已經是最終的 Media playlist;沒有,代表拿到的是 Master playlist,要挑一個版本繼續往下解析,直到真的拿到片段為止。

要說明的是,「用有沒有片段來判斷該不該再往下繞」是這裡採用的實作判斷,不是規格條文本身逐字定義的演算法——規格只定義了 Master/Media playlist 各自該有的標籤與結構,怎麼從解析結果推導出「這是哪一種、下一步該怎麼做」,是實作者依據結構特性自己導出的邏輯。

這個坑會怎麼咬人

如果程式碼沒意識到有兩種清單,看到「解析結果裡片段數量是零」,很容易誤判成「這個內容沒有片段可下載」,直接跳過、留下一份空的輸出,而不是繼續往下解析。這種問題不會拋例外、不會當機,只會安靜地產出一份不完整的結果——是最難被發現的那種錯誤。

今日思考題

你處理過的資料格式裡,有沒有類似「一層索引指向另一層索引」的巢狀結構?你的解析邏輯有沒有明確處理「已經到底層」跟「還要再往下繞一層」這兩種情況?

今日重點回顧

  • Master playlist 只列出「有哪些版本」,Media playlist 才是真正的片段清單
  • 判斷該不該繼續往下繞的依據:解析結果裡有沒有實際片段
  • 忽略這層巢狀結構的後果通常不是報錯,而是安靜產出不完整的結果

明日預告

明天進入加密片段:AES-128 加密的片段,金鑰跟初始向量(IV)從哪裡取得。


上一篇
Day 08:M3U8 索引清單的基本結構,不只是一份 URL 清單
下一篇
Day 10:AES-128 加密的片段,金鑰跟初始向量(IV)從哪裡來
系列文
下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言