FFmpeg concat视频和音频不同步

时间:2016-02-15 18:05:22

标签: audio video ffmpeg concatenation

使用ffmpeg concat加入多个文件似乎会导致音频的时间戳或偏移不匹配。我尝试了几个视频,并注意到h.264 / MP4的相同问题。

使用concat 和编码视频似乎运行正常。音频保持同步,因为ffmpeg执行完整的转换计算,并且似乎可以使一切正常。

但是,简单地连接视频而不进行任何转换或编码会导致同步问题缓慢增加。显然,对视频进行编码而不是简单地加入它们会导致信息/质量的损失,所以我宁愿找到解决这个问题的方法。

tried several flags要解决这个似乎基于时间戳的问题。但这些似乎都没有解决问题。

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不是问题所在。原始剪辑集的时间戳不匹配。以某种方式c​​oncat +编码修复了这个问题,但我不想每次重新编码视频和松散的质量。

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以及-t的不同地方使用-af apad -c:v copy m和Error in as.data.frame.default(x[[i]], optional = TRUE) : cannot coerce class "structure("mpfr1", package = "Rmpfr")" to a data.frame ,但我仍未能将持续时间保持不变。

Here is the full ffprobe output

Here is the original (red) vs the segment (green)

详细示例文件

我录制了一个示例视频,添加了将其删除的命令,然后将其连接起来。 http://davidpennington.me/share/audio_sync_test_video.zip

5 个答案:

答案 0 :(得分:12)

这个两步过程应该有效

第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步 Concat

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

其中segments.txt由填充文件的名称组成。

答案 1 :(得分:4)

我也一直在努力解决这个问题。特别是在使用Panasonic AVCHD生成的MTS文件时。我目前的解决方案是在操作系统级别连接它们而不是ffmpeg。我在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

您可以查找windowslinux二进制连接的文档。

如果原始格式适合您,那么这种连接方法就像转码一样。该方法实际上不使用CPU处理并保留原始质量。处理高质量的大宗媒体时双赢。

答案 2 :(得分:2)

您可以使用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

答案 3 :(得分:1)

我遇到了类似的问题,并且找到了一个可行的解决方案,至少对我而言。就我而言,我还连接了文件,发现iO出现了音频/视频同步问题,但Windows却没有(例如,VLC媒体播放器使用相同的mp4文件显示没有同步问题)。 iO播放此级联mp4的症状最初是良好的同步,随后随着电影播放而失去同步,音频的传输速度快于视频。有趣的是,可以通过将电影进度滑块前进到电影中的任何点来临时恢复同步,但是随着电影继续在iO中播放,同步将再次丢失。通过在iO和Windows VLC中同时播放同一部电影,并尽可能地彼此同步,通过观察它们之间“回声”的演变,我得出结论,iO的音频速度太快了(假设Windows Player是正确的)。

对我来说,解决方案是将音频过滤器选项-af aresample=async=1000添加到ffmpeg命令,我在ffmpeg在线文档中找到了该示例,并逐字使用。我不知道此设置是否最佳,但结果是mp4,iO和VLC播放时音频和视频保持同步。 ffmpeg选项在串联期间和之后重新编码已经串联的文件时都能产生正确的iO同步。

答案 4 :(得分:0)

如果输入的视频使用相同的设置进行编码,您可以使用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/^/+/')