x264 の動き探索パラメータはどこまで効くのか — VMAF・圧縮率・時間効率で検証(アニメ編)

ソフトウェア開発

x264 のオプションの中でも「動き探索(motion estimation)系」は、me_method / subme / me_range という代表格が揃っていて、エンコード時間への影響も大きい定番のチューニングポイントです。一方で「実際にどれだけ画質やサイズが変わるのか」を数字で示した資料は意外と見かけません。

この記事は、自作のエンコード検証ツールを使った検証シリーズの第 1 回です。ffmpeg でのエンコード実行から VMAF/SSIM/PSNR のフレーム単位計測、比較・可視化までを一気通貫で行うデスクトップツールを開発していて(もう少し整えたら GitHub で公開予定)、今後もいろいろなパラメータやエンコーダの検証記事を出していく予定です。

今回具体的には、x264 medium・CRF 23 を基準に、動き探索パラメータを 1 個ずつ動かして VMAF / SSIM / PSNR・出力サイズ・エンコード時間を全て計測しました。評価軸は次の 3 つです。

  • 品質: VMAF(平均と 1% low)
  • 圧縮率: 同一 CRF での出力サイズ差(小さくなれば実質タダで得)
  • 時間効率: エンコード時間の基準比(かけた時間に見合うか)

今回はアニメ素材編の第 1 回です。ひと口にアニメと言ってもシーンによって動きの量はまるで違うので、1 本で終わりにせず、動きの大きいシーンや別ソースを続編で追加検証していく予定です。その前提で、今回のシーンでの結論を先に書くと、

  1. me_method の効果は品質ではなくサイズに出る(esa/tesa で最大 −2%)— 品質が動かないのは CRF 固定の仕様どおり
  2. subme は CRF 固定でも品質が動く唯一の軸。ただし 9 で打ち止めで、subme 10/11 は(そのままでは)9 と完全に同一の出力になる
  3. me_range はこの素材では品質もサイズも動かない
  4. 動き探索だけ移植するより、素直に preset を落とす方が圧倒的に効率が良い

でした。以下、順に見ていきます。

検証環境と方法

項目内容
CPUAMD Ryzen Threadripper 2990WX(BIOS で 8C/16T に制限して運用、x264 は 24 スレッド使用)
エンコーダffmpeg 8.1.2(gyan.dev full build)/ x264 core 165 r3223
品質評価libvmaf(既定モデル)+ SSIM + PSNR、全フレーム計測
素材Netflix Open Content「Sol Levante」暗部シーン 10 秒(1920×1080・24fps・10bit)
中間素材libx264 -qp 0 のロスレス(約 355 Mbps)。配信ソースの再圧縮ではない
基準設定libx264 / CRF 23 / preset medium / 音声なし(出力は 10bit High 10 profile)

素材の Sol Levante は手描きアニメで、暗い背景に発光するキャラクターが動く、暗部グラデーションの多いシーンです。動きは激しくないので、「動き探索がそこまで苦労しない素材」として読んでください。この記事の数値はすべて「この 10 秒のシーンでは」の結果であり、アニメ一般の結論ではまだありません — 動きとエフェクトの多いシーンや別ソースでの追加検証は続編で行います。

計測には冒頭で触れた自作ツールを使っています。ffmpeg でのエンコード実行 → libvmaf によるフレーム単位の品質計測 → グラフ表示・複数 run の比較(RD カーブ・diff 表)→ ソースとのフレーム単位比較(並べて/ワイプ/差分ヒートマップ/A/B)までを一気通貫でやるデスクトップアプリで、この記事の比較は全部これで回しました。パラメータ違いの run をキューに積んで放置すれば、終わったものから順に比較表とグラフへ載っていきます。

基準 run のフレーム単位メトリクス。上から VMAF / SSIM / PSNR-Y / フレームサイズ

パラメータを変えた run を保留キューに積んで一括実行すると、終わった run から順に比較グラフと diff 表に載ってきます。

アプリの Run 比較画面。上が run ごとのビットレート vs VMAF、下が per-frame VMAF の重ね描き

