web-dev-qa-db-ja.com

FFmpeg concatビデオとオーディオが同期していない

Ffmpeg concat を使用して複数のファイルを結合すると、オーディオのタイムスタンプまたはオフセットが一致しなくなるようです。私はいくつかのビデオを試しましたが、h.264/MP4でも同じ問題に気付きました。

concatとencodingを使用すると、ビデオは正常に動作するようです。 ffmpegが完全な変換計算を行い、すべてが正しく行われるように聞こえるので、オーディオは同期したままです。

ただし、変換やエンコードを行わずにビデオを単純に連結すると、同期の問題が徐々に増加します。明らかに、ビデオを単に結合するのではなくエンコードすると、情報/品質が失われるため、この問題を回避する方法を見つけたいと思います。

いくつかのフラグを試しました タイムスタンプに基づいているように見えるこの問題を整理しました。ただし、これらのいずれも問題を修正していないようです。

ffmpeg -f concat -fflags +genpts -async 1 -i segments.txt test.mov
ffmpeg -auto_convert 1 -f concat -fflags +genpts -async 1 -i segments.txt -c copy test2.mov
ffmpeg -f concat -i segments.txt -c copy -fflags +genpts test3.mp4
ffmpeg -f concat -fflags +genpts -async 1 -i segments.txt -copyts test4.mov
ffmpeg -f concat -i segments.txt -copyts test5.mov
ffmpeg -f concat -i segments.txt -copyts -c copy test6.mov
ffmpeg -f concat -fflags +genpts -i segments.txt -copyts -c copy test7.mov

注:SOで見つけることができる他のすべての質問は、単にビデオをエンコードし直すことで問題を「修正」するようです。良い解決策ではありません。

更新

連結が問題ではないことに気付きました。クリップの元のセットのタイムスタンプが一致していませんでした。どういうわけかconcat + encodingで問題は修正されましたが、毎回ビデオを再エンコードしたり、品質を落とすことはしたくありません。

ffmpeg -y -ss 00:00:02.750 -i input.MOV -c copy -t 00:00:05.880 output.MOV

その結果、次のデータが得られました

ffprobe -v quiet -show_entries stream=start_time,duration output.MOV

start_time=-0.247500
duration=6.131125
start_time=-0.257333
duration=6.155333

それ以来、-toと一緒に-tmと-af apad -c:v copyを異なる場所で使用しようとしましたが、継続時間を同じにすることができませんでした。

これは完全なffprobe出力です

ここに元の(赤)対セグメント(緑)

詳細なサンプルファイル

サンプルビデオを録画し、それを切り取るコマンドを追加して、連結します。 http://davidpennington.me/share/audio_sync_test_video.Zip

21
Xeoncross

この2段階のプロセスは機能するはずです

ステップ1各セグメントの音声を埋める

ffmpeg -i segment1.mov -af apad -c:v copy <audio encoding params> -shortest -avoid_negative_ts make_zero -fflags +genpts padded1.mov

または

同期されたストリームでセグメントを生成する

ffmpeg -y -ss 00:00:02.750 -i input.MOV -c copy -t 00:00:05.880 -avoid_negative_ts make_zero -fflags +genpts segment.MOV

ステップ2連結

ffmpeg -f concat -i segments.txt -c copy test.mov

どこ segments.txtは、パディングされたファイルの名前で構成されます。

14
Gyan

私もこれとかなり長い間苦労してきました。特に、パナソニックAVCHDで生成されたMTSファイルを使用する場合。私の現在の解決策は、ffmpegではなくOSレベルでそれらを連結することです。私はWindows上でこれを行い、それは次のようになります:

COPY /b input_1.mts + input_2.mts + input_3.mts output.mts

Linuxでは、次のようになります。

$ cat input_1.mts input_2.mts input_3.mts > output.mts

windows および linux バイナリ連結のドキュメントを検索できます。

トランスコーディングと同じように連結するこの方法は、元の形式が機能する場合の方法です。この方法は、実際にはCPU処理を使用せず、元の品質を維持します。高品質のバルクメディアを扱う場合のwin-win。

4
salmore

filter_complexを使用して、さまざまなオプションを一度に連結できます

fmpeg -i input1.mp4 -i input2.webm \
-filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] concat=n=2:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" <encoding options> output.mkv
2
flower

私は同様の問題に遭遇し、少なくとも私にとっては有効な解決策を見つけました。私の場合、ファイルを連結していましたが、iOでオーディオ/ビデオの同期の問題が見つかりましたが、Windowsではそうではありませんでした(たとえば、VLCメディアプレーヤーは同じmp4ファイルを使用しても同期の問題はありませんでした)。この連結されたmp4を再生するiOの症状は、最初は良好な同期であり、その後、ムービーよりも同期が失われ、オーディオがビデオより速くなります。興味深いことに、映画の進行状況スライダーを映画の任意のポイントに進めることで一時的に同期を復元できますが、その後、映画がiOで再生し続けると再び同期が失われます。 iOとWindows VLCの両方で同じムービーを同時に再生し、最初に相互に同期し、それらの間の「エコー」の進化を観察することで、iOのオーディオが速すぎると仮定しました( Windowsプレーヤーが正しい)。

私にとっての解決策は、オーディオフィルターオプションを追加することでした-af aresample=async=1000 ffmpegコマンドに追加しました。これは、ffmpegオンラインドキュメントで例として見つけ、そのまま使用しました。この設定が最適かどうかはわかりませんが、iOとVLCの両方で再生すると、オーディオとビデオが同期したままのmp4になりました。このffmpegオプションにより、連結中とその後のすでに連結されたファイルの再エンコード時の両方で適切なiO同期が得られました。

1
Paul

入力ビデオが同じ設定でエンコードされている場合、代わりにmkvtoolnixのmkvmergeを使用できる場合があります。

_mkvmerge -o output.mkv file1.mkv + file2.mkv + file3.mkv
_

さまざまな設定でエンコードされたさまざまなソースのビデオを連結する必要があったため、次のようなコマンドを使用して、最初に入力ビデオのサイズを変更し、再エンコードしました。

for f in *.mp4;do width=1280;height=720;ffmpeg -i $f -filter:v "scale=iw*min($width/iw\,$height/ih):ih*min($width/iw\,$height/ih), pad=$width:$height:($width-iw*min($width/iw\,$height/ih))/2:($height-ih*min($width/iw\,$height/ih))/2" -c:v libx264 -crf 22 -preset slow -pix_fmt yuv420p -c:a libfdk_aac -vbr 3 -ac 2 -ar 44100 ${f%mp4}mkv;done

一部のビデオにはオーディオチャンネルがありませんでしたので、次のようなコマンドを使用してサイレントオーディオチャンネルを追加する必要がありました。

_for f in *.mkv;do ffprobe $f|&grep -q '1: Audio'||{ ffmpeg -i $f -f lavfi -i anullsrc -c:a libfdk_aac -shortest -c:v copy temp-$f;mv temp-$f $f; };done_

次に、次のようなコマンドを使用してビデオを連結しました。

_mkvmerge -o output.mkv $(printf %s\\n *.mkv|sed '1!s/^/+/')
_
0
nisetama