一條進來的源流要變成幾十個檔案:多個碼率、多個解析度、可能多個 codec、再乘以 HLS 與 DASH 兩種清單。這個「一變多」的過程是直播成本結構裡最大的計算支出,也是畫質的第二道關卡——源流再好,轉碼階梯設計錯了,多數觀眾看到的仍然是糟糕的畫面。


📖 學

一、三個常被混用的詞

Transcoding(轉碼)——解碼再重新編碼,可以換 codec、換解析度、換碼率。計算成本最高。

Transrating(轉碼率)——只改碼率,解析度與 codec 不變。比完整轉碼便宜,但仍需解碼重編。

Transmuxing/repackaging(轉封裝)——不碰壓縮資料,只把同樣的編碼位元流換一個容器(例如 RTMP 的 FLV 換成 fMP4 分片)。計算成本極低,畫質無損。

實務上最重要的是認出哪些工作其實只需要 transmux。 把一條 1080p H.264 的源流同時輸出 HLS 與 DASH,如果用 CMAF 共用分片,這件事完全不需要重新編碼——它是 transmux。很多系統在這裡做了不必要的轉碼,白燒計算成本又損失畫質。

二、ABR 階梯怎麼設計

階梯(ladder)是一組 (解析度, 碼率) 的組合。一個傳統的固定階梯大概長這樣:

階解析度碼率目標觀眾
11920×10805,000 kbps固網/高速行動
21280×7202,800 kbps一般寬頻
3854×4801,400 kbps行動網路
4640×360800 kbps弱網
5426×240400 kbps極弱網/保底

設計原則:

相鄰階的碼率比控制在 1.5–2 倍。 太近(1.2 倍)等於浪費一階的計算與儲存,觀眾感受不到差別;太遠(3 倍以上)切換時畫質跳變明顯,而且中間頻寬的觀眾被迫選低的那階,浪費可用頻寬。

最低階必須真的能在最差網路跑。 它的作用是「不要黑畫面」,不是好看。

最高階不要超過源流品質。 把 1080p 源流上轉成 4K 階只是浪費,畫質不會變好。

階數要考慮成本。 每多一階就多一份轉碼、儲存與(對 LL-HLS 而言)請求量。低延遲場景通常刻意減少階數,見 ABR 與延遲的交互。

三、Per-title / 內容感知編碼

固定階梯的問題是它假設所有內容的複雜度相同。一場靜態的講座與一場賽車,在 2,800 kbps 下的品質天差地遠:講座可能用 1,200 kbps 就夠了(多花的頻寬純屬浪費),賽車可能 5,000 kbps 還在崩。

Per-title encoding 的作法是先分析內容複雜度,再為這個內容客製階梯。更細的版本是 per-shot/per-scene,以鏡頭為單位調整。

對直播而言,per-title 有一個根本限制:你沒有「整個內容」可以先分析。 點播可以先跑一遍再決定,直播不行。實務上的替代方案是:

  • 以節目類型預設不同階梯(體育一套、談話一套、遊戲一套),這是最簡單也最常見的。
  • 滾動視窗分析:用剛過去的幾秒估計複雜度,動態調整碼率上限。這有效但引入延遲與不穩定性。
  • 接受浪費:在多數規模下,per-title 省下的頻寬未必抵得過系統複雜度。

所以 per-title 在直播的 ROI 明顯低於點播,而供應商常把點播的節省數字(18–22% 量級的說法流傳很廣)直接套用到直播上,這是一個需要警覺的高估,見 主張 vs 可佐證。

四、Packaging:把編碼結果變成可播的東西

打包器(packager)做幾件事:

  1. 把編碼位元流切成分片(必須在 I 幀邊界)。
  2. 包成容器(fMP4 或 TS)。
  3. 產生清單(.m3u8 / .mpd)。
  4. 套用加密(如果有的話)。

