FFmpeg では fps フィルタ 1 行でフレームレートを変換できます。60fps の動画を Web 向けに 30fps にする、映画らしい 24fps にする、といった用途に使えます。setpts と組み合わせればタイムラプスも作れます。

まず現在のフレームレートを確認する

変換前に元ファイルのフレームレートを確認します。

ffprobe -v error -select_streams v:0 \
  -show_entries stream=r_frame_rate,avg_frame_rate \
  -of default=noprint_wrappers=1 input.mp4

出力例:

r_frame_rate=60000/1001
avg_frame_rate=60000/1001
フィールド 意味
r_frame_rate FFmpeg が推定したストリームの基本フレームレート(すべてのタイムスタンプを表せる最小のレート)
avg_frame_rate 実際のフレーム数から算出した平均フレームレート

可変フレームレート(VFR)動画では、両者が異なることがあります。60000/1001 ≒ 59.94fps(NTSC規格)。

コマンド例

1. フレームレートを下げる(fps フィルタ — 推奨)

# 60fps → 30fps(Web配信・SNS向け)
ffmpeg -i input.mp4 -vf fps=30 -c:v libx264 -crf 23 -c:a copy output.mp4

# 29.97fps → 25fps(PAL規格・欧州向け)
ffmpeg -i input.mp4 -vf fps=25 -c:v libx264 -crf 23 -c:a copy output.mp4

# 30fps → 24fps(映画的な雰囲気)
ffmpeg -i input.mp4 -vf fps=24 -c:v libx264 -crf 23 -c:a copy output.mp4
  • fps=N — 目標フレームレートを指定。余分なフレームを削除してタイムスタンプ基準で間引く
  • -c:a copy — 音声はコーデックを変えずにコピー(高速・劣化なし)

2. -r オプションで指定する(シンプルな場合)

# 出力フレームレートを30fpsに指定
ffmpeg -i input.mp4 -r 30 -c:v libx264 -crf 23 -c:a copy output.mp4

-r はエンコード直前にフレームを複製・削除します。fps フィルタも同じようにタイムスタンプを見て複製・削除しますが、フィルタの中で処理するので scale などほかのフィルタと 1 つのチェーンにまとめられます。

出力側の -r と fps は、どちらもフレームを複製・間引きすることがあります。どちらを使ってもカクつきや音ズレが必ず直るわけではないので、出力の長さ、音声の同期、動きのある区間を確認してください。

3. フレームレートを上げる(フレーム複製)

# 24fps → 60fps(既存フレームを複製して 60fps にそろえる)
ffmpeg -i input.mp4 -vf fps=60 -c:v libx264 -crf 23 -c:a copy output.mp4

フレームレートを上げる場合、fps フィルタは既存フレームを複製して目標のレートに合わせます。中間フレームは生成しません。モーション推定で補間するには minterpolate フィルタが必要です。

4. タイムラプス:30 倍速にする

# 30倍速のタイムラプス(60秒 → 2秒、音声なし)
ffmpeg -i input.mp4 -vf "setpts=PTS/30,fps=30" -an -c:v libx264 -crf 23 output_timelapse.mp4
  • setpts=PTS/30 — 時間を 1/30 に縮めて 30 倍速にする
  • fps=30 — 30fps にそろえる(余ったフレームは間引かれる)
  • -an — 音声を外す(映像だけが短くなるため)

-vf fps=1 だけでは 1 秒に 1 枚のカクカクした動画になるだけで、長さは変わりません(60 秒の動画は 60 秒のまま)。速くするには setpts で時間を縮めます。

5. 連番画像から動画を作成

ffmpeg -framerate 1 -i img%03d.png -c:v libx264 -r 30 -pix_fmt yuv420p output.mp4
  • -framerate 1 — 入力画像を 1fps で読み込む(1枚=1秒のスライドショー。タイムラプスにするなら -framerate 30 のように1秒あたりの枚数を増やす)
  • -r 30 — 出力を 30fps にする(1枚が 30 フレームに複製)
  • -pix_fmt yuv420p — 互換性の高いピクセルフォーマット

6. バッチ処理:フォルダ内全動画を 30fps に変換

for f in *.mp4; do
  ffmpeg -i "$f" -vf fps=30 -c:v libx264 -crf 23 -c:a copy "30fps_${f}" -y
done

-r オプション vs fps フィルタ 比較表

比較項目 -r(出力オプション) -vf fps=N(フィルタ)
処理タイミング エンコード直前 フィルタグラフ内(より早い段階)
タイムスタンプ参照 参照して複製・間引き 参照して複製・間引き
VFR 素材 CFR になるが、変換後の確認が必要 CFR になるが、変換後の確認が必要
他フィルタとの組み合わせ 可能 フィルタチェーンに統合可能
推奨用途 シンプルな変換 ほかのフィルタと組み合わせる変換

