使用ffmpeg和xfade过滤器合并多个视频文件

我需要将多个视频文件(包含音频)合并到一个视频中。我注意到xfade最近已经发布并使用过,但是我遇到了音频同步问题。

所有视频的音频/视频格式/分辨率/成名率和比特率均相同。

这是我用来合并5个具有0.5淡入淡出过渡的不同时长的视频的方法:

ffmpeg \
-i v0.mp4 \
-i v1.mp4 \
-i v2.mp4 \
-i v3.mp4 \
-i v4.mp4 \
-filter_complex \
"[0][1]xfade=transition=fade:duration=0.5:offset=3.5[V01]; \
 [V01][2]xfade=transition=fade:duration=0.5:offset=32.75[V02]; \
 [V02][3]xfade=transition=fade:duration=0.5:offset=67.75[V03]; \
 [V03][4]xfade=transition=fade:duration=0.5:offset=98.75[video]; \
 [0:a][1:a]acrossfade=d=0.5:c1=tri:c2=tri[A01]; \
 [A01][2:a]acrossfade=d=0.5:c1=tri:c2=tri[A02]; \
 [A02][3:a]acrossfade=d=0.5:c1=tri:c2=tri[A03]; \
 [A03][4:a]acrossfade=d=0.5:c1=tri:c2=tri[audio]" \
-vsync 0 -map "[video]" -map "[audio]" out.mp4

上面的代码生成带音频的视频。第一部分和第二部分与音频对齐,但是从第二个过渡开始,声音未对齐。

iCMS 回答:使用ffmpeg和xfade过滤器合并多个视频文件

自动化该过程将有助于处理计算偏移量时出现的错误。我创建了一个 Python 脚本来进行计算并为任何大小的输入视频列表构建一个图表:

https://gist.github.com/royshil/369e175960718b5a03e40f279b131788

它将检查视频文件的长度(使用 ffprobe)以找出正确的偏移量。

问题的关键是构建过滤器图并计算偏移量:

# Prepare the filter graph
video_fades = ""
audio_fades = ""
last_fade_output = "0:v"
last_audio_output = "0:a"
video_length = 0
for i in range(len(segments) - 1):
    # Video graph: chain the xfade operator together
    video_length += file_lengths[i]
    next_fade_output = "v%d%d" % (i,i + 1)
    video_fades += "[%s][%d:v]xfade=duration=0.5:offset=%.3f[%s]; " % \
        (last_fade_output,i + 1,video_length - 1,next_fade_output)
    last_fade_output = next_fade_output

    # Audio graph:
    next_audio_output = "a%d%d" % (i,i + 1)
    audio_fades += "[%s][%d:a]acrossfade=d=1[%s]%s " % \
        (last_audio_output,next_audio_output,";" if (i+1) < len(segments)-1 else "")
    last_audio_output = next_audio_output

它可能会产生一个过滤器图,例如

[0:v][1:v]xfade=duration=0.5:offset=42.511[v01]; 
[v01][2:v]xfade=duration=0.5:offset=908.517[v12]; 
[v12][3:v]xfade=duration=0.5:offset=1098.523[v23]; 
[v23][4:v]xfade=duration=0.5:offset=1234.523[v34]; 
[v34][5:v]xfade=duration=0.5:offset=2375.523[v45]; 
[v45][6:v]xfade=duration=0.5:offset=2472.526[v56]; 
[v56][7:v]xfade=duration=0.5:offset=2659.693[v67]; 
[0:a][1:a]acrossfade=d=1[a01]; 
[a01][2:a]acrossfade=d=1[a12]; 
[a12][3:a]acrossfade=d=1[a23]; 
[a23][4:a]acrossfade=d=1[a34]; 
[a34][5:a]acrossfade=d=1[a45]; 
[a45][6:a]acrossfade=d=1[a56]; 
[a56][7:a]acrossfade=d=1[a67]
,

您的偏移量不正确。试试:

ffmpeg -i v0.mp4 -i v1.mp4 -i v2.mp4 -i v3.mp4 -i v4.mp4 -filter_complex \
"[0][1]xfade=transition=fade:duration=0.5:offset=3.5[V01]; \
 [V01][2]xfade=transition=fade:duration=0.5:offset=12.1[V02]; \
 [V02][3]xfade=transition=fade:duration=0.5:offset=15.1[V03]; \
 [V03][4]xfade=transition=fade:duration=0.5:offset=22.59,format=yuv420p[video]; \
 [0:a][1:a]acrossfade=d=0.5:c1=tri:c2=tri[A01]; \
 [A01][2:a]acrossfade=d=0.5:c1=tri:c2=tri[A02]; \
 [A02][3:a]acrossfade=d=0.5:c1=tri:c2=tri[A03]; \
 [A03][4:a]acrossfade=d=0.5:c1=tri:c2=tri[audio]" \
-map "[video]" -map "[audio]" -movflags +faststart out.mp4

如何获取偏移量:

  • 4.0-0.5 = 3.5
  • 9.10 + 3.5-0.5 = 12.1
  • 3.41 + 21.1-0.5 = 15.1
  • 7.99 + 15.1-0.5 = 22.59

4.0、9.10、3.41、7.99是输入的持续时间(最近的输入持续时间无关紧要)。

,

上面的 Python 脚本确实对我有很大帮助,但它在偏移量计算中存在错误。视频流应该是“video_length -fade_duration*(i+1)”。

如下代码:

def gen_filter(segments):
    video_fades = ""
    audio_fades = ""
    settb = ""
    last_fade_output = "0:v"
    last_audio_output = "0:a"
    fade_duration = 0.3

    video_length = 0
    file_lengths = [0]*len(segments)
    
    for i in range(len(segments)):
        settb += "[%d]settb=AVTB[%d:v];" % (i,i)

    for i in range(len(segments)-1):

        file_lengths[i] = float(ffmpeg.probe(segments[i])['format']['duration'])

        video_length += file_lengths[i]
        next_fade_output = "v%d%d" % (i,i + 1)
        video_fades += "[%s][%d:v]xfade=transition=fade:duration=%f:offset=%f%s%s" % \
            (last_fade_output,fade_duration,video_length - fade_duration*(i+1),'['+next_fade_output+'];' if (i) < len(segments)-2 else "","" if (i) < len(segments)-2 else ",format=yuv420p[video];")
        last_fade_output = next_fade_output

        next_audio_output = "a%d%d" % (i,i + 1)
        audio_fades += "[%s][%d:a]acrossfade=d=%f%s" % \
            (last_audio_output,fade_duration*2,'['+next_audio_output+'];' if (i) < len(segments)-2 else "[audio]")
        last_audio_output = next_audio_output
        
    return settb + video_fades + audio_fades
本文链接:https://www.f2er.com/1693709.html

大家都在问