HLS 串流完整指南
HLS 是當今網路影音傳輸的骨幹,從 YouTube 到各大電視台直播都靠它運作。這頁從協定設計的「為什麼」出發,帶你看懂播放清單的每個標籤,並實際示範如何用 FFmpeg 建立自己的 HLS 服務。如果你只是想播一個 m3u8,可先看播放器指南。
操作步驟
-
準備來源影片
準備一個 MP4 或其他格式的影片檔。若要從現有串流轉換,來源也可以是 m3u8 網址。
-
用 FFmpeg 切割
執行
ffmpeg -i input.mp4 -c copy -f hls -hls_time 10 -hls_playlist_type vod output.m3u8,會產生一個 m3u8 與多個 ts 片段。-hls_time 10表示每段 10 秒。 -
架設網頁播放器
把產生的檔案放到網頁伺服器,用 hls.js 或支援 HLS 的播放器載入 m3u8 網址即可。別忘了設定 CORS 標頭。
HLS 為什麼會被設計出來
HLS 由 Apple 在 2009 年提出,當時的串流技術(如 RTMP、RTSP)各有痛點:需要專用伺服器、難以穿透防火牆、擴展成本高。
HLS 的核心洞見很簡單:與其發明新的傳輸協定,不如用已經無所不在的 HTTP。具體做法是把影片切成小片段,每個片段都是一個普通檔案,用一般的 HTTP 請求下載。這樣一來:
- 任何網頁伺服器都能提供服務,不需要串流軟體
- 可以直接用 CDN 快取與加速,擴展成本大幅降低
- 能穿透企業防火牆(看起來就像普通網頁請求)
- 播放器可依網速選擇畫質,實現自適應位元率
這個設計如此成功,以至於十多年後的今天,HLS 仍是網路直播與隨選影片的主流選擇。
播放清單結構與標籤
M3U8 播放清單是純文字檔,每一行以 # 開頭的是標籤(指令),其餘是檔案路徑。以下是一個完整的 Media Playlist 範例:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="key.bin"
#EXTINF:10.0,
segment-000.ts
#EXTINF:10.0,
segment-001.ts
#EXTINF:9.8,
segment-002.ts
#EXT-X-ENDLIST常用標籤說明:
| 標籤 | 作用 |
|---|---|
#EXTM3U | 固定開頭,表示這是 M3U 格式。 |
#EXT-X-VERSION | HLS 協定版本,影響可用的標籤。 |
#EXT-X-TARGETDURATION | 單一片段的最大秒數(取整數)。播放器據此決定緩衝策略。 |
#EXT-X-MEDIA-SEQUENCE | 第一個片段的序號。直播時會遞增,用於滑動視窗。 |
#EXT-X-KEY | 標示片段加密方式與金鑰位置。有這個標籤就代表內容受保護。 |
#EXTINF | 標示下一個片段的秒數,是唯一的必要標籤。 |
#EXT-X-ENDLIST | 表示播放清單已完整。有這個標籤是隨選影片,沒有則是直播。 |
想實際看看真實串流的結構?用串流檢測工具貼上網址,就能看到片段數量、目標長度與加密狀態。
Master 與 Media:兩層結構
HLS 採用兩層清單設計,這是實現「自適應位元率」的關鍵:
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080
1080p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720
720p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=854x480
480p/index.m3u8這是 Master Playlist,它不包含片段,而是指向不同畫質的 Media Playlist。播放器讀取後就知道有哪些畫質可選,並依網速切換。
| 清單類型 | 內容 |
|---|---|
| Master Playlist | 列出所有可選畫質,每項指向一個 Media Playlist。標籤為 #EXT-X-STREAM-INF。 |
| Media Playlist | 單一畫質的片段清單,記載每個片段的位置與秒數。 |
當你貼上 Master 網址時,播放器會顯示畫質選單;貼上 Media 網址時則只播那個畫質。這也是判斷網址類型的方法。
實作:用 FFmpeg 建立 HLS 服務
最簡單的方式是用 FFmpeg 把現有影片轉成 HLS:
# 單一畫質(最簡單)
ffmpeg -i input.mp4 -c copy -f hls \
-hls_time 10 -hls_playlist_type vod \
output.m3u8若要產生多畫質(Master Playlist),需要分別轉出各畫質再手動建立 Master:
# 1080p
ffmpeg -i input.mp4 -vf scale=1920:1080 -c:v libx264 \
-b:v 5000k -c:a aac -b:a 128k -f hls \
-hls_time 10 -hls_playlist_type vod 1080p/index.m3u8
# 720p
ffmpeg -i input.mp4 -vf scale=1280:720 -c:v libx264 \
-b:v 2500k -c:a aac -b:a 128k -f hls \
-hls_time 10 -hls_playlist_type vod 720p/index.m3u8部署注意事項:
- MIME 類型:
.m3u8要設為application/vnd.apple.mpegurl,.ts設為video/mp2t。 - CORS 標頭:若播放器與影片不同網域,必須設定
Access-Control-Allow-Origin。 - 快取策略:VOD 的片段可長期快取,但 m3u8 要設短快取(直播則不可快取)。
- HTTPS:若網頁是 HTTPS,串流也必須是 HTTPS,否則瀏覽器會阻擋(混合內容)。
更完整的 FFmpeg 參數與錯誤排除,請見 FFmpeg M3U8 指令集。
HLS 與其他串流技術比較
| 技術 | 延遲 | 特性與適用場景 |
|---|---|---|
| HLS | 6-30 秒 (LL-HLS 約 2 秒) | 相容性最佳,Apple 原生支援,可穿透防火牆,CDN 友善。直播與 VOD 皆適用。 |
| MPEG-DASH | 與 HLS 相近 | 開放標準,Android 生態較常見。與 HLS 原理相似,常與 HLS 並行提供。 |
| WebRTC | 低於 1 秒 | 超低延遲,適合視訊通話、互動直播。但架構複雜、CDN 成本高、不適合大規模單向播放。 |
| RTMP | 2-5 秒 | 舊技術,需要專用伺服器,無法穿透防火牆。現多用於「推流端」,再由伺服器轉成 HLS。 |
選擇原則:如果你的目標是「大量使用者、各種裝置都能看」,選 HLS;如果需要「即時互動、延遲低於 1 秒」,選 WebRTC。沒有最好的技術,只有最適合場景的技術。