音ズレを直す (原理説明)
まず原理を説明します.
音ズレがある元ファイルの名前を original.mp4 とします.
手順1) 音声と映像の分離
まずoriginal.mp4 から映像データを抜き出します.
$ ffmpeg -i original.mp4 -vc -an v.mp4
これで映像だけが v.mp4 として保存されます.
この際のログをよく見ると,映像の再生時間がわかります.
frame=233871 fps=0.0 q=-1.0 Lsize= 4416826kB time=01:05:00.57 bitrate= 4875 kb/s
例えば,上記の表示なら,映像 v.mp4 の長さは 01:05:00.57 となります.
次に original.mp4 から音声データを抜き出します.
$ ffmpeg -i original.mp4 -vn -ac a.mp4
これで音声だけが a.mp4 として保存されます.
こちらも再生時間を調べます.
size= 731596kB time=01:05:01.84 bitrate=1336.0kbits/s speed= 1745x
音声の長さは 01:05:01.84 となります.
元の動画ファイル original.mp4 の長さも調べましょう
$ ffprob -i original.mp4
Duration: 01:05:01.85, start: 0.000000, bitrate: 2020 kb/s
01:05:01.85です
時間から秒への換算してみます.換算は "qalc" コマンドがオススメです
$ qalc
> 01:05:01.85 h to s
(3901.85 / 3600) * hour = 3901.85 s
表でまとめてみます
|
再生時間 |
再生時間(秒) |
元動画 original.mp4 |
01:05:01.85 |
3901.85 |
映像データ |
01:05:00.57 |
3900.57 |
音声データ |
01:05:01.84 |
3901.84 |
このように動画に含まれている,映像データと音声データとで再生時間が違うと,音ズレが発生します.
音ズレを修正するには,映像と音声どちらかの再生速度を変えて,再生時間を揃えればOKです.
再生速度の変換は音声処理の方が早いので,今回は映像はそのままで,音声の再生速度を変えることにします
映像に合わせて,音声の再生速度を x 倍に変換すると考えると
x = (音声の再生時間)/(映像の再生時間)
となります
$ qalc
> 3901.84/3900.57
3901.84 / 3900.57 = approx. 1.0003256
計算すると x=1.0003256 です
この値で,音声の再生速度を変換します.
$ ffmpeg -i a.mp4 -filter:a "atempo=1.0003256" a_fixed.mp4
確認します
$ ffprobe -i a_fixed.mp4
Duration: 01:05:00.58, bitrate: 1536 kb/s
1/100秒ほどズレが残っていますが,まあ誤差の範囲としましょう.
変換した音声データと,元の映像データを結合します
$ ffmpeg -i v.mp4 -i a_fixed.mp4 -vc -ac output.mp4
音ズレを直す (運用版)
まず映像,音声の長さを調べます
$ ffprob -i original.mp4
音声の再生速度 x を求めます
変換します
$ ffmpeg -i original.mp4 -filter_complex "[0:a]atempo=1.0003256[a]" -map "[0:v]" -map "[a]" output.mp4
オプションの -filter_complex "[0:a]atempo=1.0003256[a]" で音声の再生速度を変換しています
"[0:a]" は -i オプションで最初に指定した入力 original.mp4 の 音声(a),という意味です.
それを 1.0003256倍の速度で再生,その結果に "[a]"という名前をつけています
オプション -map "[0:v]" は,入力 original.mp4 の 映像(v)を,出力 output.mp4 に割り当てるという意味です.
オプション -map "[a]" は,変換後の音声データ "[a]"を,出力 output.mp4 に割り当てるという意味です.
これで中間ファイルを作成することなく音ズレが修正できます.