第 4 項是安全與打包的交界,也是成本影響最大的一處。 加密在打包階段做,意味著:

  • 用 CMAF + cbcs 模式加密,同一份分片可以同時被 Widevine、PlayReady、FairPlay 解密 → 只需要打包一次。
  • 用舊的分流做法(DASH 用 cenc、HLS 用 SAMPLE-AES),就必須為 FairPlay 單獨打包一份,儲存與 CDN 快取效率都減半。

這是 CMAF 對內容保護最實際的貢獻,詳見 內容保護基礎。

五、轉碼放哪裡:源站 vs 邊緣

集中轉碼(源站)——一個地方轉完,分發出去。簡單、可控,但跨區域的分發距離長。

邊緣轉碼——在靠近觀眾的地方轉。可以省跨區頻寬,但同一個轉碼工作會在多個邊緣重複執行,計算成本乘上區域數。

判準是「轉碼成本 vs 跨區頻寬成本」的比較。多數情況下集中轉碼 + CDN 分發更划算,因為 CDN 的跨區傳輸已經高度優化。邊緣轉碼主要用在需要個體化的場景——例如逐會話的浮水印,那必須在靠近使用者的地方做,而且它的成本模型完全不同(從「每條流一次」變成「每個觀眾一次」),這是 案例拆解 裡一個關鍵的成本警告。

六、一個實際的轉碼成本直覺

假設一條 1080p 源流要出 5 階 ABR:

  • 1080p 的即時 H.264 編碼,軟體(x264 medium)約需 2–4 個現代 CPU 核心。
  • 五階合計(1080p + 720p + 480p + 360p + 240p),低解析度便宜得多,總計約 4–8 核。
  • 硬體編碼(NVENC)可以把這個降到單張卡跑數十路。

所以「要不要用硬體編碼」在規模化時不是品質問題而是數量級問題。 一千路併發的轉碼,用軟體要數千核,用硬體要數十張卡。


🧠 記

先認出哪些工作只需要 transmux,不要做不必要的轉碼。

相鄰階碼率比 1.5–2 倍;最低階負責「不黑畫面」,最高階不要超過源流。

per-title 在直播的 ROI 明顯低於點播,因為沒有完整內容可先分析。

CMAF + cbcs 讓一份分片服務三家 DRM,這是打包階段對成本影響最大的決定。

逐會話個體化(浮水印需要)會把成本模型從「每條流」變成「每個觀眾」,必須單獨計算。


✍️ 實踐

用 FFmpeg 產一組 ABR 階梯並檢查分片邊界,約 30 分鐘:

ffmpeg -re -i input.mp4 \
  -filter_complex "[0:v]split=3[v1][v2][v3]; \
   [v1]scale=1920:1080[v1out];[v2]scale=1280:720[v2out];[v3]scale=854:480[v3out]" \
  -map "[v1out]" -c:v:0 libx264 -b:v:0 5000k -maxrate:v:0 5350k -bufsize:v:0 7500k \
  -map "[v2out]" -c:v:1 libx264 -b:v:1 2800k -maxrate:v:1 2996k -bufsize:v:1 4200k \
  -map "[v3out]" -c:v:2 libx264 -b:v:2 1400k -maxrate:v:2 1498k -bufsize:v:2 2100k \
  -x264-params "keyint=48:min-keyint=48:scenecut=0" \
  -map a:0 -c:a aac -b:a 128k -ac 2 \
  -f hls -hls_time 2 -hls_playlist_type event \
  -master_pl_name master.m3u8 \
  -var_stream_map "v:0,a:0 v:1,a:0 v:2,a:0" \
  stream_%v.m3u8

然後做兩件檢查:

  1. cat stream_0.m3u8,確認 #EXT-X-TARGETDURATION 與實際 #EXTINF 一致。
  2. 把 keyint 改成 100(大於 2 秒 × fps)再跑一次,觀察分片長度會變得不受控——因為切不到 I 幀。

第 2 步是重點:它讓「GOP 必須整除分片長度」從一條規則變成親眼看過的現象。


🔗 延伸學習


相關