ffmpegにはフレームレートの設定方法がいくつかあるが、同じオプションでも指定場所では効果が違ったりするので一般的な用途のまとめ。オリジナルよりもフレームレートが少ないときは同じように間引かれるが、出力結果も一致するとは限らない。オプションの-rは出力コンテナによって既定値が異なるのでMP4出力時と今回テストしているMKVとでは結果が異なり以下に説明している-fps_modeも併用する。
公式Wiki:ChangingFrameRate – FFmpeg
ffmpeg – Framerate vs r vs Filter fps – Stack Overflow
changing the framerate: “fps=X” filter vs “-r X” option : ffmpeg
実験用の動画を作る
- 0番から249番までの250フレーム、25fps の基本動画(手軽)
ffmpeg -f lavfi -i testsrc2=d=10 -vcodec utvideo input.mkv
- 0番から249番までの250フレーム、25fps の基本動画
ffmpeg -f lavfi -i testsrc=d=10,drawtext=fontfile="C\\:/Windows/Fonts/msgothic.ttc:text='%{n}':fontsize=30:x=W-tw:y=H-th" -vcodec utvideo input.mkv
コマンド例
- フィルタとしての
fps
オリジナルよりフレームレートが少なければ間引く、多ければ重複フレームをつくる。動画時間は変わらないコマンド例
ffmpeg -i input.mkv -vf fps=30 -vcodec utvideo output.mkv
参考記事:フレームレートを変更するfps
- フィルタとしての
framerate
オリジナルよりフレームレートが少なければ間引く、多ければ前後フレームを平均して増やす。動画時間は変わらない。YUV限定でRGB出力不可。コマンド例
ffmpeg -i input.mkv -vf framerate=30 -vcodec utvideo output.mkv
- フィルタとしての
minterpolate
フレーム補間フィルタなのでオリジナルよりも多い値を指定する。補間方法は平均と予測がある。動画時間は変わらない。コマンド例(予測なのでかなり遅い)
ffmpeg -i input.mkv -vf minterpolate=50 -vcodec utvideo output.mkv
- 入力オプションとしての-r
入力ファイルの前に指定する。総フレーム数はそのままに1秒あたりのフレームレートを指定するので、オリジナルよりフレームレートが少なければ動画時間が長く、多ければ動画時間が短くなる。-c copyと併用しても効果がない。コマンド例
ffmpeg -r 30 -i input.mkv -vcodec utvideo output.mkv
公式ドキュメント:ffmpeg Documentation : Video Options
- 出力オプションとしての-r
入力ファイルの後に指定する。オリジナルよりフレームレートが少なければ間引く、多ければオリジナルのまま。動画時間は変わらない。だたしこの-rは出力コンテナによって既定値が異なるのでMP4出力時と今回テストしているMKVとでは結果が異なり以下に説明している-fps_modeも併用する。-c copyと併用しても効果がない。コマンド例
ffmpeg -i input.mkv -r 30 -vcodec utvideo output.mkv
ffmpeg -i input.mkv -r 30 -vcodec libx264 -preset ultrafast output.mp4出力コンテナ 出力オプションの-r frames time 備考 mp4 20 201 10.00 間引く mkv 20 202 10.05 間引く mp4 30 300 9.96 重複フレーム mkv 30 250 9.96 変化なし 公式ドキュメント:ffmpeg Documentation : Video Options
- 出力オプションとしての-fpsmax
ffmpeg 4.4以降から使える。この値よりも高い値とのときの上限を指定する。オリジナルのほうが低ければ変更しない。-rと併用できない。ストリームコピーすると機能しない dshow
としての-framerate
Windows の DirectShow 入力での入力フレームレート。SCFFなどの仮想デバイスのように任意に指定できる場合と、キャプチャカードやウェブカメラのように任意に指定できない場合があるコマンド例
ffmpeg -rtbufsize 100MB -f dshow -framerate 30 -i video=device_name -vcodec utvideo output.mkv
公式ドキュメント:FFmpeg Devices Documentation : dshow
- 連番画像を入力するときのフレームレートを決める-framerate
連番画像を入力するときのフレームレートは-rではなくて-framerateを使う方がより正確であり、公式ドキュメントを見ても設定項目に書いてある
コマンド例
ffmpeg -framerate 30 -i img%03d.png -vf colorspace=all=bt709:iall=bt601-6-625:fast=1 -pix_fmt yuv420p -colorspace 1 -color_primaries 1 -color_trc 1 out.mp4
また、長時間の連番画像を100フレーム毎などフレームを間引いてタイムラプス(低速度撮影)にする場合は
framestep
フィルタを使う。
コマンド例
ffmpeg -framerate 30 -i img%03d.png -vf colorspace=all=bt709:iall=bt601-6-625:fast=1,framestep=100 -pix_fmt yuv420p -colorspace 1 -color_primaries 1 -color_trc 1 out.mp4
参考記事:指定フレーム毎に出力する
- 1枚画像から動画を作るときのフレームレートを決める-framerate
これも-rではなくて-framerateを使う方がより正確であり、公式ドキュメントを見ても設定項目に書いてあるコマンド例
ffmpeg -framerate 30 -loop 1 -i img.png -vf colorspace=all=bt709:iall=bt601-6-625:fast=1 -pix_fmt yuv420p -colorspace 1 -color_primaries 1 -color_trc 1 out.mp4
公式ドキュメント:FFmpeg Formats Documentation : image2
参考記事:【ffmpeg】動画から特定フレームを画像で出力する方法
再生速度の変更
再生速度を変更する場合は以下を参照。
- 再エンコードせずに fps を変更する
- 映像と音声の pts を扱う setpts, asetpts
- 【ffmpeg】倍速再生できる動画にエンコードする
- サンプリング周波数を変えずにテンポとピッチを変える rubberband
重複フレーム
定期的に重複フレームがあるとき、ここではNTSCの30000/1001フレームレートに5分の1フレーム間引いた24000/1001フレームレートを指定している。
ffmpeg -i input -vf mpdecimate output
ffmpeg -i input -vf decimate,setpts=N/(24000/1001)/TB output
ffmpeg – remove sequentially duplicate frames – Stack Overflow
shuffleframes
フィルタでも一定間隔の重複フレームを間引くことができる。
指定フレーム毎に順番を入れ換える shuffleframes
フィルタで重複フレームを自動的に間引くならdecimate、mpdecimate
フィルタを使う。
フレームを間引くdecimate、mpdecimate
可変フレームレート
可変フレームレートとはPTS間隔が一定でない映像のことである。可変フレームレートに平均フレームレートをそれぞれのオプションに指定した場合、フィルタのfps, framerate, minterpolate
と入力オプションとしての-rは PTS間隔を平均化させるが、出力オプションとしての-rは PTS間隔を平均化させない。
最初のコマンドで5フレーム毎に1フレーム間引きPTS間隔を修正しないのでVFRになる。
ffmpeg -f lavfi -i testsrc2=d=4:r=25 -vf select='mod(n,5)' -c:v ffv1 25.mkv
ffmpeg -i 25.mkv -vf fps=25,vfrdet -f null -
ffmpeg -r 25 -i 25.mkv -vf vfrdet -f null -
ffmpeg -i 25.mkv -r 25 -vf vfrdet -f null -
具体的に説明すると-fps_modeを無指定だと出力コンテナに合わせて自動設定する。MP4出力で-fps_modeを無指定だとVFRにならず、間引かれたフレームはその次のフレームを複製する。
ffmpeg -f lavfi -i testsrc2=d=4:r=25 -vf select='mod(n,5)' vfr.mp4
ffmpeg -i vfr.mp4 -an -vf vfrdet -f null -
MKV出力で-fps_modeを無指定だとVFRになる。
ffmpeg -f lavfi -i testsrc2=d=4:r=25 -vf select='mod(n,5)' vfr.mkv
ffmpeg -i vfr.mkv -an -vf vfrdet -f null -
ffprobe -v error -i vfr.mkv -select_streams v:0 -show_frames -show_entries frame=pkt_pts_time -of csv=p=0 > vfr.mkv.txt
フレームを間引いた動画にPTSを振り直すなら目的のフレームレートを指定したsetpts
フィルタを使う。間引く前のフレームレートが25で5分の1を間引く、つまり20を指定する。
ffmpeg -i testsrc2.mp4 -vf select='mod(n,5)',setpts=N/20/TB -fps_mode vfr vfr-setpts.mp4
ffmpeg -i vfr-setpts.mp4 -an -vf vfrdet -f null -
ffprobe -v error -i vfr-setpts.mp4 -select_streams v:0 -show_frames -show_entries frame=pkt_pts_time -of csv=p=0 > vfr-setpts.mp4.txt
-vsyncの内容。ffmpeg 5.1から-vsyncが廃止予定で代わりに-fps_modeが追加され、-vsyncの互換性とストリーム指定ができるように。
- -fps_mode[:stream_specifier] parameter (output,per-stream)
- passthrough
デマクサからマクサにタイムスタンプを通す - cfr
入力した映像のフレームレートにより一定間隔のPTSにあわせてフレームを出力する。VFRだと途切れたフレームはその次のフレームを複製して固定フレームレートにする - vfr
一定間隔のPTSにあわせたフレームがなければ間引き、同じタイムスタンプを持つフレームがあっても間引。つまり可変フレームレートを固定フレームレートに変換しないく - drop
passthroughと同じだが、すべてのタイムスタンプを破棄する - auto
出力コンテナに合わせてcfr、vfrのどちらかを選ぶ。既定値
指定例:
-fps_mode cfr -fps_mode:v cfr -fps_mode:0 cfr
-fps_mode dropでタイムスタンプを作り直すことができる。
ffmpeg -i input.mp4 -fps_mode drop -c copy output.mp4
もしくは生データにいったん出力してMP4に入れ直す方法もある。適宜正しいフレームレートを-rで指定する。
ffmpeg -i input.mp4 -c:v copy -bsf:v h264_mp4toannexb input.h264
ffmpeg -fflags +genpts -r 30000/1001 -i input.h264 -c:v copy output.mp4
FFmpeg: recreate timestamps without reencoding – Super User
公式ドキュメント:ffmpeg Documentation : Advanced options
参考記事:
ログの見方
ちなみにエンコードの出力ログに表示される tbc, tbn, tbr について。https://qiita.com/ymotongpoo/items/eb9754b75606be117b70(qiitaの個人ページ統計データ公開後削除)より。
tbr, tbn, tbcはそれぞれの逆数が実際のタイムベースとなる。
- tbr: 実際にビデオを表示する際に参照するレート。ビデオストリームからの類推値。インタレースだと倍値になってたりする。
- tbn: コンテナ側に書かれたストリームのタイムベース。
- tbc: 特定のコーデックにだけ存在するコーデック側のタイムベース。
タイムベースはタイムスケールの1刻みの時間。
timebase = 1/timescale
pts_time = frame * pts * timebase
Timebase = 1/75; Timescale = 75 Frame pts pts_time 0 0 0 x 1/75 = 0.00 1 3 3 x 1/75 = 0.04 2 6 6 x 1/75 = 0.08 3 9 9 x 1/75 = 0.12 ...
- video – Meaning of ffmpeg output (tbc, tbn, tbr) – Stack Overflow
- What is fps, tbr, tbn, tbc in `ffmpeg`? – Super User
- FFmpeg-users – What does the output of ffmpeg mean? tbr tbn tbc etc? : archive.org
- What is video timescale, timebase, or timestamp in ffmpeg? – Stack Overflow
- Using ffmpeg option -video_track_timescale 25 produces a video with 1k tbn. Why is this? – Stack Overflow
- timescale, timebase, pts in video/audio frames | by Selvan | Aug, 2021 | Medium
- ffmpeg – How to add black frames and keep the framerate? – Stack Overflow
tbctbnを修正するには整数指定の-video_track_timescaleを使う。MOV、MP4コンテナ専用。
ffmpeg -i input -c copy -video_track_timescale 30 output.mp4
タイムコードについて
ffmpegではmovコンテナに入っているようなメタデータにあるタイムコードを映像におそらく?描写できない。
drawtext
フィルタでタイムコードを描写できるが整数フレームレートしか指定できず、ドロップフレームのタイムコードを扱えない。
タイムコードを0秒リセットにするには-mapに負の値を指定する。
ffmpeg -i input.mov -map 0 -map -0:d -c copy -timecode 00:00:00:00 output.mov
フレームを間引く方法が分からなかったので大変助かりました。
-vf fps、-vf framerate、-r の3つがとても似ていますが、通常は特に使い分ける必要はないのでしょうか?
間引くフレームに指定がないのなら使い分ける必要はないですが
nフレーム毎に間引くtrim, decimateフィルタや、
映像の一致の割合で間引くmpdecimateフィルタなど
使い分けることもできます。
https://looooooooop.blog.fc2.com/blog-entry-1154.html
https://looooooooop.blog.fc2.com/blog-entry-903.html#decimate
[…] ffmpeg でのフレームレート設定の違い | ニコラボ […]
[…] FFmpeg でのフレームレート設定の違い | ニコラボ […]
[…] FFmpeg でのフレームレート設定の違い | ニコラボ […]
[…] FFmpeg でのフレームレート設定の違い | ニコラボ […]
[…] FFmpeg でのフレームレート設定の違い | ニコラボ […]