PTSを変更することで再生速度を上げたり下げたり、複数のファイルを合わせたりするときにPTSを揃えたりするのに使うsetpts、asetptsフィルタの使い方。音声の速度変更にはrubberbandフィルタを使う方法もある。

サンプリング周波数を変えずにテンポとピッチを変える rubberband

FFmpeg 7.0からsetptsフィルタを通して映像を出力するとフレームレートが25に上書きされるので、fpsフィルタか、出力オプションの-rとfps数、または-fps_mode passthroughを追加する。

Ffmpeg: concatenate videos and keep framerate the same – Super User

24000/1001 fpsで出力する例。
-vf setpts=PTS-STARTPTS,fps=24000/1001
-vf setpts=PTS-STARTPTS -r 24000/1001

lavf/vf_setpts: unset output framerate · FFmpeg/FFmpeg@f121d95 · GitHub

アニメGIFの速度調整は-itsscaleで1/倍速を小数で指定する。
再エンコードせずに fps を変更する

PTSとDTSの生成

CTS(Composition Time Stamp)について。
timestamp – Different PTS values in ffmpeg and MP4 CTS values obtained using ctts and stts – Stack Overflow

ffmpeg 4.4からはビットストリームフィルタでPTSを書き換えられるようになったので再エンコードコード不要で映像の再生速度を変更できる。
ffmpeg -i input -af "atempo=2" -bsf:v setts=ts=TS/2 -c:v copy output

出力フレームレートを29.97fpsに変更する。
ffmpeg -i video -bsf:v setts=dts=N/((30000/1001)*TB):pts=PTS+N/((30000/1001)*TB)-DTS -c:v copy output

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

基本コマンド

PTSを0リセットする。
ffmpeg -i input -filter_complex setpts=PTS-STARTPTS -c:a copy output

再生速度を2倍にする。
ffmpeg -i input -filter_complex setpts=(PTS-STARTPTS)/2;atempo=2 output

再生速度を半分にする。
ffmpeg -i input -filter_complex setpts=2*(PTS-STARTPTS);atempo=0.5 output

【ffmpeg】倍速再生できる動画にエンコードする

2つの映像のPTSをリセットして縦に並べる。
ffmpeg -i input1 -i input2 -filter_complex [0:v]setpts=PTS-STARTPTS[v0];[1:v]setpts=PTS-STARTPTS[v1];[v0][v1]vstack output

公式ドキュメント:FFmpeg Filters Documentation : setpts, asetpts

オプション

評価式のオプション

  • FRAME_RATE, FR
    フレームレート。固定フレームレートだけを定義する。固定値。音声はNaN
  • PTS
    PTS(Presentation Timestamp)秒。PTS*TBでよく見る秒時間になる
  • N
    0から始まる映像フレーム数、または音声サンプル数
  • NB_CONSUMED_SAMPLES
    累積の音声サンプル数
  • NB_SAMPLES, S
    音声サンプル数。固定値
  • SAMPLE_RATE, SR
    音声のサンプリング周波数
  • STARTPTS
    入力したストリームの開始時のPTS時間
  • STARTT
    入力したストリームの開始時の時間
  • INTERLACED
    現在のフレームがインターレースかどうか。インターレースなら1。そうでなければ0
  • T
    現在のフレームの秒時間
  • POS
    読み込み位置でのバイトサイズ。分からなければ未定義になる
  • PREV_INPTS
    1つ前フレームのPTS
  • PREV_INT
    1つ前フレームのT
  • PREV_OUTPTS
  • PREV_OUTT
  • RTCTIME
    RTC のマイクロ秒。現在は非推奨。代わりに time(0) を使う
  • RTCSTART
    RTC のマイクロ秒。マイクロ秒で動く
  • TB
    タイムスタンプのタイムベース。固定値

応用例

PTSを25fpsに修正する。映像がそれよりも高fpsなら再生速度が遅くなり、低fpsなら再生速度が速くなる。selectフィルタなどで連続しない特定フレームで出力するときなどにも使う。
ffplay -f lavfi -i testsrc2=r=60,setpts=N/(25*TB)
ffplay -f lavfi -i testsrc2=r=10,setpts=N/(25*TB)

特定の映像フレームや音声サンプルを出力するselect, aselect

開始PTSを10秒進める。用途は動画の開始PTSが0開始でない場合に修正する。利用例
setpts=PTS+10/TB

trim, atrimフィルタで10秒から20秒までカットする。
trim=10:20,setpts=PTS+10/TB;atrim=10:20,asetpts=PTS+10/TB

フレーム数から現在のタイムスタンプ秒に変換しタイムスタンプを振り直す。一部をカットしてフレームレートを変えない時に使う。
setpts=N/FRAME_RATE/TB

音声サンプル数から現在のタイムスタンプ秒に変換しタイムスタンプを振り直す。一部をカットしてサンプルレートを変えない時に使う。
asetpts=N/SR/TB

タイムスタンプを振り直すのはtrim、select、segmentフィルタなどで複数に分割、特定フレームだけ出力する場合に使う。振り直さなければ元映像のPTSで分割されるので、出力されなかった映像は動かなくなる。
ffmpeg -i input -an -vf select=eq(pict_type\,I) -vsync 0 -t 5 output.mp4
ffmpeg -i input -an -vf select=eq(pict_type\,I),setpts=N/FRAME_RATE/TB -vsync 0 -t 5 output.mp4

動画の途中、ここでは10秒から12秒までをカットして前後をつなげる。
ffmpeg -i input -vf select='not(between(t\,10\,12))',setpts=N/FRAME_RATE/TB -af aselect='not(between(t\,10\,12))',asetpts=N/SR/TB output

25fpsから60fpsにフレーム落ちせずに再生速度を2.4倍にする。
settb=1/6000,setpts=PTS/2.4

ffmpeg speed up video from 25 to 60 fps dropping frames – Stack Overflow

10秒以内は3秒のオフセットを追加して、10秒以降は入力と同じPTS。
asetpts='if(lt(N\,10)\,PTS+3/TB\,PTS)'

How to use FFmpeg to adjust the audio pts of specific frames – Stack Overflow

部分的に速度を変えるには映像はtrimフィルタでカットしてsetptsフィルタで速度を変えて、音声はatrimフィルタでカットしてatempo、rubberbandフィルタで速度を変えてconcatフィルタでつなげる。
ffmpeg -i Soon.mp4 -filter_complex "[0:v]trim=0:2,setpts=PTS-STARTPTS[v1];[0:v]trim=2:5,setpts=2*(PTS-STARTPTS)[v2];[0:v]trim=5,setpts=PTS-STARTPTS[v3];[0:a]atrim=0:2,asetpts=PTS-STARTPTS[a1];[0:a]atrim=2:5,asetpts=PTS-STARTPTS,atempo=0.5[a2];[0:a]atrim=5,asetpts=PTS-STARTPTS[a3];[v1][a1][v2][a2][v3][a3]concat=n=3:v=1:a=1" -preset superfast -profile:v baseline output.mp4

One thought on “映像と音声の pts を扱う setpts, asetpts”

  • 匿名

    trim=10:20,setpts=PTS+10/TB;atrim=10:20,asetpts=PTS+10/TB
    はあ、trimフィルタはPTSをいじらないから、開始秒は20秒になるのか

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

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