使用 FFmpeg 实现视频淡入淡出的有效方法是什么?

使用 FFmpeg 实现视频淡入淡出的有效方法是什么?

在 FFmpeg 中,对两个视频内容进行淡入淡出其实相当复杂。没有像音频那样的“淡入淡出”过滤器。

有什么有效的方法吗?

答案1

TL;DR 版本:

此示例仅执行视频,假设两个视频剪辑的分辨率、帧速率等相同。这将在 fadeoutclip 和 fadeinclip 之间创建 1 秒的淡入。假设 fadeoutclip 为 10 秒长。请注意,此代码经过格式化以便清晰显示:它实际上只有一行代码。

ffmpeg -i fadeoutclip.mp4 -i fadeinclip.mp4 -an \
-filter_complex "\
    [0:v]trim=start=0:end=9,setpts=PTS-STARTPTS[firstclip]; \
    [1:v]trim=start=1,setpts=PTS-STARTPTS[secondclip]; \
    [0:v]trim=start=9:end=10,setpts=PTS-STARTPTS[fadeoutsrc]; \
    [1:v]trim=start=0:end=1,setpts=PTS-STARTPTS[fadeinsrc]; \
    [fadeinsrc]format=pix_fmts=yuva420p, \
                fade=t=in:st=0:d=1:alpha=1[fadein]; \
    [fadeoutsrc]format=pix_fmts=yuva420p, \
                fade=t=out:st=0:d=1:alpha=1[fadeout]; \
    [fadein]fifo[fadeinfifo]; \
    [fadeout]fifo[fadeoutfifo]; \
    [fadeoutfifo][fadeinfifo]overlay[crossfade]; \
    [firstclip][crossfade][secondclip]concat=n=3[output] \
    " \
-map "[output]" <add in encoding part here>

完整版本:

以下是对这一切的解释:

输入规范...明显

ffmpeg -i fadeoutclip.mp4 -i fadeinclip.mp4 -an

创建一个filter_complex 假设你已经理解了过滤器复合体:

-filter_complex

首先,我们将两个流分成两部分,分别使用调整过滤器内容和淡入淡出部分。淡出分为内容和淡入淡出部分,而淡入分为淡入淡出部分和内容。共四个部分。

请注意,严格来说,我们不分解交叉淡入淡出部分:我们可以只指定两个视频片段的淡出和淡入时间。但是,通过这样做,我们:

这四个部分分别规定:开始时间(秒)、结束时间(秒),以及神秘的setpts=PTS-STARTPTS筛选,这实际上使每个视频子片段从 0 秒开始。这在重新合成时至关重要。

请注意,说明s=0符是多余的,并且1setpts的过滤器s=0也是多余的。但是,两者都是冗余指定的,以允许开始时间从 0 开始更改,而不会破坏过滤器复合体。此外,第二个内容片段运行到结尾,因此e=未指定部分 (end=)。

    [0:v]trim=s=0:e=9,setpts=PTS-STARTPTS[firstclip];
    [1:v]trim=s=1,setpts=PTS-STARTPTS[secondclip];
    [0:v]trim=s=9:e=10,setpts=PTS-STARTPTS[fadeoutsrc];
    [1:v]trim=s=0:e=1,setpts=PTS-STARTPTS[fadeinsrc];

接下来,我们指定淡入淡出:我们首先为两个淡入淡出部分添加一个 alpha(透明)通道,方法是指定像素格式yuva420p。您实际上可以使用任何提供 alpha 通道的格式。

接下来,在这个滤波器子复合体中,我们指定一个淡出,一个淡入。表示alpha=1视频本身不会变暗,只有透明度会“消失”。st表示开始,d表示持续时间。

    [fadeinsrc]format=pix_fmts=yuva420p,      
                fade=t=in:st=0:d=1:alpha=1[fadein];
    [fadeoutsrc]format=pix_fmts=yuva420p,
                fade=t=out:st=0:d=1:alpha=1[fadeout];

这是什么?: 过滤fifo确保过滤器综合体中有可用的缓冲空间。令人惊讶的是,这不是默认的。如果不这样做,当上面阶段的输出超出下面的覆盖过滤器时,交叉淡入淡出可能会失败。是的,我知道你现在在想什么。这确实是 FFMPEG 的一个错误

    [fadein]fifo[fadeinfifo];
    [fadeout]fifo[fadeoutfifo];

现在,叠加两个淡入淡出部分:通过确保两个交叉淡入淡出部分的大小相同,我们不必担心覆盖过滤器采用的相当讨厌的选项(因此我们在这里忽略它们):

    [fadeoutfifo][fadeinfifo]overlay[crossfade];

最后,我们把三个部分排列起来使用 concat 过滤器

    [firstclip][crossfade][secondclip]concat=n=3[output]

现在,将输出板映射为您的视频源。

不要忘记将像素格式设置为您通常使用的格式(通常),因为交叉淡入淡出部分将在输出通道上将yuv420p其设置为!yuv420(由于我们没有指定,您可以使用覆盖参数)当然,如果您愿意yuv420,那就没问题:-)

-map "[output]" <add your normal encoding part here>

然后您可以稍后重新组合音频(超出了本问答的范围)

答案2

FFmpeg 现在有一个xfade(淡入淡出)过滤器

您可以通过复杂的过滤链在两个输入上使用它:

ffmpeg -i input1.mp4 -i input2.mp4 \
  -filter_complex "[0:v][1:v]xfade=transition=fade:duration=1:offset=2.5" \
  output.mp4

在这里,两个视频将被连接在一起,2.5 秒(offset=2.5)后,第一个视频将淡入第二个视频,淡入淡出持续时间为 1 秒(duration=1)。

您可以查看FFmpeg 维基

相关内容