使用 FFmpeg 以 VP9 進行直播編碼
編碼參數
VP9 提供一系列參數,可最佳化直播編碼。如要瞭解這些原則的概略資訊,請參閱「位元率模式」。
FFmpeg VP9 編碼範例
下表說明 VP9 編碼的 ffmpeg
呼叫範例參數。
參數 | 說明 |
---|---|
-quality realtime |
realtime 是直播的必要條件,且適用於高於 5 的速度。 |
-speed 6 |
「速度」5 至 8 應適用於即時編碼。數字越小 (5 或 6 ) 品質越高,但需要更多 CPU 運算能力。數字越大 (7 或 8 ) 品質越低,但更適合延遲時間較短的用途,以及 CPU 效能較低的裝置 (例如行動裝置)。 |
-tile-columns 4 |
分格會將影片分割成矩形區域,以便進行多執行緒編碼和解碼。圖塊數量一律為 2 的乘冪。0 = 1 個圖塊、1 = 2、2 = 4、3 = 8、4 = 16、5 = 32。 |
-frame-parallel 1 |
啟用並行解碼功能。 |
-threads 8 |
要使用的執行緒數量上限。 |
-static-thresh 0 |
動作偵測門檻。 |
-max-intra-rate 300 |
最高 I 影格位元率 (百分比) |
-deadline realtime |
-quality realtime 的替代 (舊版) 版本 |
-lag-in-frames 0 |
要延遲的影格數量上限 |
-qmin 4 -qmax 48 |
量化器的最小值和最大值。這裡的值僅供參考,調整此值會以壓縮效率為代價,提高/降低影片品質。 |
-row-mt 1 |
啟用列多執行緒。最多可使用 2 倍的執行緒做為圖塊資料欄。0 = 關閉,1 = 開啟。 |
-error-resilient 1 |
啟用錯誤復原功能。 |
選擇編碼參數
以下資訊使用固定位元率 (CBR) 編碼,進行即時自適應位元率串流 (ABR),其中每個目標速率都會在封裝工具的資訊清單中明確設定。這樣一來,客戶的費率「切換」會更順暢。如果位元率可以更彈性,或編碼正在分塊,您也可以選擇可變位元率 (VBR) 編碼和 CQ 模式。Q 模式無法即時編碼,因此不適合用於直播影片。詳情請參閱「位元率模式」。
如要進一步瞭解如何操作 VP9,也建議參閱隨附的 VOD 設定文章,但請以 CBR 為重點。
提示與秘訣
請注意,直播時所有內容都會受到限制,最低即時編碼速度為 1 倍 (FFmpeg 會在編碼過程中回報編碼速度)。如果編碼速度低於 1 倍,編碼程序就無法跟上即時影像的輸入速度,使用者會遇到緩衝問題,傳輸中斷也會導致直播期間無法使用串流 (但封存檔通常可用)。
編碼參數的實際運作範例
下圖顯示在執行 Linux 的四核心 i5 3.6Ghz 桌機上,以 25 FPS 播放各種影格大小的影片時,CPU 使用率:
目標解析度 | FFmpeg VP9 參數 | CPU / 速度 (範例) |
---|---|---|
3840x2160 (2160p) | -r 30 -g 90 -s 3840x2160 -quality realtime -speed 5 -threads 16 -row-mt 1 -tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 7800k | 約 88% 0.39 倍 |
2560x1440 (1440p) | -r 30 -g 90 -s 2560x1440 -quality realtime -speed 5 -threads 16 -row-mt 1 -tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 6000k | 約 86% 0.68 倍 |
1920x1080 (1080p) | -r 30 -g 90 -s 1920x1080 -quality realtime -speed 5 -threads 8 -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 4500k | ~82% 1.04x |
1280x720 (720p) | -r 30 -g 90 -s 1280x720 -quality realtime -speed 5 -threads 8 -row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 3000k | 約 78% 1.77 倍 |
854x480 (480p) | -r 30 -g 90 -s 854x480 -quality realtime -speed 6 -threads 4 -row-mt 1 -tile-columns 1 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 1800k | ~64% 3.51x |
640x360 (360p) | -r 30 -g 90 -s 640x360 -quality realtime -speed 7 -threads 4 -row-mt 1 -tile-columns 1 -frame-parallel 0 -qmin 4 -qmax 48 -b:v 730k | ~62% 5.27x |
426x240 (240p) | -r 30 -g 90 -s 426x240 -quality realtime -speed 8 -threads 2 -row-mt 1 -tile-columns 0 -frame-parallel 0 -qmin 4 -qmax 48 -b:v 365k | ~66% 8.27x |
FFmpeg 範例如下:
ffmpeg -stream_loop 100 -i /home/id3as/Videos/120s_tears_of_steel_1080p.webm \
-r 30 -g 90 -s 3840x2160 -quality realtime -speed 5 -threads 16 -row-mt 1 \
-tile-columns 3 -frame-parallel 1 -qmin 4 -qmax 48 -b:v 7800k -c:v libvpx-vp9 \
-b:a 128k -c:a libopus -f webm pipe1
提示與秘訣
請注意,我們在這裡輸出至 FIFO 管道 ("pipe1"),執行前應先建立該管道,再執行 FFmpeg 指令。如要這麼做,請在工作目錄中執行
mkfifo pipe1
指令。使用 Shaka Packager 時,系統會將該管道做為指定串流的輸入來源。其他包裝型號可能需要使用不同方法。如要確保系統能辨識
-row-mt
指令,請使用 FFmpeg 的最新穩定版本 (目前為 3.3.3),網址為 https://www.ffmpeg.org/download.html
自動調整位元率設定範例
視執行 FFmpeg 編碼的電腦效能而定,可能無法同時提供下列所有編碼,因此請從清單中選取適合可用資源和目標對象的子集。
FFmpeg 完整 ABR 設定
在理想情況下,我們會結合前一節中列出的編碼範例,建立單一指令,同時產生所有編碼:
ffmpeg -stream_loop 100 -i lakes1080p.mp4 \
-y -r 25 -g 75 -s 3840x2160 -quality realtime -speed 5 -threads 8 \
-tile-columns 2 -frame-parallel 1 \
-b:v 7800k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe1 \
-y -r 25 -g 75 -s 2560x1440 -quality realtime -speed 5 -threads 8 \
-tile-columns 2 -frame-parallel 1 \
-b:v 6000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe2 \
-y -r 25 -g 75 -s 1920x1080 -quality realtime -speed 5 -threads 4 \
-tile-columns 2 -frame-parallel 1 \
-b:v 4500k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe3 \
-y -r 25 -g 75 -s 1280x720 -quality realtime -speed 5 -threads 4 \
-tile-columns 2 -frame-parallel 1 \
-b:v 3000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe4 \
-y -r 25 -g 75 -s 854x480 -quality realtime -speed 6 -threads 4 \
-tile-columns 2 -frame-parallel 1 \
-b:v 2000k -c:v libvpx-vp9 -b:a 196k -c:a libopus -f webm pipe5 \
-y -r 25 -g 75 -s 640x360 -quality realtime -speed 7 -threads 2 \
-tile-columns 1 -frame-parallel 0 \
-b:v 730k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe6 \
-y -r 25 -g 75 -s 426x240 -quality realtime -speed 8 -threads 2 \
-tile-columns 1 -frame-parallel 0 \
-b:v 365k -c:v libvpx-vp9 -b:a 64k -c:a libopus -f webm pipe7
不過,上述完整組合需要非常強大的 CPU,或可能需要硬體 GPU 卸載支援,例如某些晶片組越來越常提供的支援。Intel Kabylake (和後續版本) 具有完整的硬體編碼管道。(請注意,Kabylake GPU 可以進行 8 位元 VP9 編碼,但無法進行 10 位元編碼)。
使用 Shaka Packager 的實用電腦版範例
以常見的桌上型電腦為例,更實用的做法是使用 Shaka Packager。 如要輕鬆設定 Shaka,請使用 Google 的 DockerHub 映像檔,在 Docker 容器中安裝 Shaka。如需操作說明,請參閱:
https://github.com/google/shaka-packager#using-docker-for-testing--development
在本範例中,我們使用的機器具有下列設定:
系統 | Host: obs Kernel: 4.4.0-91-lowlatency x86_64 (64 bit) |
電腦 | Xfce 4.12.3 發行版本:OS:https://ubuntustudio.org/2016/10/ubuntu-studio-16-10-released/ |
CPU | 四核心 Intel Core i5-6500 (-MCP-) 快取:6144 KB 時脈速度:最高:3600 MHz 1:800 MHz 2:800 MHz 3:800 MHz 4:800 MHz |
顯示卡 | Intel Skylake 整合式顯示卡 |
記憶體 | 8 GB RAM |
實際上,這部機器可以最佳化產生下列可用的 ABR 編碼範圍,而 FFmpeg 會持續回報 1 倍的編碼速度:
ffmpeg -stream_loop 100 -i 120s_tears_of_steel_1080p.webm \
-y -r 30 -g 90 -s 1920x1080 -quality realtime -speed 7 -threads 8 \
-row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 \
-b:v 4500k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe1 \
-y -r 30 -g 90 -s 1280x720 -quality realtime -speed 8 -threads 6 \
-row-mt 1 -tile-columns 2 -frame-parallel 1 -qmin 4 -qmax 48 \
-b:v 3000k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe2 \
-y -r 30 -g 90 -s 640x360 -quality realtime -speed 8 -threads 2 \
-row-mt 1 -tile-columns 1 -frame-parallel 1 -qmin 4 -qmax 48 \
-b:v 730k -c:v libvpx-vp9 -b:a 128k -c:a libopus -f webm pipe3
請注意,-speed
設定相當高。這些設定是透過實驗建立,會因機器而異。
Shaka Packager 負荷
封裝作業並不會特別耗用 CPU 資源。即使 FFmpeg 只傳送部分輸出內容,Shaka Packager 仍可設定為監聽所有輸出內容。以下是在上述電腦上測試的封裝工具設定:
packager \
in=pipe1,stream=audio,init_segment=livehd-audio-1080.webm,segment_template=livehd-audio-1080-\$Number\$.webm \
in=pipe1,stream=video,init_segment=livehd-video-1080.webm,template=livehd-video-1080-\$Number\$.webm \
in=pipe2,stream=audio,init_segment=livehd-audio-720.webm,segment_template=livehd-audio-720-\$Number\$.webm \
in=pipe2,stream=video,init_segment=livehd-video-720.webm,template=livehd-video-720-\$Number\$.webm \
in=pipe3,stream=audio,init_segment=livehd-audio-360.webm,segment_template=livehd-audio-360-\$Number\$.webm \
in=pipe3,stream=video,init_segment=livehd-video-360.webm,template=livehd-video-360-\$Number\$.webm \
--mpd_output livehd.mpd --dump_stream_info --min_buffer_time=10 --time_shift_buffer_depth=300 \
--segment_duration=3 --io_block_size 65536