在 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
首先,我们将两个流分成两部分,分别使用调整过滤器:内容和淡入淡出部分。淡出分为内容和淡入淡出部分,而淡入分为淡入淡出部分和内容。共四个部分。
请注意,严格来说,我们不有分解交叉淡入淡出部分:我们可以只指定两个视频片段的淡出和淡入时间。但是,通过这样做,我们:
- 遵循 GUI 视频编辑器通常使用的方法
overlay
避免过滤器使用过程中令人烦恼的复杂性- 确保解决方案尽可能通用(即可重用代码)
- 允许我们根据需要对交叉淡入淡出部分进行预处理和后处理(这里不做)
这四个部分分别规定:开始时间(秒)、结束时间(秒),以及神秘的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 维基。