読み方の注意をひとつ。この記事の比較はすべて「同一 CRF での単点比較」です。CRF は「品質を一定に保ち、サイズは成り行きに任せる」モードなので、理屈のうえでは、圧縮を賢くするパラメータの効果は品質ではなくサイズの縮みとして現れます。つまり VMAF がほぼ動かないのは期待どおりの挙動であり、主役の指標は「同一 CRF でどれだけ縮んだか」です。ただし CRF が内部で保とうとする「品質」は VMAF そのものではないため、レート配分やモード決定の判断そのものを変えるパラメータ(subme・trellis など)では、実際に届く品質のほうもズレます。等品質換算のビットレート差を出すには CRF スイープで RD カーブを引く必要があり、それは今回のスコープ外です。

me_method — 品質は動かない。サイズは縮む

動き探索アルゴリズム本体の比較です。dia(菱形)→ hex(六角形)→ umh(不等間隔多角形)→ esa(全探索)→ tesa(アダマール全探索)の順に「丁寧」になります。medium の既定は hex。

me_methodビットレート kbpsサイズ差VMAFΔVMAFVMAF 1%low時間 s時間比
dia14,458+0.2%92.12−0.0384.1216.5×0.92
hex(基準)14,426+0.0%92.15+0.0083.9118.0×1.00
umh14,273−1.1%92.15+0.0184.1022.7×1.26
esa14,189−1.6%92.16+0.0184.2932.1×1.79
tesa14,139−2.0%92.26+0.1284.3238.1×2.12
me_method 比較チャート

VMAF は dia から tesa まで ±0.12 の範囲にしか動きませんが、これは驚くところではありません(品質を一定に保つのは CRF の仕事)。勝負は圧縮率のほうです。

そちらは理屈どおりで、探索を丁寧にするほど同一 CRF でもサイズが縮んでいきます(tesa で −2.0%)。より正確な動きベクトルが見つかる → 残差が減る → 同じ品質狙いでもビットが減る、という期待どおりの挙動です。問題はその縮み幅で、時間を 2.1 倍かけてようやく 2%。動きの少ないこの素材では hex の時点でほぼ最適な動きベクトルが見つかっており、上積みの余地がもともと小さい、ということです。アーカイブ用途で時間が余っているとき向けでしょう。

逆方向の dia は 8% 速くなって VMAF −0.03。この素材に限れば dia まで落としてもほぼ気づけないというのも発見です。

subme — 9 で打ち止め。10/11 は「無言で 9 に降格」される

サブピクセル精度・モード決定の丁寧さを決める subme(0〜11)。medium の既定は 7 です。

submeビットレート kbpsサイズ差VMAFΔVMAFVMAF 1%low時間 s時間比
015,245+5.7%90.91−1.2382.1810.8×0.60
213,652−5.4%90.12−2.0381.0011.6×0.64
413,965−3.2%90.85−1.3082.3213.0×0.72
614,472+0.3%91.27−0.8782.4316.5×0.92
7(基準)14,426+0.0%92.15+0.0083.9118.0×1.00
814,589+1.1%92.23+0.0984.2219.3×1.07
914,802+2.6%92.75+0.6184.8925.1×1.39
1014,802+2.6%92.75+0.6184.8925.3×1.41
1114,802+2.6%92.75+0.6184.8923.4×1.30
subme スイープチャート

CRF 固定なら品質は動かないはず — ですが subme は動かします。subme はモーション精度だけでなくモード決定・RD 最適化の丁寧さそのものを変えるパラメータで、CRF が頼る内部の品質推定と実際の見え方の関係ごとズレるためです。実際、動き探索系の中で唯一まともに品質へ効きました。7 → 9 で VMAF +0.61(1% low も +0.98)。下方向は 6 ですでに −0.87 と大きく落ちます。x264 は subme 6 以上でないと psy-RD が有効にならないので、6 未満の急落はそれも効いています。subme 0(フルペル探索のみ)は「速いがサイズが 5.7% 増えて品質も 1.2 点低い」と、良いところがありません。

そして表をよく見ると、9 / 10 / 11 の数値が完全に一致しています。これは丸め誤差ではなく、出力の映像ビットストリームの MD5 が 3 本とも同一でした。つまり同じファイルが出てきています。

原因は x264 の仕様で、subme 10(QP-RD)と 11(full RD)は trellis=2 が前提のため、medium の既定である trellis=1 のままでは無言で 9 に降格されます。実際、subme=11 を指定した run のビットストリームに埋め込まれた x264 のオプション文字列(SEI)を見ると subme=9 と記録されていました。「subme だけ 11 に上げる」は、何も言われずに 9 として実行されているわけです。

me_range

動き探索の範囲(既定 16)。hex では実質効かないパラメータなので、umh に固定した上で me_range だけを動かしました。

