「動画を 2 倍速にしたら音だけ元のままで気持ち悪い」「スローにしたらカクついた」「atempo=3.0 がエラーになる」——再生速度変更は単純そうで音ずれの罠が多い処理です。FFmpeg では映像用 setpts と音声用 atempo正しい比率で組み合わせるのが正解。本記事では 0.25 倍から 10 倍までの早送り・スロー、ピッチ保持、部分的な速度変更まで、コピペで動くコマンドで網羅します。所要時間:12分。

動作確認: FFmpeg 8.1(Windows / macOS / Linux 共通)


この記事でわかること

  1. setptsatempo の関係(係数の方向に注意)
  2. 早送り(2 倍・4 倍・10 倍)コマンドと音声同期
  3. スロー再生(0.5 倍・0.25 倍)コマンド
  4. atempo の制約(0.5〜100)と古い FFmpeg 向け回避策
  5. 音を消して映像だけ速度変更する方法
  6. ピッチを保ったまま速度変更する rubberband フィルタ
  7. 時間範囲ごとに速度を変える方法
  8. minterpolate で滑らかなスロー再生
  9. トラブルシューティング & FAQ

速度変更の基本: setpts と atempo

FFmpeg の速度変更は「映像のタイムスタンプ」と「音声のテンポ」を別々に操作します。それぞれの方向を間違えると音ずれの原因になります。

用途フィルタ係数の意味例(2 倍速)
映像setpts=N*PTS小さいほど速い(PTS を圧縮)setpts=0.5*PTS
音声atempo=N大きいほど速い(再生速度倍率)atempo=2.0

重要: setpts の係数は再生速度倍率の逆数です。2 倍速にするには PTS を半分(0.5*PTS)に、半分速にするには PTS を倍(2*PTS)にします。一方 atempo は素直に倍率そのものを書きます。

速度・係数早見表

再生速度setpts 係数atempo 係数
0.25 倍(4 倍スロー)4*PTS0.5,atempo=0.5(または 0.25
0.5 倍(2 倍スロー)2*PTS0.5
1.0 倍(等速)1*PTS1.0
2.0 倍(早送り)0.5*PTS2.0
4.0 倍0.25*PTS4.0
10.0 倍0.1*PTS10.0

FFmpeg 4.2 以降、atempo は単体で 0.5〜100 倍まで対応します。古いビルドでは 0.5〜2.0 が上限なので、atempo=2.0,atempo=2.0 のように連結します(後述)。


早送り(2 倍・4 倍・10 倍)

2 倍速(音声同期あり)

ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" \
  -map "[v]" -map "[a]" output_2x.mp4

setpts=0.5*PTS で映像のタイムスタンプを半分に圧縮し、atempo=2.0 で音声を 2 倍テンポに加速します。-map "[v]" -map "[a]"filter_complex の出力を明示的にマップしないと音声が無音になることがあります。

4 倍速

ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.25*PTS[v];[0:a]atempo=4.0[a]" \
  -map "[v]" -map "[a]" output_4x.mp4

20 秒の素材なら 5 秒に圧縮されます。atempo=4.0 は FFmpeg 4.2 以降であれば単体でそのまま動きます。

10 倍速

ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.1*PTS[v];[0:a]atempo=10.0[a]" \
  -map "[v]" -map "[a]" output_10x.mp4

10 倍速は監視カメラのダイジェスト・タイムラプスの代替などに便利です。音声は人声としては聞き取れなくなるので、後述の -an で音声をカットするほうが現実的です。


スロー再生(0.5 倍・0.25 倍)

0.5 倍速(半分速)

ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=2*PTS[v];[0:a]atempo=0.5[a]" \
  -map "[v]" -map "[a]" output_half.mp4

setpts=2*PTS で各フレームの表示時間を倍に伸ばし、atempo=0.5 で音声を半分のテンポに減速します。

0.25 倍速(4 倍スロー)

ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=4*PTS[v];[0:a]atempo=0.5,atempo=0.5[a]" \
  -map "[v]" -map "[a]" output_quarter.mp4

atempo=0.5 を連結することで合計 0.25 倍にできます。FFmpeg 4.2 以降なら atempo=0.25 単体でも動作しますが、互換性を考えるなら連結が安全です。

スローのカクつき: setpts で時間を伸ばしただけではフレーム数は増えません。元が 30fps なら 0.25 倍では実効 7.5fps となりカクつきます。次節の minterpolate でフレーム補間できます。


音声を同期させる atempo の制約と回避

atempo は単一インスタンスで以下の範囲です:

FFmpeg バージョン単体での範囲連結での実用範囲
4.1 以前0.5〜2.0連結で任意倍率
4.2 以降0.5〜100.0通常は単体で十分

古い FFmpeg で 0.25 倍速にする(連結回避)

# Wrong: 単体 atempo=0.25 は 4.1 以前ではエラー
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=4*PTS[v];[0:a]atempo=0.25[a]" \
  -map "[v]" -map "[a]" output_bad.mp4
# 正しい: 0.5 を 2 段連結で 0.25
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=4*PTS[v];[0:a]atempo=0.5,atempo=0.5[a]" \
  -map "[v]" -map "[a]" output_quarter_safe.mp4

古い FFmpeg で 8 倍速にする

ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.125*PTS[v];[0:a]atempo=2.0,atempo=2.0,atempo=2.0[a]" \
  -map "[v]" -map "[a]" output_8x.mp4

atempo=2.0 を 3 段連結で 8 倍。係数の積(2×2×2)が目標倍率と一致するように組みます。


音を消して映像だけ速度変更

無音でいいタイムラプスや監視カメラ的な早送りでは、音声処理を省略するとコマンドがシンプルになります。

ffmpeg -i input.mp4 -vf "setpts=0.25*PTS" -an output_4x_silent.mp4
  • -an — 音声ストリームを削除
  • -vf — 映像 1 系統だけなら filter_complex ではなく -vf で十分
# スロー(音声なし)
ffmpeg -i input.mp4 -vf "setpts=2*PTS" -an output_slow_silent.mp4

音声を残したいが速度同期は諦める、という運用なら -c:a copy で元音声を流用できます(ただし映像と長さが合わなくなります)。


ピッチを保ったまま速度変更(rubberband)

atempo は単純な再サンプリングなので、3 倍速にすると音程が「チップマンク(早口で甲高い)」になります。ピッチ(音高)を保ったまま速度だけ変えるには rubberband フィルタを使います。

ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]rubberband=tempo=2.0[a]" \
  -map "[v]" -map "[a]" output_2x_pitch_keep.mp4

