可変フレームレート(VFR)とは、フレーム間の時間が固定されていない動画のことです。ソースは一定の間隔ではなく、何かが変化したときにフレームを記録します。画面録画ソフト、スマホのカメラ、ゲームキャプチャツールの多くは、しばしばVFRを生成します。録画には効率的ですが、「音がズレる」問題の非常に多くの割合を占める隠れた根本原因でもあります。一定の音声クロックが、さまよう映像クロックに揃い続けられないからです。多くの編集ソフトやプレイヤーは固定フレームレート(CFR)を前提としており、VFRを正しく扱えないこともあります。本記事では ffprobe でVFRを 検出 し、FFmpegでCFRに 変換 する方法を示します。

動作確認: FFmpeg 8.1


この記事でわかること

  • VFRとCFRとは何か、なぜVFRが音ズレを起こすのか
  • ffprober_frame_rateavg_frame_rate を比較してVFRの疑いを見分ける方法(ヒューリスティック)
  • -fps_mode cfr と目標レートでVFRをCFRに変換する方法
  • FFmpeg 8.x では -fps_mode を使うこと(旧来の -vsync も動くが非推奨)

音ズレやドリフトでここに来た場合、CFRへの変換がまさに「決定打」になることがよくあります。音ズレが徐々に進行する問題を直す変換後に音ズレする原因と解決法 も参照してください。


VFR と CFR

種類フレームのタイミング典型的なソース編集ソフト/プレイヤーとの相性
VFR(可変)フレームごとに間隔が変わる画面/スマホ/ゲーム録画誤処理されがち、ドリフトしうる
CFR(固定)一定間隔(例: 1/30秒ごと)放送、ほとんどのエンコーダ広く対応

CFRでは、すべてのフレームが予測可能な時刻に位置するため、一定の音声クロックが映像にロックし続けます。VFRではフレーム間隔がさまよい、固定レートを前提とするツールが徐々に音声をズラしていきます。これがクリップ全体で悪化するドリフトとして現れます。


手順①: ffprobe でVFRを検出する

VFRを「疑う」手早い方法は、報告される2つのレート、r_frame_rateavg_frame_rate(ファイル全体の平均)を比較することです。ここで r_frame_rate が何かを正しく理解しておくことが重要です。これは FFmpegが推測した基準レート——ストリーム内のすべてのタイムスタンプを表現できる最小のレート(最小公倍数に近い値)であって、「実際の」あるいは意図されたフレームレートではありません。したがって r_frame_rateavg_frame_rate が食い違うのは、そのファイルがVFRかもしれないという「ヒューリスティック(手がかり)」であって、それだけでは証拠になりません。真のCFRファイルでは、両者は通常等しいかほぼ等しくなります。

ファイルをざっと調べます。

ffprobe -hide_banner input.mp4

ストリームの概要で、FFmpegは 30 fps29.97 tbr といった値を表示します。2つのレートを明示的に読むには、映像ストリームの r_frame_rateavg_frame_rate フィールドを見ます。両者が食い違っていれば、そのファイルがVFRである強い手がかりと捉え、変換する前に確認しましょう。

# 例示的な比較(コマンドではありません)
r_frame_rate   = 60/1     <- FFmpegの基準レート推測値(最小公倍数に近い)
avg_frame_rate = 47/1     <- 実際の平均。異なる => VFRを疑う

近い・同一ならCFRを示唆し、目立った差はVFRのサインです。「疑う」だけでなくVFRを確定するには、実際のフレームごとの長さが変動しているかを確認します——例えばフレームごとのタイムスタンプを調べます(ffprobe -show_frames / -show_packetspkt_duration やタイムスタンプ間の差がどう変化するかを見る)。フレームの長さが実際に変動していればVFR、均一であれば、たとえ報告される2つのレートが食い違っていても実質的にCFRです。


手順②: 30 fps のCFRに変換する

変換するには、-fps_mode cfr で固定フレームレートに強制し、-r で目標レートを選びます。ソースの公称ケイデンスに合うレートを使います(画面/スマホ録画では一般的に30)。ここでは音声をそのままコピーするので、再エンコードされるのは映像だけです。

ffmpeg -i input.mp4 -fps_mode cfr -r 30 -c:v libx264 -c:a copy output.mp4
  • -fps_mode cfr — 出力を固定フレームレートに強制
  • -r 30 — 目標を毎秒30フレームに
  • -c:v libx264 — 映像を安定したタイムライン上に再エンコード(フレームタイミング変更に必須)
  • -c:a copy — 音声をそのままコピー(無劣化)

