ffmpeg NVENCの画質と最適設定

NVENCとfdk-aacが使えるffmpegをビルドし、h264_nvenc cq (constant quality mode) の動作を解析し最適なエンコード設定を求めた。

x264 の crf とは設定が根本的に違う。crf は動きの少ない時の目標、cq は動きの多い時の目標(q の平均の上限)

動きの少ない時の q (Quantization Parameter) は cq の方が 5 低いので cq 28 が crf 23 相当。

nvdec を使わない場合の cq 28 の画質は x264 デフォルト crf 23 と同程度。(動きが激しい時は除く)

ただしビットレートは3割程度大きい。(cq 30 なら x264 並Turing 以降ではビットレート約2割減、画質改善とBフレームの効果

評価環境は ffmpeg-4.3.1   nvenc 9.0.18.3(デフォルト Bフレームなし)GT 710 2020/11

問題点

・Bフレームを使うと画質が悪い

・nvdec を使うと画質が少し悪い(画質と速度、どちらを取るか)

cq のビットレートは x264 と比較して動きが少ないと増加動きが多いと減少する(q の変動が大きい)

 Bフレームの画質-rc-lookahead が使えれば問題ない

追加情報

ffmpeg-5.1.2  の評価を追加 nvenc 10.0.26.2 RTX 4060 で確認 2023/12

Bフレームのデフォルトが 3 に変わったのでBフレームなしにするには -bf 0 が必要。h264 のBフレーム使用時の画質は -b_ref_mode 1 でかなり改善している。(q値の評価)hevc の場合は -b_ref_mode 1 ならBフレームを使っても問題な。(Turing 世代でhevc のBフレーム対応次の評価で問題が見つかったので h264 の -b_ref_mode 1 は使えない

 -bf は nvenc の help には記載されていないオプション、libx264 でも使える(helpの表示  ffmpeg -h encoder=h264_nvenc)

ffmpeg-6.1.2  の評価を追加 nvenc 12.0.16.1 RTX 4060 で確認 2024/12

h264 の画質はデフォルトの -rc-lookahead 無効だとかなり悪いので -rc-lookahead を有効にする必要がある。(目視の評価※)原因は -b_adapt 無効、-rc-lookahead と -b_adapt は連動している。-rc-lookahead の有効な設定範囲は 5~40。これでBフレームの問題は解決し画質は x264 と同程度 -rc-lookahead 使えない場合はBフレームなしにする。※q値の評価では差が出ない現象だったので目視の評価重要でした

-b_ref_mode のデフォルトが  0 (無効)から -1 (実際は2)に変わったので-b_ref_mode 1 と 2 の画質を確認

h264 はデフォルトの -b_ref_mode  2 が最適。 -b_ref_mode 1 には cq モードビットレートが増える問題があるので使えない。cq 30 のビットレートは x264  crf 23 より少し低くなったhevc では -b_ref_mode 1  と 2 のがほとんどないのでデフォルトの 2 よい。hevc では -rc-lookahead 0 でも画質は悪くないがキーフレーム間隔が固定から可変に変わる効果もあるので -rc-lookahead は有効する。hevc は h264 より低ビットレートに強いが画質はいまいち。

新機能の av1 は nvenc  API 12.0 以降で対応、av1 の画質はビットレート指定では hevc より良い。 cq モードでは設定や挙動が変だが、画質はよいので hevc の代わりに使ってもよいだろう。(av1  cq 35 が hevc  cq 30 相当のビットレート

h264 と hevc の画質については Turing の GTX 1660 super でも同じでした。 

これ以降の記事は古い世代のGPU(GT 710など)を元にしているので新しい世代のGPUに関しては後述の追加データの方も見てください。h264_nvenc の挙動は新しい世代のGPUでも変わっていない。

デコーダ(nvdec)の画質確認

Full HD から 720p の mp4 を作成する場合

-c:v mpeg2_cuvid -deint 1 -drop_second_field 1 -resize 1280x720

・インターレース解除は-deint 1 (bob) と-deint 2 (adaptive) があるがbobは高速だが画質が悪い

 adaptiveの画質はffmpegのbwdifより悪い(ffmpegのyadifの画質はいまいち、線の上に斑点が散るのでアニメには不向き)※現在の環境では再現しないので yadif でよい、bwdif より線が少し汚い程度

 60fps化はしないので2番目のフィールドは捨てる

・リサイズの画質はffmpegのデフォルトbicubicより悪い

デコーダは速度重視ならnvdec、画質重視ならffmpeg

エンコード オプションの検討

デフォルトでは 2000kbps の vbr になるが、品質を指定する場合は -b:v 0 -cq を使う

-b:v 0 なしだと使う ffmpeg によって挙動が変わるので -b:v 0 は必要(ビルドしたものと q の上限が違った)

h264_nvenc の cq (constant quality mode) は x264 と違い、動きが少ない時に q の値が大幅に低下する

q は quantization parameter (QP)

・h264_nvenc の -b:v 0 -cq

 q は設定値 +5 ~ -7 (エンコード時の q 表示、-qp 換算だと +6 ~ -6、q 表示は整数で設定より 1 低い、切り捨て?)

 動きが少ない時は -7

・libx264 の -crf

 q は設定値 +6 ~ -4 (エンコード後のPフレームの q 表示、Bフレームは +6 を越えない範囲で P + 2 程度)

 -4 は静止の場合、動きが少ない時は -1~-2 程度 (実質的な q の範囲は +6 ~ -2 )

x264 とは q の下がり方に 5 の差があるので

-b:v 0 -cq 28 で動きの少ない時の q は x264 のデフォルト -crf 23 とほぼ同じになる( q の最大値は 4 大きい)

これでも x264 よりファイルサイズはかなり大きいので -cq 30 でも良いと思う(ファイルサイズ優先)

Constant QP mode で画質を確認(nvdec未使用)

 -qp 21 ◎ 細部の描画良好

 -qp 23 ◎ 静止画でも気にならない

 -qp 25 ◎ 静止画だと少し気になる

 -qp 28 ○ 動いているなら気にならない

 -qp 32 △ 動きが大きい時なら許容できる

 -qp 36  ×  動きが大きくてもかなり気になる

これを目安に設定を決める、動きの多い時でも32程度に抑えたい

-rc constqp (Constant QP mode) のデフォルトは -qp 28(エンコード時の q 表示は 設定値 -1 )

x264 のデフォルト crf 23 の q の範囲 19~29 は非常に優秀であることがわかる

Bフレームなしの x264 と h264_nvenc で同じ -qp なら画質はほぼ同じ、ビットレートは nvenc が1割程度大きい。※ RTX 4060 ではビットレートは同じ

ビットレート指定の vbr では qmin qmax を指定することができる

-b:v 2000k -qmin 23 -qmax 36

-qp 23 より下げても画質はあまり改善しないので -qmin 23

-qp 36 を越えると急激に画質が悪化するので -qmax 36

720p のビットレートは 2000k 以上が必要

その他のオプション

-g 150  GOPサイズ(キーフレーム間隔) 30fps で 5 秒、デフォルトの 250 は長すぎる

  250 だとシークが遅くなる、ファイルサイズ的にもほとんどメリットない

  x264 は可変で max 250 なので、150 程度がちょうどよい

  ※ -rc-lookahead を使う場合はキーフレーム間隔が可変になるので -g 150 は不要(x264 と同じ max 250 になる)

-profile:v high  high profile(デフォルトはmain) high の方が薄い背景の潰れが少ない

  main だと q が大きい時に階調が潰れやすい(アニメだとわかりやすい)

-rc vbr_hq  high quality mode 速度低下に見合った効果があるかは疑問、ビットレートは僅かに小さくなる

-bf 3  Bフレーム(max 4) 画質が非常に悪くなる ※ -rc-lookahead が使えれば改善

  Constant QP mode で確認すると q の値が時々 +8 跳ね上がる

画質で注目したポイントは

薄い背景などの潰れ、文字やロゴの潰れ、線の綺麗さとノイズ、青色部分の潰れ


最適なエンコード設定

品質指定の場合 -profile:v high -g 150 -b:v 0 -cq 30 -bf 0 ※デフォルトが -bf 3 に変わったので -bf 0 追加、 -rc-lookahead が使える場合は -profile:v high -b:v 0 -cq 30 -bf 3  -rc-lookahead 20

ffmpeg -y -c:v mpeg2_cuvid -deint 1 -drop_second_field 1 -resize 1280x720 -i "input file" -vf fps=30000/1001 -async 1 -aspect 16:9 -c:v h264_nvenc -profile:v high -g 150 -b:v 0 -cq 30 -bf 0 -c:a libfdk_aac -ac 2 -b:a 128k -brand mp42 "output.mp4"

-cq 30 で q の範囲は -qmin 24 -qmax 36 相当

ビットレートは実写で 2000kbps 程度、-cq 28 だと3割増加するが高画質(x264 デフォルト並)

nvdec を使わない場合

ffmpeg -y -i "input file" -vf yadif,fps=30000/1001 -async 1 -s 1280x720 -aspect 16:9 -c:v h264_nvenc -profile:v high -g 150 -b:v 0 -cq 30 -bf 0 -c:a libfdk_aac -ac 2 -b:a 128k -brand mp42 "output.mp4"

ビットレート指定の場合

ffmpeg -y -c:v mpeg2_cuvid -deint 1 -drop_second_field 1 -resize 1280x720 -i "input file" -vf fps=30000/1001 -async 1 -aspect 16:9 -c:v h264_nvenc -profile:v high -g 150 -b:v 2000k -qmin 23 -qmax 36 -bf 0 -c:a libfdk_aac -ac 2 -b:a 128k -brand mp42 "output.mp4"

nvdec nvenc 以外のオプションの説明はこちら