rubberband=tempo=2.0 で音声を 2 倍速にしつつ音程を維持します。インタビュー・講義など「内容の聞き取りやすさ」が重要な素材で有効です。

# スロー再生でも音程キープ(モノマネ防止)
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=2*PTS[v];[0:a]rubberband=tempo=0.5[a]" \
  -map "[v]" -map "[a]" output_half_pitch_keep.mp4

rubberband--enable-librubberband 付きの FFmpeg ビルドが必要です。Windows なら gyan.dev のフルビルド、macOS は brew install ffmpeg、Ubuntu は公式 ppa 版で利用可能。ffmpeg -filters | grep rubberband で確認できます。


部分的に速度を変える(時間範囲ごと)

「最初の 5 秒だけスロー、その後は等速」のような可変速度は 2 通りで実現できます。

方法 1: setpts 式で時間条件を書く(音声なし向け)

ffmpeg -i input.mp4 -vf "setpts='if(lt(T,5),2,1)*PTS'" -an output_var.mp4

T は出力フレームのタイムスタンプ(秒)、if(lt(T,5),2,1) は「5 秒未満なら 2、それ以外なら 1」を返します。つまり最初 5 秒を 0.5 倍速(2 倍 PTS)、以降を等速にしています。

方法 2: trim + setpts で分割して concat(音声同期可能)

ffmpeg -i input.mp4 -filter_complex \
  "[0:v]trim=0:5,setpts=2*PTS[v1];[0:a]atrim=0:5,asetpts=PTS-STARTPTS,atempo=0.5[a1]; \
   [0:v]trim=5:20,setpts=PTS-STARTPTS[v2];[0:a]atrim=5:20,asetpts=PTS-STARTPTS[a2]; \
   [v1][a1][v2][a2]concat=n=2:v=1:a=1[v][a]" \
  -map "[v]" -map "[a]" output_var_audio.mp4

trim / atrim で時間範囲を切り出し、それぞれ速度を変えてから concat で連結します。音声同期が必要ならこちらを採用。可変速度は複雑なので、まず -an 版で映像だけ確認し、音声は後付けするのが楽です。


フレームレートを保ちつつスロー(minterpolate)

setpts=2*PTS だけのスローは元のフレームを引き延ばすだけでフレーム数が増えません。minterpolate フィルタはモーションベクトルから中間フレームを生成し、本物の滑らかなスローを作ります。

