キーフレームの間隔は force_key_frames で設定する【FFmpeg】

はじめに

前回の記事を書いた後で、force_key_frames を設定する方法を知ったので、それについて書きます。 ちなみに、前回の記事はこちらです。

確認した環境

本題

force_key_framesによるキーフレームの設定では式(expression)を使って詳細に指定することができます。 例えば、5秒間隔でキーフレームを挿入するコマンドは以下の通りです。

ffmpeg -i input.mp4 -vcodec h264 -force_key_frames expr:gte(t,n_forced*5) out.mp4

また、150フレームに1回キーフレームを入れるコマンドは以下の通りです。

ffmpeg -i input.mp4 -vcodec h264 -force_key_frames expr:gte(n,n_forced*150) out.mp4

expr:以下について

expr:以下に式を書くことで、式によるキーフレームの指定ができます。 この式は最初のフレームからフレーム単位で順番に評価され、その式が0以外を返すときそのフレームはキーフレームになります。
そしてforce_key_framesexpr:で指定する式には、数字以外に使用できる値があります。 今回のgte(t,n_forced*5)ではtn_forcedを使用しています。
tは評価されるフレームの時間を表します。単位は秒です。
n_forcedはそれまでに評価されたフレームのキーフレームの数を表します。

例としてgte(t,n_forced*5)を詳しく見ていきます。
まずgte(t,n_forced*5)gte(x,y)x >= yのとき1を返し、それ以外のときは0を返す関数です。
gte(t,n_forced*5)は、0フレーム目のときt = 0, n_forced*5 = 0*5 = 0となるので1を返しキーフレームになります。 次の1フレームはt = 0.033…, n_forced*5 = 1*5 = 5となるので、gte(t,n_forced*5)は0を返しキーフレームになりません(tはフレームレートが30fpsのときの値)。 よって次にgte(t,n_forced*5)が1を返すのはt >= 5となる最初のフレームなので、5秒のところにキーフレームがきます。 それから次フレームからはn_forced*5 = 2*5 = 10となるので、次のキーフレームは10秒のところとなって……、 というのを繰り返すので、キーフレームが5秒間隔で設定されることになります。

利用できる関数は他にもあります。
例えば、ifnot(x,y)x == 0のときyを返し、それ以外のときは0を返す関数です。
また使用できる値は他にもあります。
例えば、nは評価されるフレームのフレーム数を表します。0オリジンです。
よって以下のコマンドでも150フレームに1回キーフレームを入れることができます。

ffmpeg -i input.mp4 -vcodec h264 -force_key_frames expr:ifnot(mod(n,150),1) out.mp4

詳しくは、参考に載せる公式ドキュメントをご確認ください。

参考

公式ドキュメントでforce_key_framesに関する説明があります。

https://ffmpeg.org/ffmpeg.html#Advanced-Video-options

同じく公式ドキュメントで`FFmpegで使用できる関数の一覧があります。

https://ffmpeg.org/ffmpeg-utils.html#Expression-Evaluation

expr:以下の式の評価のされ方に関しては以下のページの説明が分かりやすかったです。

paulherron.com