音と映像のズレが「常に一定量」なら、自動補正に頼らず手動でオフセットを当てるのが最も確実です。FFmpeg では adelay で音声に遅延を足す方法と、-itsoffset で映像・音声のどちらかを時間シフトする方法があり、ズレの向きで使い分けます。この記事では ffprobe でズレ量を測るところから、音が早い/遅いそれぞれのケースの直し方までを具体的に示します。

動作確認: FFmpeg 6.1(ubuntu-latest / GitHub Actions CI 検証済み)/対象 OS: Windows / macOS / Linux


音声遅延の種類

音ズレには大きく 2 種類あります:

パターン症状原因例
音声が映像より 遅れている口パクより音が後から出るマイク遅延、録画設定
音声が映像より 早い音が出てから口が動くキャプチャデバイスの遅延差

方法 1: adelay — 音声に遅延を追加する

音声が映像より 早すぎる 場合に、音声を遅らせます。

ステレオ音声に 500ms の遅延を追加する

ffmpeg -i input.mp4 \
  -af "adelay=500|500" \
  -c:v copy \
  output.mp4

500|500 はステレオの左チャンネル・右チャンネルそれぞれに 500ms の遅延を指定します。

モノラル音声の場合

ffmpeg -i input.mp3 \
  -af "adelay=300" \
  output.mp3

adelay パラメータ詳細

adelay=delays[|delays...]
  • 遅延量はチャンネルごとにパイプ(|)で区切って指定します
  • 単位はミリ秒(ms)
  • 0 で遅延なし
# 2チャンネル(ステレオ)に異なる遅延
ffmpeg -i input.mp4 -af "adelay=200|400" -c:v copy output.mp4

# 5.1chに対応する場合(6チャンネル)
ffmpeg -i input.mp4 -af "adelay=300|300|300|300|300|300" -c:v copy output.mp4

方法 2: -itsoffset — 入力ファイルのタイムスタンプをずらす

-itsoffset は入力ファイルのタイムスタンプをオフセットします。音声だけ、または映像だけを別入力として指定することで細かい制御ができます。

音声を 0.5秒 遅らせる(映像より音声が早い場合)

ffmpeg -i input.mp4 -itsoffset 0.5 -i input.mp4 \
  -map 0:v -map 1:a \
  -c:v copy -c:a copy \
  output.mp4
  1. 0:v — 1本目のファイルの映像(タイムスタンプそのまま)
  2. 1:a — 2本目のファイルの音声(0.5秒オフセットあり)

音声を 0.5秒 早める(音声が映像より遅れている場合)

ffmpeg -itsoffset 0.5 -i input.mp4 -i input.mp4 \
  -map 0:v -map 1:a \
  -c:v copy -c:a copy \
  output.mp4

今度は映像(0:v)の方に itsoffset を適用します。映像の再生開始が 0.5秒 遅れる = 相対的に音声が 0.5秒 早まります。


方法 3: -ss で音声だけを前にトリムする

音声が映像より遅れている場合、音声の開始位置をトリムして合わせる方法もあります。

ffmpeg -i input.mp4 \
  -vf "setpts=PTS-STARTPTS" \
  -af "atrim=start=0.3,asetpts=PTS-STARTPTS" \
  -c:v libx264 \
  output.mp4

atrim=start=0.3 で音声を 0.3 秒分前にずらします。


ffprobe で音声遅延を確認する

ffprobe -v quiet -print_format json -show_streams input.mp4 2>&1 | grep "start_time"

映像ストリームと音声ストリームの start_time の差が遅延量の目安になります。


映像と音声の start_time を揃える

一部の動画ファイルは映像と音声の start_time がずれています。以下のコマンドで統一できます:

ffmpeg -i input.mp4 -c:v copy -c:a copy -avoid_negative_ts make_zero output.mp4

-avoid_negative_ts make_zero でタイムスタンプのゼロ点を揃えます。


実用的なワークフロー

ステップ 1: ズレを確認する

動画プレイヤー(VLC など)で映像と音声のズレを秒単位で確認します。

ステップ 2: 方向を判断する

  • 口が先に動いて音が後から来る → 音声が遅れている → adelay で音声を遅らせる必要はなく、-itsoffset で映像を遅らせる
  • 音が先に出て口が後から動く → 音声が早い → adelay で音声を遅らせる

ステップ 3: コマンドを実行する

# 例: 音声が300ms早い場合 (adelayで音声を遅らせる)
ffmpeg -i input.mp4 -af "adelay=300|300" -c:v copy output.mp4

NG例

NG例: adelayにステレオファイルで単一チャンネル値を指定
ffmpeg -i input.mp4 -af "adelay=500" -c:v copy output.mp4

ステレオファイルに adelay=500(単一値)を指定した場合、左チャンネルのみに適用され右チャンネルはズレたままになることがあります。必ずチャンネル数に合わせた値を指定してください。


注意点

  • adelay は音声に遅延を追加するフィルタであり、早める(引き算)ことはできません。
  • 音声を早めたい場合は -itsoffset または atrim を使います。
  • コピー(-c:a copy)は音声を再エンコードしないため、音質が劣化しません。ただし adelay を使う場合は再エンコードが必要です。

関連フィルタ

  • asetpts — 音声タイムスタンプの操作
  • setpts — 映像タイムスタンプの操作
  • atrim — 音声のトリミング

よくある質問

長い動画ほど音ズレが進むのはなぜ?

VFR(可変フレームレート)動画 + ストリームコピーが典型原因。音声は固定クロックで進み、映像フレームは不規則に到着するためズレが累積します。CFR に変換するか再エンコードすれば解消します。

-itsoffset は何をする?

入力ストリームのタイムスタンプを他に対してずらします。-itsoffset 0.5 -i audio.aac で音声を 500ms 遅らせます。負の値で逆方向。

オフセットを自動検出したい

ffmpeg -i video.mp4 -i audio.wav -filter_complex "[0:a][1:a]axcorrelate" -f null - を実行して相関ピークが最大の lag を読みます。

Bluetooth による遅延も直せる?

無理です — Bluetooth レイテンシは再生時に発生する端末固有のもの。書き出し済みファイルでは、ハードウェア lip-sync か後処理 re-mux しか対処策がありません。

トリムするとオフセットが変わる?

はい。-ss を使うとそこを新しい原点として時間が始まります。トリム + オフセットを併用するときは慎重に、できれば再エンコードで keyframe drift を回避してください。

関連リソース

よく使うオプション・フィルタ・コーデック設定をまとめた PDF チートシートです。手元に置いておくと調べる時間を短縮できます。

FFmpeg チートシート