既にタイトルで出オチなのですが、FFmpegで標準的な引数だったので、まさかそこまで異なっているとは考えておらず失敗した、というお話です。
背景、経緯
私はWindowsで物体検出を利用した動画編集アプリをリリースしており、動画の処理にはFFmpeg.exeを利用しています。
NVIDIA Geforceだけでなく、AMD RadeonやIntelなど様々なパソコン環境に対応させるため、物体検出にはDirectMLを用い、動画のエンコードには各GPUのハードウェアエンコーダであるNVIDIA nvenc、AMD amf、Intel qsvを指定していました。
以前はFFmpegをビルドしないとamfやqsvが使えなかったようですが、最近の配布されているバイナリでは最初からamf、qsvが使える状態になっています。
アプリをリリースする上で気がかりだったのは、AMD Radeonでの動作確認ができていないことでした。
私のパソコンは、Intel CPU + NVIDIA GPUです。
DirectML、nvencはGPUでテストができました。
qsvについては、CPUでテストすることができました。
Radeon、具体的にはFFmpegのamfでの動作テストができておらず、不安ではありましたが、
- FFmpegで何か特別な引数を利用している訳ではなかった
- nvenc、qsvで動作したので、きっとamfでも大丈夫だろう
- 私がRadeon持っておらず、また身近なRadeonユーザーも見つからなかった
というようなことから、まぁきっと大丈夫だろう、と楽観的にアプリをリリースしていました。
すると、アプリをリリースしてから数か月後、Radeonユーザーから正常に処理が終わらずエラーになる、という問い合わせを受けたのでした。
問題となったFFmpegの引数
arguments = $"-hwaccel \"{hwaccel}\"
-i \"{audioFile1}\"
-i \"{videoFile2}\"
-vcodec \"{codec}\"
-b:v 11M
-preset slow
\"{outvideo}\"";
実際に問題となっていたのは物体検出時の動画処理でしたが、わかりやすさでこちらを記載します。
ハードウェアエンコーダを指定して、音声ファイルと映像ファイルを1つの動画に結合する処理です。
hwaccel
とcodec
はプライマリーディスプレイを判定し指定するようにしていました。
問題になったのは、-preset slow
でした。
amfでは-preset slow
は使えない
-preset slow
は、x264などのソフトウェアエンコーダーでも使うものなので疑いもしませんでしたが、amfでは使えない値でした。
1.NVIDIA nvencで利用できる-preset
の値
各エンコーダで使える引数は例えば次のようなコマンドで確認できます。
利用しているFFmpegは7.1です。
ffmpeg -h encoder=hevc_nvenc
-preset
の部分だけを転記すると
-preset <int> E..V....... Set the encoding preset (from 0 to 18) (default p4)
default 0 E..V.......
slow 1 E..V....... hq 2 passes
medium 2 E..V....... hq 1 pass
fast 3 E..V....... hp 1 pass
hp 4 E..V.......
hq 5 E..V.......
bd 6 E..V.......
ll 7 E..V....... low latency
llhq 8 E..V....... low latency hq
llhp 9 E..V....... low latency hp
lossless 10 E..V....... lossless
losslesshp 11 E..V....... lossless hp
p1 12 E..V....... fastest (lowest quality)
p2 13 E..V....... faster (lower quality)
p3 14 E..V....... fast (low quality)
p4 15 E..V....... medium (default)
p5 16 E..V....... slow (good quality)
p6 17 E..V....... slower (better quality)
p7 18 E..V....... slowest (best quality)
2.Intel qsvで利用できる-preset
の値
ffmpeg -h encoder=hevc_qsv
同様に-preset
の部分だけを転記すると
-preset <int> E..V....... (from 0 to 7) (default 0)
veryfast 7 E..V.......
faster 6 E..V.......
fast 5 E..V.......
medium 4 E..V.......
slow 3 E..V.......
slower 2 E..V.......
veryslow 1 E..V.......
3.AMD Radeon amfで利用できる-preset
の値
ffmpeg -h encoder=hevc_amf
同様に-preset
の部分だけを転記すると
-preset <int> E..V....... Set the encoding quality preset (from -1 to 10) (default -1)
quality 0 E..V.......
balanced 5 E..V.......
speed 10 E..V.......
なんということでしょう!
運がいいことにテストしていないamfにだけslowはありませんでした。
っていうかamfの-preset
少なくない?
感想など
- エンコーダが変われば設定できる引数やその値が変わるのは当たり前と言えば当たり前なんですが、presetはFFmpegの標準的な引数だと思っていたので共通だろう、と思い込んでいたのが失敗でした
-
-preset 3
というようにint指示としようか?とも思いましたが、わかりにくくまた指示の内容も微妙に異なりそうなので、amfの場合だけ-preset quality
と設定するようにしました - テストしない(できない)のであれば、今回確認したような仕様の確認を細かく真面目に実施するべきでしたが、その点も怠ってしまったことで今回の失敗につながったと考えています
- 問合せしてくださったユーザーの方には、FFmpegのコマンドを試してみてテストして頂いたりと、いろいろとご迷惑をかけてしまいました