Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Video 使用ffmpeg和xfade过滤器合并多个视频文件_Video_Ffmpeg_Concatenation_Cross Fade - Fatal编程技术网

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

Video 使用ffmpeg和xfade过滤器合并多个视频文件,video,ffmpeg,concatenation,cross-fade,Video,Ffmpeg,Concatenation,Cross Fade,我需要将多个视频文件(包括音频)合并到一个视频中。我注意到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:duratio

我需要将多个视频文件(包括音频)合并到一个视频中。我注意到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

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

您的偏移不正确。尝试:

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[A01]; \
 [A01][2:a]acrossfade=d=0.5[A02]; \
 [A02][3:a]acrossfade=d=0.5[A03]; \
 [A03][4:a]acrossfade=d=0.5[audio]" \
-map "[video]" -map "[audio]" -movflags +faststart out.mp4
如何获取xfade
offset
值:

输入 输入持续时间 + 上一个xfade
偏移量
- xfade
持续时间
=
v0.mp4
4 + 0 - 0.5 3.5
v1.mp4
9.19 + 3.5 - 0.5 12.1
v2.mp4
3.41 + 12.1 - 0.5 15.1
v3.mp4
7.99 + 15.1 - 0.5 22.59
自动化过程将有助于处理偏移计算中的错误。我创建了一个Python脚本,用于进行计算,并为任意大小的输入视频列表构建一个图形:

它将检查视频文件的长度(使用
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, i + 1, next_audio_output, ";" if (i+1) < len(segments)-1 else "")
    last_audio_output = next_audio_output

上面的Python脚本确实帮助了我很多,但它在偏移量计算中有一个错误。视频流应为“视频长度-衰减持续时间*(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, i + 1, 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, i + 1, 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
def gen_过滤器(段):
视频衰减=“”
音频衰减=“”
settb=“”
最后一次衰减输出=“0:v”
上次音频输出=“0:a”
衰减持续时间=0.3
视频长度=0
文件长度=[0]*len(段)
对于范围内的i(len(段)):
settb+=“[%d]settb=AVTB[%d:v];”%(i,i)
对于范围内的i(长度(段)-1):
文件长度[i]=float(ffmpeg.probe(段[i])['format']['duration']))
视频长度+=文件长度[i]
下一步衰减输出=“v%d%d”%(i,i+1)
视频淡入淡出+=“[%s][%d:v]xfade=transition=fade:duration=%f:offset=%f%s%s”\
(上一次淡入淡出输出,i+1,淡入淡出持续时间,视频长度-淡入淡出持续时间*(i+1),“[”+下一次淡入淡出输出+”;“如果(i)
@llogan这是一个巨大的问题,你是对的,今天通过一些测试也发现了这一点。我还找到了一种方法,通过在这些操作之前修剪/填充音频来获得更好的同步。这是一个问题,因为大多数文件的音频和视频持续时间不相等。这就是我现在正在做的(这是另一组视频+你的其他建议):使用这个方法,我得到“超过1000帧重复”,并且在输出的中间,视频和音频之间是不同步的。有什么想法吗?
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, i + 1, 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, i + 1, 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