me_rangeビットレート kbpsサイズ差VMAFΔVMAFVMAF 1%low時間 s時間比
16(既定)14,273−1.1%92.15+0.0184.1022.7×1.26
2414,272−1.1%92.15+0.0084.3226.0×1.44
3214,266−1.1%92.17+0.0284.2027.1×1.51
4814,279−1.0%92.16+0.0184.1838.0×2.11
6414,290−0.9%92.18+0.0384.3745.1×2.50
me_range スイープチャート

VMAF が動かないのは期待どおりとして、me_method では出ていたサイズの縮みすら 16 → 64 でほぼ動かず、時間だけが最大 2.5 倍になりました。表のサイズ差 −1% は me_range ではなく umh 自体の効果です(前節の umh 単独と同じ値)。1080p24 のアニメで 16 ピクセルを超える動きが処理しきれず困る場面がそもそも少ない、ということだと解釈しています。高解像度・高速モーションで初めて意味が出るパラメータなので、ここは実写編での再検証課題です。

組み合わせ — preset の「動き探索部分だけ」を移植してみる

単軸で効いたのは subme だけでした。次は組み合わせです。x264 の preset は内部で動き探索パラメータを段階的に上げていくので、「preset の動き探索部分だけ」を medium に移植した設定を作って比較しました。各 preset の実効値は出力ビットストリームの SEI で確認済みで、slower = umh+subme9、veryslow = umh+subme10+me_range24、placebo = tesa+subme11+me_range24 です(意外なことに slow は me_method を hex のまま、subme 8 + ref 5 + trellis 2 に上げるだけでした)。さらに参照点として preset そのものを落とした run(slow / veryslow / placebo)も並べます。

設定ビットレート kbpsサイズ差VMAFΔVMAFVMAF 1%low時間 s時間比
基準 medium14,426+0.0%92.15+0.0083.9118.0×1.00
umh subme814,426+0.0%92.25+0.1184.1925.6×1.42
slower 相当(umh subme9)14,641+1.5%92.75+0.6085.1331.0×1.72
umh subme11 mr2414,640+1.5%92.76+0.6185.1331.8×1.77
veryslow 相当(umh subme10 mr24)14,640+1.5%92.76+0.6185.1334.4×1.91
placebo 相当(tesa subme11 mr24)14,461+0.2%92.88+0.7385.0657.8×3.21
全部盛り(tesa subme11 mr64)14,405−0.1%92.92+0.7785.16174.2×9.68
preset slow14,551+0.9%92.67+0.5285.0223.2×1.29
preset veryslow13,833−4.1%93.28+1.1486.85101.7×5.65
preset placebo13,991−3.0%93.62+1.4887.63251.8×13.99
時間 vs 品質マップ
時間 vs 圧縮率マップ

まず組み合わせ側。slower 相当・veryslow 相当・umh subme11 mr24 の 3 つがほぼ同じ結果(+0.60〜0.61)に収束していますが、これは偶然ではありません。前節の通り trellis=1 のままでは subme 10 も 11 も 9 に降格されるので、この 3 つは実効的に「umh + subme9(+me_range だけ違う)」という同じ設定であり、me_range はこの素材では無風だからです。つまり「動き探索の枠だけを preset から移植する」やり方では、subme 9 の +0.6 点が実質の上限になります。tesa まで積んだ placebo 相当で +0.73、探索範囲まで盛った全部盛り(×9.68!)でも +0.77 と、上積みはごくわずかでした。

そして参照点の preset まるごとと比べると、構図がはっきりします。

  • preset slow(×1.29)は、slower 相当(×1.72)より速くて品質がほぼ同じ。slow が速いのは動き探索を欲張らない(me は hex のまま subme 8 止まり)代わりに trellis 2 と ref 5 で補う構成だから
  • preset veryslow(×5.65)は VMAF +1.14 に加えてサイズが −4.1%。動き探索チューンでは何時間かけてもこの数字には届かない

preset が動き探索と同時に上げている refs・trellis・rc-lookahead・B フレーム判定などがまとめて効いているためで、「動き探索だけを頑張るくらいなら preset を 1 段落とす」が、この素材での明確な結論です。ちなみに trellis は slow の時点でもう 2 になるので、subme 10/11 が本来の姿で動くのも preset 経由なら自然に実現します(veryslow の SEI は subme=10、placebo は subme=11 でした — 単発指定では 9 に降格されていたアレです)。

