ffmpeg

ffmpegでH.264のプリセットのベンチマーク

More than 1 year has passed since last update.

はじめに

ffmpegでH.264コーデックでエンコードするときに選択するプリセットについて計測したデータの記録です。

背景

S3に保存してある動画をストリーミング用にエンコードします。S3にあるのでelastic transcoderをすぐに使えますが、東京リージョンでHD画質の場合、動画1分間あたりおよそ4円(2016.01.23現在)なので、60分のHD動画で240円。これが100本で24,000円。節約したいので、今回は手元のEC2のサーバのCPU使用率の少ない時間帯をCloudWatchで確認して、ffmpegでエンコードすることにしました。

H.264のプリセット

ffmpegのH.264の説明を読みます。
https://trac.ffmpeg.org/wiki/Encode/H.264
プリセットはエンコードのスピードと圧縮率に影響をもたらすオプションのコレクションです、と。遅いプリセットほどより良い圧縮を提供します。そして、速いほうから順に、ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placeboで、placeboは非常に遅いですが圧縮率もveryslowと1%くらいしか変わらないので無視してください、と書いてあります。
デフォルトは、mediumです。

圧縮は画質に影響するのかという点について、プリセットとは別に画質は-crfオプションで指定します。また-tuneオプションで最適化されます。今回は-crf 18(ほぼ無劣化に見える品質)と-tune film(実写最適化)を指定します。

ベンチマーク

プリセットはたくさん選択できますが、どれが最適かは試してみないとわかりません。アウトプットのファイルサイズはS3の容量とストリーミング時の通信料の課金対象になるので、圧縮率は高いほうが良いです。速度については、どれくらい時間がかかるのか見積もりたいので計測します。
実際の動画で、冒頭の60秒はタイトル画面などがあるのでスキップして、その次の60秒間をエンコードした結果がコレです。

graph1.png

速度はたしかにultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslowの順です。
圧縮率はそうではない、というのがわかります。

圧縮率が高いのはveryslowですが、動画1分あたり1時間以上かかっています。30分の動画なら1日以上ということです。
同等の圧縮率でveryfastなら動画1分あたり3分間で済み、30分の動画なら90分間で済みます。

今回の動画ではデフォルトのmediumからveryfastに変更することで、時間を81%も節約し、ファイルサイズを16%も節約できることがわかりました。

まとめと考察

veryfastが優秀なので採用。
動画によって(実写、アニメ、ノイズの量など)結果は異なると思うので、試してみるのが大事。
値はマシンスペックに依存する部分もありますが、比率はあまり変わらないと思います。

Appendix.A ベンチマーク用シェルスクリプト

実行は$ bash ffmpegperf.sh > ffmpegperf.logで、実行後に$ grep user ffmpegperf.log$ grep sys ffmpegperf.logで実行時間を得ます。

ffmpegperf.sh
#!/bin/sh

for preset in ultrafast superfast veryfast faster fast medium slow slower veryslow; do
time ffmpeg \
-i input.wmv \
-vcodec libx264 \
-preset ${preset} \
-crf 18 \
-tune zerolatency,film \
-movflags +faststart \
-acodec libmp3lame \
-b:a 192k \
-ss 60 \
-t 60 \
output.${preset}.mp4 
done