ハードウェア支援がまだ未実装の新し目のコーデックを使った動画のエンコードはとにかく時間が掛かりますが、その解決策の一つに分割エンコードというものがあります。エンコード前の動画を一定のルールで分割して、分割した動画を同時に並行してエンコードするというものです。今回は、分割エンコーディングツールである『AV1an』を使用して、分割エンコーディングの実力を試したいと思います。

『AV1an』とは

各種AV1エンコーダーの分割エンコーディングをサポートした便利なオープンソースのツールです。以下、GitHubリンクから入手することが可能です。

『AV1an』(https://github.com/master-of-zen/Av1an

Windowsバイナリが配布されていますが、環境設定起因のエラーの解消が難しかったため、ビルドから実行しようとしましたが、どうやってもビルドが通らなかったため、WSL2上のUbuntuでビルドをします(cargo install av1anでもインストール出来るようですが、最新のバージョンを取得してこないため、ビルドをします)。

Windowsで試してみたい方は、以下リンク先を参考にしてビルドにチャレンジしてみて下さい。

Windows上での『AV1an』のビルド方法(https://www.reddit.com/r/AV1/comments/s8151l/how_to_compile_av1an_on_windows_without_breaking/

『AV1an』をUbuntu上でビルドする

前述のようにWindowsでのビルドはうまく行かなかったため、WSL2上のUbuntuでビルドしていきます。まずはビルドにあたっての準備です。

1.Rustのインストール

Av1anのビルドにはRustが必要なため、Rustをインストールします。以下は、RustをインストールするためのCargoコマンドとなります。

sudo curl https://sh.rustup.rs -sSf | sh

2.各種パッケージのインストール

ビルドに必要なパッケージをaptコマンドでインストールします。

sudo apt install build-essential make pkg-config python3 cython3 autoconf automake libtool clang libavdevice-dev libavformat-dev libavfilter-dev libavutil-dev ffmpeg curl nasm python3-pip

3.VapourSynthをインストールします

エンコード用の元動画を分割するために必要なVapourSynthをインストールします。Pythonのライブラリのため、pipコマンドでインストールします。

pip install vapoursynth

これで準備は整いました。では、いよいよAV1anをビルドしていきます。

4.『AV1an』のビルド

Githubからソースを取得した後、cargoコマンドでビルドします。

cargo build --release

以上で『AV1an』のビルドは完了です。

エンコードの準備

次にエンコードの準備をしていきます。

1.AOMのAV1エンコーダーを取得

エンコードに必要なエンコーダーを取得します。今回はAv1anがデフォルトで使用するAO MediaのAV1エンコーダーを使用します。

AO MediaのAV1エンコーダー(https://aomedia.googlesource.com/aom/

説明にある通りビルドし、取得してください。

2.FFmpeg Staticビルドの取得

エンコードの際に必要となるFFmpeg staticをダウンロードします。

FFmpeg Staticビルド(https://johnvansickle.com/ffmpeg/

3.各種バイナリの配置

AV1エンコーダーとFFmpeg StaticビルドはAv1anと同じディレクトリに配置してください。aomencとffmpeg、ffprobeをAV1anと同じディレクトリに置いて下さい。

これで分割エンコーディングの準備はすべて整いました。

分割エンコーディングを実施

それでは実際に動画のエンコードを行ってみようと思います。エンコード元動画は下記となります。

  • 画角:1920×1080
  • フレームレート:60FPS
  • 画質:214kbps
  • 尺:2時間47分

エンコードを行うPCのスペックは以下となります。

  • CPU:Core i9 9900k
  • メモリ:DDR4 64GB
  • ストレージ:NVMe M.2 SSD

今回はエンコード時間比較のために、FFmpegとaomencでもエンコードを行います。ffmpegとaomencのエンコードでは極力av1anのデフォルトパラメータを使うようにします。

エンコードのコマンド

実行するコマンドは以下となります。

AV1an

time av1an -i ./input.mp4 -o ./output.mp4

※av1anのオプション(https://github.com/master-of-zen/Av1an/blob/master/docs/CLI.md

FFmpeg

av1anがデフォルトで2passエンコードを行うので、ffmpegでも2passエンコードを行います。

time ffmpeg -y -i ./src/test.mp4 -c:v libaom-av1 -threads 8 -cpu-used 6 -tile-columns 1 -tile-rows 0 -aom-params cq-level=30 -pass 1 -f null /dev/null && time ffmpeg -y -i ./input.mp4 -c:v libaom-av1 -threads 8 -cpu-used 6 -tile-columns 1 -tile-rows 0 -aom-params cq-level=30 -pass 2 ./outputffmpeg.mp4

aomenc

aomencはmp4を直接処理できないので、ffmpegでy4mの形式に変換しておきます。

ffmpeg -i input.mp4 -f yuv4mpegpipe input.y4m
time aomenc --threads=8 --cpu-used=6 --end-usage=q --cq-level=30 --tile-columns=1 --tile-rows=0 --width=1920 --height=1080 -o ./outputaomenc.bin ./input.y4m

※aomencのオプション(https://github.com/master-of-zen/Av1an/blob/master/docs/Encoders/aomenc.md

エンコードの実施結果

エンコード時間の結果は下記となります。それぞれ、実施日と時間を変えて3回エンコード時間を計測しました。時間は、分(m)と秒(s)で表記しています。

No.AV1anFFmpeg
(1passと2pass合計)
aomenc
(1)20m01s28m22s
(1m31s+26m51s)
31m40s
(2)20m38s28m04s
(1m35s+26m29s)
30m37s
(3)20m46s29m41s
(1m37s+28m04s)
32m24s
エンコーディング時間の比較

いかがでしょうか。分割エンコードを行ったAV1anはFFmpegとaomencと比べて3割程度、エンコード時間が短縮される結果になりました。Av1anはデフォルトでワーカープロセスを5つ起動してエンコードを行うため、さすがに通常のエンコードよりも速いですね。動画の分割と再結合というオーバーヘッドがあった上で速いのですから、分割エンコードはハードウェア支援が無い環境では、割りと有効なのではないかと思います。

尚、ワーカープロセスは「-w」オプションで変えられるので、幾つかのパターンで試してみたところ、以下のような結果となりました。

ワーカープロセス数エンコード時間
分(m)と秒(s)で表記
137m21s
224m26s
322m21s
421m42s
5(20m)
621m40s
821m46s
1622m43s
ワーカープロセス数別エンコード時間

9900kは8コア16スレッドのCPUであるため、いたずらにワーカープロセスを増やしても、リソースの限界が来てエンコード速度の向上には繋がらないようです。また、6ワーカープロセスで全論理プロセッサが使用率100%になって、エンコードが終わるまで何も出来なくなりました。

さいごに

さて、今回は動画の分割エンコードを体験してみよう、という内容でしたが、いかがでしたでしょうか?AV1anはAV1なら、他にSVT-AV1やrav1e、H.264/265、VP8/9にも対応していますし、最新のCPUで動かしてみると面白いかもしれません。64コア/128スレッドのRyzen Threadripper PRO 5995WXなんかでエンコードしてみると、凄いことになりそうですね。