パラメータ diff 表。基準・tesa・veryslow 相当・preset veryslow の比較

おまけ: trellis / partitions / fast-pskip

動き探索の「相方」としてよく一緒に語られるパラメータも、umh+subme11+me_range24 をベースに振ってみました(これも上記の通り実効 subme は 9 です)。

設定ビットレート kbpsサイズ差VMAFΔVMAFPSNR-YSSIM時間比
基準 medium14,426+0.0%92.15+0.0038.950.9935×1.00
umh subme11 mr2414,640+1.5%92.76+0.6138.990.9936×1.77
+ trellis 014,318−0.7%90.65−1.5038.680.9923×1.71
+ trellis 214,325−0.7%93.56+1.4138.860.9934×2.80
+ partitions all14,617+1.3%92.76+0.6138.990.9936×1.74
+ fast-pskip 014,643+1.5%92.78+0.6338.990.9936×1.71

目を引くのは trellis 2 です。サイズが 0.7% 縮んだ上で VMAF が +1.41 と、この記事に登場した単発チューニングでは最大の伸び。しかも PSNR と SSIM はむしろ基準より下がっています。トレリス量子化は「数学的な忠実度」ではなく「見た目に効くところ」へビットを寄せる最適化なので、PSNR/SSIM が下がって VMAF(知覚品質)が上がるのは仕様どおりの挙動です。どのメトリクスを信じるかで評価が反転する、メトリクス比較の教材みたいな結果でした。なお trellis 2 は subme 10/11 の解禁条件でもあるので、「subme を上限まで使いたいなら trellis 2 とセット」と覚えておくのが良さそうです(実際に解禁するとどこまで伸びるかは、次回の実写編の追補で検証します)。

partitions all が基準とほぼ同一なのは、medium の時点で主要パーティション(p8x8, b8x8, i8x8, i4x4)がすでに有効だからです。fast-pskip オフも誤差の範囲でした。

まとめ(アニメ編・第 1 回)

動きの少ないアニメの暗部シーン(Sol Levante・CRF 23 medium 基準)では:

  • me_method: 品質不変は CRF の仕様どおり。効果はサイズの −1.6〜2.0%(esa/tesa)に出るが、時間 2 倍の対価としては小粒。急ぎなら dia に落としても壊れない
  • subme: CRF 固定でも品質が動く唯一の軸(RD 最適化と psy-RD の精度が変わるため)。9 で +0.61 が上限。10/11 は trellis=2 がないと 9 に無言で降格(出力 MD5 一致で確認)
  • me_range: 品質もサイズも動かない無風。時間だけ最大 ×2.5
  • 組み合わせ: 動き探索の枠だけでは +0.77 が天井。preset veryslow(+1.14・サイズ −4.1%)に遠く及ばない
  • 時間効率の勝者: ちょっと盛りたいなら preset slow(×1.29 で +0.52)。品質と圧縮率を両取りしたいなら preset veryslow

「動き探索パラメータを個別にいじる意味は、少なくともこのシーンではほぼない」という身も蓋もない結論になりましたが、個別に振ったからこそ「preset のどの成分が効いているのか(→ 動き探索ではなく trellis・refs 側)」まで切り分けられました。

ただし冒頭に書いたとおり、これは暗部・低モーションという「動き探索が効きづらい」シーンでの結果です。アニメ編の続編では、同じ手順のまま素材を広げて検証する予定です — 候補は同じ Sol Levante の森+魔法エフェクトシーン(線画+派手なパーティクル)、CG アニメの大きなカメラモーションあたり。セル塗りの平坦な面とエフェクトの組み合わせで subme や me_method の効き方が変わるのか、が見どころです。

その前にまず次回は実写編です。動き探索が本領を発揮するはずの高速モーション素材(群衆マラソン・1080p50)で同じ表を作ります。me_range が今度こそ仕事をするのか、お楽しみに。


検証データ: 各設定 1 run(x264 は同一設定・同一スレッド数なら決定的に同一出力になります)。VMAF は libvmaf 既定モデル・全 240 フレーム計測の平均値。

素材クレジット: “Sol Levante” — Netflix Open Content(CC BY 4.0)。UHD SDR 版の t=144〜154 秒を 1080p・10bit へ変換したロスレス中間を使用。

このシリーズは自作エンコード検証ツールの実戦テストを兼ねています。ツールはもう少し整えたら GitHub で公開予定です。

コメント

タイトルとURLをコピーしました