推奨: 迷ったら -vf fps=N を使います。ほかのフィルタと同じ -vf にまとめて書けます。VFR 素材(スマホ撮影・OBS 録画など)はどちらの方法でも CFR にできますが、変換後に長さと音声の同期を確認してください。

代表的なフレームレート一覧

fps 用途
24 / 23.976 映画標準。映画的な雰囲気
25 PAL規格(欧州・中東・アジア一部)
29.97 / 30 NTSC規格(日本・北米)、Web動画
50 PAL規格の高フレームレート
59.94 / 60 ゲーム・スポーツ・高品質Web動画
120 最新スマートフォン・ハイスピード撮影

オプション詳解

オプション 意味 推奨値
-vf fps=N フィルタグラフでフレームレートを変換 24 / 30 / 60
-r N 出力フレームレート指定(エンコード直前) シンプルな変換時
-framerate N 入力画像シーケンスの読み込み速度 タイムラプス作成時
-pix_fmt yuv420p ピクセルフォーマット指定 互換性確保に必須
-c:a copy 音声を無劣化コピー フレームレート変換では常に推奨

トラブルシューティング

エラー1: 変換後の動画が音声とズレる

症状: 映像と音声のタイミングがズレます
原因: -r を -i の前に付けています。入力側の -r は映像の時刻だけを付け直し、音声はそのままです(エラー4)。-i の後の -r と fps フィルタは、どちらもタイムスタンプを見てフレームを削除・複製するだけで音声は動かさないので、元の動画の同期が保たれます
解決策:

# フレームレートは -i の後で指定(変換後に長さと音声の同期を確認)
ffmpeg -i input.mp4 -vf fps=30 -c:v libx264 -crf 23 -c:a copy output.mp4

エラー2: タイムラプス変換後に音声が長い

症状: 映像は短いのに、音声が元の長さのまま残ります
原因: setpts で短くなるのは映像だけで、音声は元の長さのままです
解決策: タイムラプスでは音声を除去します:

ffmpeg -i input.mp4 -vf "setpts=PTS/30,fps=30" -an -c:v libx264 -crf 23 output.mp4

エラー3: Unknown encoder 'libx264'

原因: FFmpeg が libx264 なしでビルドされています
解決策: フル機能版の FFmpeg をインストールします:

sudo apt install ffmpeg        # Ubuntu/Debian
brew install ffmpeg            # macOS

エラー4: 変換後の動画が長くなり、スローになる

原因: -r を入力側(-i の前)に付けています。入力側の -r はファイルのタイムスタンプを無視して、指定したフレームレートで読み直します。60fps の動画に -r 30 を付けると全フレームが 30fps で並べ直され、長さが 2 倍のスローになります(音声は元の長さのまま)
解決策: -r または fps=N は -i の後に指定します:

# 間違い(入力側に -r)
ffmpeg -r 30 -i input.mp4 output.mp4

# 正しい(出力側に指定)
ffmpeg -i input.mp4 -vf fps=30 -c:v libx264 -crf 23 output.mp4

エラー5: 画像シーケンスが読み込めない(Could find no file or sequence with path ...)

原因: ファイル名のパターン(%03d の桁数など)や開始番号が、実際のファイルと合っていません。番号が 0〜4 以外から始まるときは -start_number で開始番号を指定します。なお -framerate を省略しても読み込みは失敗せず、25fps で読み込まれます
解決策:

# ファイル名パターンを確認してから実行
ls img*.png | head -3
# 出力例: img001.png img002.png img003.png → %03d を使う
ffmpeg -framerate 24 -i img%03d.png -c:v libx264 -pix_fmt yuv420p output.mp4

FAQ

Q1. -r と -vf fps=N はどちらを使えばいいですか?
A. 迷ったら -vf fps=N を使ってください。ほかのフィルタと 1 つのチェーンにまとめられます。-r もタイムスタンプを見てフレームを複製・間引きするので、単純な変換なら結果はほぼ同じです。スマホや OBS などの VFR 素材は、どちらで変換しても長さと音声の同期を確認してください。

Q2. フレームレートを上げると動きが滑らかになりますか?
A. fps フィルタは既存フレームを複製するだけなので、動きの滑らかさは元素材と同じです。滑らかにするには minterpolate フィルタ(モーション推定)が必要ですが、処理に時間がかかります。

Q3. 変換後のフレームレートを確認するには?

ffprobe -v error -select_streams v:0 \
  -show_entries stream=avg_frame_rate \
  -of default=noprint_wrappers=1 output.mp4

Q4. タイムラプス作成時に音声も残したい場合は?
A. 映像の時間軸が変わるため、そのまま残すと音声と映像がズレます。音楽などを別途追加するか、-an で音声なしにするのが現実的です。

Q5. 29.97fps(30000/1001)のような分数指定はできますか?
A. できます:

# 29.97fps(NTSC)で出力
ffmpeg -i input.mp4 -vf fps=30000/1001 -c:v libx264 -crf 23 output.mp4

関連記事