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