CFRに強制するとき映像の再エンコードは避けられません。固定のケイデンスに合わせるため、FFmpegがフレームを複製・削除する必要があるからです。音声は通常コピーできます。


手順③: 60 fps のCFRに変換する(高品質)

動きの激しいコンテンツ(ゲームプレイ、速いアクション)で60 fpsと高品質を狙う場合は、レートを上げてCRFを下げます。ここでは音声をAACに再エンコードします。ソースの音声コーデックが出力コンテナに適さない場合の安全な選択です。

ffmpeg -i input.mp4 -fps_mode cfr -r 60 -c:v libx264 -crf 18 -c:a aac output.mp4
  • -r 60 — 目標を毎秒60フレームに
  • -crf 18 — 既定より高品質(CRFが低いほど高品質・大きいファイル)
  • -c:a aac — MP4との幅広い互換性のため音声をAACに再エンコード

目標レートは意図して選んでください。30 fpsのソースを60 fpsにエンコードしてもフレームが複製されるだけで実際の滑らかさは増しません。レートを上げる特別な理由がない限り、-r はソースが実際に出すものに合わせてください。


重要: -fps_mode と非推奨の -vsync

FFmpeg 8.x では正しいオプションは -fps_mode cfr です。古いチュートリアルでは -vsync cfr(または -vsync 1)を使っているのを今でも見かけます。その記法は今のところ まだ動作します が、-vsync非推奨 であり、将来のリリースで削除される可能性があります。新しいコマンドでは -fps_mode を優先してください。両者は同じ内部挙動に対応します——cfr は必要に応じてフレームを複製・削除することで固定フレームレートに強制します。

オプションFFmpeg 8.x での状態使うべきか
-fps_mode cfr現行、推奨はい
-vsync cfr / -vsync 1非推奨、まだ動作いいえ(旧来のみ)

まとめ表

目的コマンド
VFRの疑いffprobe -hide_banner input.mp4r_frame_rateavg_frame_rate を比較)
CFR 30に変換、音声維持ffmpeg -i input.mp4 -fps_mode cfr -r 30 -c:v libx264 -c:a copy output.mp4
CFR 60に変換、高品質ffmpeg -i input.mp4 -fps_mode cfr -r 60 -c:v libx264 -crf 18 -c:a aac output.mp4

VFR→CFRという枠組みではなく、単にfpsを変えたい場合は フレームレートを変更する を参照してください。


よくある質問

自分のファイルがVFRだと確実に判断するには?

r_frame_rateavg_frame_rate の比較はあくまで「ヒューリスティック(手がかり)」です。r_frame_rate はFFmpegが推測した基準レート(最小公倍数に近い値)であり実際のフレームレートではないため、不一致はVFRを「示唆」するにすぎません。確定するには、実際のフレームごとの長さを調べます(例: ffprobe -show_frames / -show_packets でフレームごとのタイムスタンプを確認)。フレーム間隔が変動していれば真のVFR、均一であれば不一致があっても実質的にCFRです。画面・スマホ・ゲームの録画は、VFRであることの方がはるかに多いです。

なぜVFRは音ズレを起こすのですか?

音声は一定のサンプルクロックで再生されますが、VFRの映像フレームは不規則な間隔で到着します。一定レートを前提とするツールが徐々に両者をズラし、クリップ全体で悪化するドリフトを生みます。CFRに変換すれば音声がロックできる固定ケイデンスが得られます——音ズレが徐々に進行する問題を直す を参照。

VFRをCFRに変換するには映像の再エンコードが必要ですか?

はい。固定フレームレートに強制するには、固定ケイデンスに合わせてフレームを複製・削除する必要があり、映像の再エンコードを伴います。ただし音声は -c:a copy でコピーできることが多いです。

目標フレームレートは何にすべきですか?

-r はソースの公称レートに合わせてください——画面/スマホ録画なら通常30、ゲームプレイなら60です。30 fpsのソースを60 fpsにエンコードしてもフレームが複製されるだけで、実際の滑らかさは増しません。

-vsync と -fps_mode のどちらを使うべきですか?

-fps_mode cfr を使ってください。FFmpeg 8.x では -vsync は非推奨です。まだ動作しますが旧来扱いとすべきです。新しいコマンドでは -fps_mode を使ってください。


関連記事


Tested with FFmpeg 8.1 — verified with our command-check script
一次ソース: ffmpeg.org/ffmpeg.html / ffmpeg.org/ffmpeg-filters.html#aresample