FFmpeg を使用した VP9 によるライブ エンコード

エンコード パラメータ

VP9 には、ライブ エンコードを最適化するためのさまざまなパラメータが用意されています。これらの一般的な原則については、ビットレート モードで説明します。

FFmpeg VP9 エンコードの例

次の表に、VP9 エンコードの ffmpeg 呼び出しの例のパラメータを示します。

パラメータ 説明
-quality realtime realtime は、ライブ配信や 5 を超える速度に不可欠です。
-speed 6 ライブ / リアルタイム エンコードには、速度 58 を使用する必要があります。数値が小さいほど(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 エラー復元機能を有効にします。

エンコード パラメータの選択

以下の情報は、ライブ アダプティブ ビットレート ストリーミング(ABR)に固定ビットレート(CBR)エンコードを使用する場合のものです。この場合、各ターゲット レートはパケージャーのマニフェストで明示的に設定されます。これにより、クライアントの料金間の「切り替え」がより明確になります。ビットレートの柔軟性が高い場合や、エンコードがチャンク化されている場合は、可変ビットレート(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.04 倍
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.51 倍
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.27 倍
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.27 倍

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 コマンドが認識されるようにするには、https://www.ffmpeg.org/download.html から FFmpeg の最新の安定版(現在は 3.3.3)を使用します。

アダプティブ ビットレート セットの例

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 コンテナ内にインストールすることです。手順については、こちらをご覧ください。

https://github.com/google/shaka-packager#using-docker-for-testing--development

この例では、次の構成のマシンを使用しました。

システム ホスト: obs カーネル: 4.4.0-91-lowlatency x86_64(64 ビット)
パソコン 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