SVT-AV1 を定量的に評価してみる

# はじめに
かつてAV1が出てきたときに、[エンコードがHEVCの100倍遅い](https://gigazine.net/news/20180208-av1-near-future/)とか、[専用のFPGA組まないとリアルタイムエンコードできない](https://dwango.github.io/articles/av1hwencoder/)とか記事を見たせいで、まあ私にはしばらく縁のない話だな・・・とほかっておいたのだが、[最近SVT-AV1というものが出てきて](https://qiita.com/yanoshi/items/544a361baf76b8114067)そのあたりが大きく改善されているという話を聞き、もう一度やってみようかと思った。

試しにエンコードしてみると、思いのほか（というより劇的に）高速化されており、これはまじめに使ってみようと。単に動かすだけなら先行記事がいっぱいあるので、HEVCと比べてまじめに定量評価してみると記事になるのではと思ったのがこれを書き始めた動機。

# 用語とか使うものとか

動画の世界は用語が少し独特。

## コーデック

- H.264 : H.265(=HEVC) の前の世代のコーデック。世の中のスマホを含む主要なOSやブラウザでサポートされている。[策定が2003年](https://ja.wikipedia.org/wiki/H.264)で、[オープンソース実装のx264が出てきたのが2006年](https://rpmfind.net/linux/rpm2html/search.php?query=x264)ごろ。今となっては古めのコーデックだが、割と現役で使っているところも多い。MPEG-2 とくらべておおよそ半分のビットレートで同等の画質を実現できるというのが売り。
- H.265 : H.264 の後継コーデック。H.265 HEVC(High Efficiency Video Coding) とか、単に HEVC と呼ばれることもある。策定が2013年で、[オープンソース実装のx265も同年に出てきている](https://en.wikipedia.org/wiki/X265#History)。H.264 に比べておおよそ半分のビットレートで同等の画質を実現できるというのが売り。
- MPEG-2: H.264 の前の世代のコーデック。策定が1995年。実は地上波デジタルとか、衛星放送では未だに現役で、録画したソースは MPEG-2 TS(Transport Stream) になっている。
- [AV1](https://ja.wikipedia.org/wiki/AV1) : Google や Netflix などが主導して作られた [Alliance for Open Media(AOM)](https://ja.wikipedia.org/wiki/Alliance_for_Open_Media) が2018年に公開したコーデック。特許利用料の支払いが不要で H.265 の置き換えができるというのが売り。最近だとYouTube でよく使われている。

ファイルサイズとしては MPEG-2 > H.264 > AV1 ? H.265 HEVC という感じで

エンコード時間は AV1 >>> H.265 HEVC > H.264 > MPEG-2 という感じ（だった）。

なんで AV1 なの？という話は映像業界とIT業界の考え方の違い的なところがあるんだけど、この記事の主題から離れるし私自身詳しくないので、気になる人は各自調べてほしい。例えば[ここ](https://bloggeek.me/av1-vs-hevc-webrtc-codec/)とか、[ここ](https://gigazine.net/news/20230418-codec-hevc-av1-vvc/)とか。その関係かどうか、[Safari は AV1 デコードをサポートしていない](https://caniuse.com/av1)。

## 実装

AV1 には以下の実装がある

- [AOM-AV1](https://aomedia.googlesource.com/aom/) : AOMがAV1をリリースしたときの実装。エンコードが激遅という致命的なデメリットがある。
- [SVT-AV1](https://gitlab.com/AOMediaCodec/SVT-AV1) : Intel と Netflix が SVT(Scalable Video Technology) として CPU をより効率的に使って AV1 のエンコーダとデコーダを実装したもの。今回の話の主役。

## サイズや画質に影響するパラメータ

以下の要素がエンコード後のファイルサイズや画質に影響を与える。

- ビットレート: 言わずもがなだが、高ければ画質が高く、ファイルサイズが大きくなる
- CBR, VBR: CBR はすべての区間に同一の帯域を使ってエンコードする。VBR は動きの少ないところのビットレートを絞り、動きの大きいところに節約した帯域を割り当てることで、最終ファイルサイズを CBR とほぼ同等に保ちながらより画質を向上させるテクニック
- CRF: 画質の判断を動的に行い、1 pass のエンコードでありながら VBR と似たビットレートの動的調整を行うエンコード方法。コーデックによっては CRF と n-pass エンコードを組み合わせてより画質向上を行うこともできるらしい。

## 評価の観点

動画の評価軸としては、エンコード時間、ファイルサイズ、リソースの利用効率、画質評価などがある。エンコード時間、ファイルサイズ、リソースの利用効率というのはそのまま計測すればわかるのだが、画質の評価基準は人間の主観が入ることから今まであまり使いやすいものがなかったが、Netflix が [VMAF](https://github.com/Netflix/vmaf) というものを発表して以降、徐々に利用されるようになっている。

VMAF を含めた画質の評価基準は以下のものがある。

- [PSNR](https://ja.wikipedia.org/wiki/%E3%83%94%E3%83%BC%E3%82%AF%E4%BF%A1%E5%8F%B7%E5%AF%BE%E9%9B%91%E9%9F%B3%E6%AF%94)(ピーク信号対雑音比, Peak signal-to-noise ratio) : 元画像とエンコード後の画像をピクセル単位で比較することにより差分を算出する方法。計算すれば算出できるが、一概に PSNR が悪いものであっても人間の目には劣化を感じさせない場合も多いことから、今は参考程度の指標になっているようだ (PSNR をどの程度重視するかは様々な意見がある)。
- SSIM(structural similarity) : “[人間の画質劣化の知覚に画像構造の類似度が寄与するものとした指標](https://qiita.com/toshi_machine/items/3ff0a09279a8e71c4e82#ssim%E3%81%A8%E3%81%AF)”。らしい。正直私は使ったことがないのでコメントできない。
- [PC 法](https://www.rd.ntt/ns/qos/technology/visual/01_5_4.html)などの主観評価方法 : 人間に 10 秒程度の映像を見せて品質の良し悪しを評価してもらう方法。[PC 法のほかにも様々な手法があって](https://cir.nii.ac.jp/crid/1050564287847914752)、それ専門で研究している人がいる。当然評価する人間が必要なので、時間とお金がかかり個人ではとてもじゃないけどできない。
- VMAF : [Netflix と南カリフォルニア大学が共同開発した](https://netflixtechblog.com/toward-a-practical-perceptual-video-quality-metric-653f208b9652)動画専用の評価手法。上記の指標をベースとして、機械学習による重み付けを行っている。 もちろん人間が介在せず自動化が可能。

# 検証環境・前提条件

環境は以下の通り

- ハードウェア
    - CPU: AMD Ryzen 7 1700(3.75GHz, 8cores, 16 threads)
    - MEM: 32GB DDR4-2133 (一般的にエンコーダはメモリをそれほど使用しない。実際には 8GB もあれば十分)
    - 仮想化は未使用

CPU は意図的に少し前のものをチョイスしてみた。これで良好な結果が出ればリソースの有効活用の幅が出る(=ちょっと古い PC をエンコードマシンにできる)と思ったので。現在録画した TS は上記のような H.265 で保存しているので、AV1 でも同等程度のパフォーマンスが出ればいいな、というのが期待値になる。

- ソフトウェア
    - OS : Ubuntu 23.04 Server
    - FFMpeg : 6.0 (Repository HEAD)
        - AOM-AV1: repository head
        - SVT-AV1: repository head
        - VMAF: repository head
- データソース
    - データソース1 : 地上波デジタルから録画したバラエティ番組 (MPEG2-TS) を HuffYUV 可逆圧縮した。MPEG2-TS のビットレートはおおよそ 13M~15Mbps 程度。元映像は 1440x1080 のいわゆるスクイーズ (SAR=4:3) された映像なので、可逆圧縮する際に 1920x1080(SAR=1:1) にリサイズしている。
    - データソース2 : 地上波デジタルから録画したアニメ番組 (MPEG2-TS) を HuffYUV 可逆圧縮した。MPEG2-TS のビットレートはおおよそ 13~15Mbps 程度。元映像は 1440x1080 のいわゆるスクイーズ (SAR=4:3) された映像なので、可逆圧縮する際に 1920x1080(SAR=1:1) にリサイズしている。

よく実写映像とアニメの映像は適するエンコード形式が異なると言われているので、データソースとして用意した。[SVT-AV1 のドキュメント](https://gitlab.com/AOMediaCodec/SVT-AV1/-/blob/master/Docs/CommonQuestions.md#practical-advice-on-grain-synthesis)を見ると、過去のフィルム映像に見られるような不規則なノイズが入っているような映像もエンコーダにとって負荷が高いというコメントもあったが、手元にいいサンプルがなかったので用意していない。

今回はアーカイブ用途を想定する。ストリーミングは想定しない。

# 検証(1) エンコード時間とファイルサイズ

まずは 30 秒と 150 秒のソースファイルを上記のデータソースから切り出して、パラメータ総当りの 108 パターンエンコードし、エンコード時間とファイルサイズを H.265 の場合と比較してみる。

検証したパターンは以下の通り。

1. libx265 2-pass VBR, Bitrate=2000k, MaxBitrate=4000k, preset=slow(6), CRF=default(28)
1. libsvtav1 2-pass, BitRate=1000K, MaxBitrate=2000k
    - preset=12,11,10,9,8,6,5,4,2
    - film grain=0,10,20,30,40,50
    - tune=0(PSNR), 1(VQ)

今回は H.265, SVT-AV1 ともに VBR での比較とした。preset の値に抜けがあるのは[ドキュメントの上では下位 preset からパラメータやエンコードアルゴリズムに変化がない](https://gitlab.com/AOMediaCodec/SVT-AV1/-/blob/master/Docs/CommonQuestions.md#what-presets-do)ため。

## 結果

[結果のCSV](https://docs.google.com/spreadsheets/d/1UKDqLB8BpF-KCuWeUKutuEccz7cGIREmj7n_lJqRMys/edit?usp=sharing)

30 秒、150 秒で傾向として変化はなかったので 150 秒の場合をプロットする

![plot](https://gitlab.com/mkiuchi/qiita-av1-vmaf/-/raw/main/files/test1.jpg)
[元ファイル](https://docs.google.com/presentation/d/1AFBb8e9M9k4tc6cSB4CvD2eUAyP46SGyjsyLPc9bNLA/edit?usp=sharing)

- エンコードは非常に早い。H.265 と比べて 3~4 割ほど時間が短くなっている。film grain の有無と、preset のレベルがエンコード時間に影響を及ぼす。
    - film grain は有効にするとエンコード時間が増えるが、有効化したときのレベルの変化による影響はわずか。
    - preset は強くするごとにエンコード時間が増える。10 以下にするかどうか、4 以下にするかどうかが判断の分かれ目になりそう。なんとなく preset12, 11 はストリーミング用なのではないかと思う。
- ファイルサイズはデータソース1(実写系)の場合は H.265 と大きな変化はなさそう。データソース2(アニメ系)では 25% 程度の削減が期待できそう
    - ファイルサイズに大きく影響するのは preset。おおむね 10 以下になると増加する(一部例外もある)。予想では preset のレベルが増加するたびにファイルサイズが小さくなると思っていたのでこの結果は意外。
- tune の種別はエンコード時間、ファイルサイズにはほぼ影響はなし

もし大規模なエンコード環境があって、エンコードコストを削減したいのであれば、AV1 化はやってもいいのかもしれない。ファイルサイズを削減したいという目的で既に H.265 環境なのであれば、AV1 移行のメリットは保管されるコンテンツ次第ということになりそう。

また 8core16thread の CPU 利用効率を計測したところ、おおよそ 35~60% となった。つまり１つのエンコードあたり 6~10thread 用意すれば CPU を有効利用できそうということになる。それ以上あっても CPU が空転するだけなので、マシンサイズを縮小するなり、エンコードを複数パラレルで動かしたほうがいいということになる。

# 検証(2) VMAFによる画質評価

検証(1) の結果を踏まえ、以下の条件で画質を検証することにした

- ソース
    - 上記のデータソース1, 2 から 1500秒(=25分) の映像を切り出しソースとする
- パラメータ
    - 以下のセットで検証
        - libx265 2-pass VBR, Bitrate=2000k, MaxBitrate=4000k, preset=slow(6), CRF=default(28)
        - libsvtav1 2-pass, BitRate=1000K, MaxBitrate=2000k
            1. [パターン1] preset=2, filmgrain=0,50, tune=0, 1
            1. [パターン2] preset=5, filmgrain=0,50, tune=0, 1
- 評価方法: VMAF による評価

## 結果

ソースによって異なる結果が出た

- ソース1(実写映像が主)については H.265 のほうがソース映像により近いと判断された
- ソース2(アニメ映像が主)については AV1 のほうがソース映像により近いと判断された
- Film grain, tune の値はVMAFの評価値にほとんど影響を及ぼさなかった

VMAF はフレーム単位の評価値を出すこともできるのでプロットしてみた。

![testsource1](https://gitlab.com/mkiuchi/qiita-av1-vmaf/-/raw/main/files/testsource1.tsframeVMAF-all.png)
![testsource2](https://gitlab.com/mkiuchi/qiita-av1-vmaf/-/raw/main/files/testsource2.tsframeVMAF-all.png)

いずれの場合でも実際の映像をフレーム単位で確認しても、VMAF の評価値が低いほうが明確に画像が劣化しているようには見えなかった。動きの激しいシーンをフレーム単位で見ると、AV1 の方が連続的に色が変化している部分に若干粗があることがわかったが、正直等倍速で再生していたら気づかないと思う。この場合も含め、ソース1 と 2で評価値の傾向が逆転する理由はわからなかった。また量子化、エントロピー符号化エンコーダの差がわかりやすいような映像、例えばキラキラ輝く水面とか、花火のような映像のときに起きる劣化傾向も、H.265 と AV1 で差はわからなかった。

AV1 の Preset 値は VMAF 評価値に 10~20% 程度影響する。ただしこれも肉眼では判別できなかった。

Film grain, Tune の値はVMAFの評価値には大きな影響を及ぼしていないように見える。実映像も肉眼による有意差はなかった。

# 自分なりの結論

検証(1), (2) を踏まえると自分としては以下のように思える。

- SVT-AV1 エンコーダは x265 エンコーダと比べても同等以上に高速であり、エンコード時間は H.265 と比較して有意に削減される。ソフトウェアエンコードを現実的な時間で完了させることができるし、リアルタイムストリーミングに利用することも可能。
- AV1 のファイルサイズは実写系の映像では、H.265 と同等以上のサイズが必要。アニメ系では有意に削減される
- 肉眼で見る限りでは H.265 と AV1 はほぼ同等という AOM の主張は正しいように思われる。機械的な評価という観点では AV1 が H.265 と同等かどうかは議論の余地がある。仮に機械的な評価値に差があったとして、それが実質的に意味があるか一律に判断はできない。PSNR, SSIM の評価とも比較しながら検証していく必要がある。個人的には既にアーカイブ用途で H.265 を使っているのであれば強いて AV1 に移行するメリットはないと思う。
- アーカイブ用の AV1 の設定として、Preset 4 以下は比較的意味がない (やるなとは言わないが費やした時間に見合った成果があると感じるかどうかは人による)。エンコード速度の観点から 5 が適切。Film grain は無効化して問題ない(有効化しても画質向上にはそれほど寄与せず、エンコード時間が長くなる)。Tuneは 0(VQ), 1(PSNR) いずれでもよい。

もちろんソース映像の種類によって上記の考えは変わるかもしれないので、それぞれの環境で検証することは必要。

# さいごに

使用したコードを上げておくので役に立てばうれしいです。

[Repository(GitLab)](https://gitlab.com/mkiuchi/qiita-av1-vmaf)