ffmpeg -i input.mp4 -vf "setpts=4*PTS,minterpolate=fps=60:mi_mode=mci" -an output_smooth_slow.mp4
  • setpts=4*PTS — 4 倍スロー
  • minterpolate=fps=60 — 出力フレームレートを 60fps に
  • mi_mode=mci — Motion Compensated Interpolation(推定中間フレームを生成)
mi_mode意味用途
dupフレーム複製のみ高速処理、品質低
blendクロスフェード混合中間品質、軽量
mciモーション補間(推奨)高品質スロー

minterpolate は CPU 負荷が高く、HD 動画では実時間の数十倍かかることもあります。長尺は -ss / -to で範囲を絞ってからかけるのが現実的です。


速度変更後にコーデックを変える

速度変更フィルタは映像を再エンコードするので、ついでに圧縮設定を最適化できます。

ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" \
  -map "[v]" -map "[a]" -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output_optimized.mp4
  • -crf 23 — 標準品質(18〜28 が実用範囲、低いほど高品質)
  • -preset medium — 速度と圧縮率のバランス
  • -c:a aac -b:a 128k — AAC 128kbps の標準音声

H.265 で容量を抑えたい場合は -c:v libx265 -crf 28 に変更します。


トラブルシューティング

1. 音だけ・映像だけが速くなる

原因: setptsatempo のどちらか片方しか書いていない、または -map が抜けている。

# Wrong: 映像しか速くならない(音声は元のまま流れて長さが合わない)
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" output_bad.mp4
# 正しい: 両方を filter_complex で処理し、map で出力に明示
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" \
  -map "[v]" -map "[a]" output_ok.mp4

2. 「Value 3.000000 for parameter ‘tempo’ out of range」エラー

原因: FFmpeg 4.1 以前で atempo に 2.0 を超える値を指定した。
解決: バージョンを上げるか、atempo=2.0,atempo=1.5 のように連結(積で 3.0)。

3. 音声と映像のリップシンクが少しだけズレる

原因: setpts 係数と atempo 係数の積(≈ 倍率)が一致していない。
解決: setpts=N*PTSatempo=1/N が逆数関係になるよう厳密に合わせる。0.5*PTSatempo=2.00.333*PTSatempo=3.0 など。

4. スローにしたらフレームがカクつく

原因: setpts だけだと既存フレームを伸ばすため、実効 fps が低下する。
解決: minterpolate=fps=60:mi_mode=mci を後段に追加(前述)。

5. 出力ファイルの長さがおかしい

原因: concat 後にタイムスタンプがリセットされていない、または -shortest を付け忘れた。
解決: 各セグメント内で setpts=PTS-STARTPTS / asetpts=PTS-STARTPTS を入れて時間原点をリセットする。


FAQ

Q1. 音と映像のどちらかだけが速くなってしまうのはなぜ?
A. -vf を使うと音声は処理されません。-filter_complex で映像と音声を別々に書き、-map "[v]" -map "[a]" で出力にマップしてください。-vf 派でも -af "atempo=N" を併用すれば両方を処理できます。

Q2. 10 倍速にしたら音が壊れて聞こえます。
A. atempo=10.0 は単体ではノイズ気味になります。声を残したい場合は rubberband=tempo=10 のほうが自然ですが、それでも 5 倍以上は実用性が落ちます。早送りプレビュー目的なら -an で音声をカットするのが定石です。

Q3. スローモーションがカクつくのは仕様?
A. はい、setpts は時間を引き延ばすだけでフレームを増やしません。元 30fps を 0.25 倍にすると実効 7.5fps です。minterpolate=fps=60:mi_mode=mci で本物のフレーム補間ができます。

Q4. 速度変更後にコーデックを変えたいです。
A. 速度変更は再エンコードを伴うので、同じコマンドで -c:v libx264 -crf 23 -c:a aac -b:a 128k を指定するだけで OK です。フィルタと出力コーデックは独立して指定できます。

Q5. iPhone のスロー動画を更にスローにできますか?
A. できます。iPhone のスロー素材は実際は 240fps で記録されているので、setpts=2*PTS を適用しても 120fps 相当のなめらかさが残ります。ffprobe -show_streamsr_frame_rate を確認してから倍率を決めると失敗しません。

Q6. 速度変更しても字幕(埋め込み)の同期は維持されますか?
A. ハードサブ(焼き付け)なら映像と一緒に再エンコードされるため自動同期します。ソフトサブは別ストリームなので手動で -itsoffsetpts 調整が必要です。


関連記事


動作確認: ffmpeg 8.1 / Windows 11 + Ubuntu 24.04
一次ソース: ffmpeg.org/ffmpeg-filters.html#setpts / ffmpeg.org/ffmpeg-filters.html#atempo