ffmpegにはフレームレートの設定方法がいくつかあるが、同じオプションでも指定場所では効果が違ったりするので一般的な用途のまとめ。オリジナルよりもフレームレートが少ないときは同じように間引かれるが、出力結果も一致するとは限らない。動画時間が変わる方法に入力オプションの-rがあるが変わるのは映像の速度であり、音声の速度は変わらない。

実験用の動画を作る

  • 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

    公式ドキュメント:FFmpeg Filters Documentation : fps

  • フィルタとしてのframerate
    オリジナルよりフレームレートが少なければ間引く、多ければ前後フレームを平均して増やす。動画時間は変わらない。YUV限定でRGB出力不可。簡易的なフレーム補間をする framerate

    コマンド例
    ffmpeg -i input.mkv -vf framerate=30 -vcodec utvideo output.mkv

  • フィルタとしてのminterpolate
    フレーム補間フィルタなのでオリジナルよりも多い値を指定する。補間方法は平均と予測がある。動画時間は変わらない。ffmpeg でフレーム補間する minterpolate

    コマンド例(予測なのでかなり遅い)
    ffmpeg -i input.mkv -vf minterpolate=50 -vcodec utvideo output.mkv

  • 入力オプションとしての-r
    入力ファイルの前に指定する。総フレーム数はそのままに1秒あたりのフレームレートを指定するので、オリジナルよりフレームレートが少なければ動画時間が長く、多ければ動画時間が短くなる

    コマンド例
    ffmpeg -r 30 -i input.mkv -vcodec utvideo output.mkv

    公式ドキュメント:ffmpeg Documentation : Video Options

  • 出力オプションとしての-r
    入力ファイルの後に指定する。オリジナルよりフレームレートが少なければ間引く、多ければオリジナルのまま。動画時間は変わらない

    コマンド例
    ffmpeg -i input.mkv -r 30 -vcodec utvideo output.mkv

    公式ドキュメント:ffmpeg Documentation : Video Options

  • 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 -pix_fmt yuv420p out.mkv

    また、長時間の連番画像を100フレーム毎などフレームを間引いてタイムラプス(低速度撮影)にする場合はframestepフィルタを使う。
    コマンド例
    ffmpeg -framerate 30 -i img%03d.png -vf format=yuv420p,framestep=100 out.mkv

    参考記事:指定フレーム毎に出力する

  • 1枚画像から動画を作るときのフレームレートを決める-framerate
    これも-rではなくて-framerateを使う方がより正確であり、公式ドキュメントを見ても設定項目に書いてある

    コマンド例
    ffmpeg -framerate 30 -loop 1 -i img.png -pix_fmt yuv420p out.mkv

    公式ドキュメント:FFmpeg Formats Documentation : image2
    参考記事:【ffmpeg】動画から特定フレームを画像で出力する方法

再生速度の変更

再生速度を変更する場合は以下を参照。

重複フレーム

定期的に重複フレームがあるとき、ここでは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 -

具体的に説明すると-vsyncを無指定だと出力コンテナに合わせて自動設定する。MP4出力で-vsyncを無指定だと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出力で-vsyncを無指定だと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 -vsync 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の内容。

  • 0, passthrough
    デマクサからマクサにタイムスタンプを通す
  • 1, cfr
    入力した映像のフレームレートにより一定間隔のPTSにあわせてフレームを出力する。VFRだと途切れたフレームはその次のフレームを複製して固定フレームレートにする
  • 2, vfr
    一定間隔のPTSにあわせたフレームがなければ間引き、同じタイムスタンプを持つフレームがあっても間引く
  • -1, auto
    出力コンテナに合わせて1、2のどちらかを選ぶ。既定値

公式ドキュメント:ffmpeg Documentation : Advanced options

参考記事:

ログの見方

ちなみにエンコードの出力ログに表示される tbc, tbn, tbr について。https://qiita.com/ymotongpoo/items/eb9754b75606be117b70(qiitaの個人ページ統計データ公開後削除)より。

tbr, tbn, tbcはそれぞれの逆数が実際のタイムベースとなる。

  • tbr: 実際にビデオを表示する際に参照するレート。ビデオストリームからの類推値。インタレースだと倍値になってたりする。
  • tbn: コンテナ側に書かれたストリームのタイムベース。
  • tbc: 特定のコーデックにだけ存在するコーデック側のタイムベース。

tbc を修正するには-video_track_timescaleを使う。
ffmpeg -i input -c copy -video_track_timescale 30 output

3 thoughts on “ffmpeg でのフレームレート設定の違い

コメントを残す

メールアドレスが公開されることはありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)