使用 ffmpeg 在 2 个视频之间淡入淡出

Mug*_*gba 41 video ffmpeg command-line video-editing

我一直在尝试使用 ffmpeg 在 2 个视频剪辑之间实现淡入淡出过渡,但到目前为止都失败了。我是 ffmpeg 的新手,主要依赖于调整我可以在文档和在线现有示例中找到的内容。从我到目前为止所读到的内容来看,使用混合叠加过滤器应该有助于实现我所追求的目标,但我无法弄清楚命令行细节以使其正常工作。

褪色和CONCAT过滤器是伟大的淡出视频1,淡入到视频2和CONCAT 2到1个夹子型的转变,但我会在得到一个命令,从过渡视频1视频2没有任何感激的帮助中间会变黑。我在任何地方都找不到针对此问题的任何示例,也许我正在寻找错误的关键字......?

更具体地说,我的视频是 mp4(h264 视频,没有声音,以防万一),每个视频长 5 秒,我从大约 . 视频 1 的 4.5 秒到视频 2 的 0.5 秒。

与本教程使用 MLT 和帧所做的类似(有关淡入淡出示例,请参阅 2:25),但我正在寻找一种方法,仅在 ffmpeg 中执行此操作,而无需调用任何其他程序。 http://www.youtube.com/watch?v=3PRZ9L_KLdI

非常感谢任何指针或命令行来获得这样的淡入淡出,非常感谢!

ptQ*_*tQa 35

我建议这样做:

  • 创建与输出视频具有相同持续时间和分辨率的黑色背景
  • 为每个视频添加 Alpha 通道
  • 为每个视频添加淡入淡出阿尔法效果
  • 在黑色背景的每个视频上使用叠加层

因此,将交叉淡入淡出添加到 2 个视频(5 秒)的命令应该是:

ffmpeg -i 1.mp4 -i 2.mp4 -f lavfi -i color=black -filter_complex \
"[0:v]format=pix_fmts=yuva420p,fade=t=out:st=4:d=1:alpha=1,setpts=PTS-STARTPTS[va0];\
[1:v]format=pix_fmts=yuva420p,fade=t=in:st=0:d=1:alpha=1,setpts=PTS-STARTPTS+4/TB[va1];\
[2:v]scale=960x720,trim=duration=9[over];\
[over][va0]overlay[over1];\
[over1][va1]overlay=format=yuv420[outv]" \
-vcodec libx264 -map [outv] out.mp4
Run Code Online (Sandbox Code Playgroud)

这将在第 4 秒 (st=4) 将第一个视频淡出到 alpha,持续时间为 1 秒 (d=1),在第 0 秒 (st=0) 淡入第二个视频,持续时间为 1 秒( d=1),并将其显示时间向前移动到 4 秒 (+4/TB)。然后我们只剪掉 9 秒的黑色,缩放它以输出视频大小并覆盖这些东西。

希望能帮助到你。


Ora*_*Dog 11

FFmpeg 现在有一个交叉淡入淡出过滤器,在 4.3 版中发布。

ffmpeg -i 1.mp4 -i 2.mp4 -filter_complex "xfade=offset=4.5:duration=1" output.mp4
Run Code Online (Sandbox Code Playgroud)

同样,还有一个音频版本

ffmpeg -i 1.mp4 -i 2.mp4 -filter_complex "xfade=offset=4.5:duration=1;acrossfade=duration=1" output.mp4
Run Code Online (Sandbox Code Playgroud)


fis*_*ch2 9

ffmpeg-concat是完成你想要的最简单的方法,它允许你使用一堆性感的 OpenGL 过渡,默认是交叉淡入淡出。

ffmpeg-gl-transition是一个自定义的 ffmpeg 过滤器,它允许您使用 GLSL 在两个视频流之间平滑过渡。此过滤器比此处列出的替代方案更易于使用和定制。

该过滤器支持大名单的过渡类型,缺省设置为交叉淡入淡出。

./ffmpeg -i 0.mp4 -i 1.mp4 -filter_complex "gltransition=duration=4:offset=1.5" out.mp4
Run Code Online (Sandbox Code Playgroud)

  • 您是否考虑过向 FFmpeg 提交补丁? (7认同)
  • 这是在官方的 FFmpeg 中吗?我好像找不到 (3认同)
  • 我肯定会,我只需要解决一些小问题并先进行更多测试。好决定! (2认同)

小智 6

这就是我所做的:

  • ffmpeg 版本 N-77197-gdf2ce13
  • 2 个视频,每个 4 秒。
  • 需要在它们之间加入淡入淡出。
  • 视频为 25 fps。

1)在第一个结尾添加淡出(从浅到深),在第二个开头添加淡入(从深到浅):

ffmpeg -i 1.mp4 -y -vf fade=out:76:24 1f.mp4

ffmpeg -i 2.mp4 -y -vf fade=in:0:25 2f.mp4
Run Code Online (Sandbox Code Playgroud)

76:24 表示淡出将从第 76 帧开始,并在 24 帧后结束 = 1 秒淡出。

0:25 表示淡入将从第 0 帧开始,并在 25 帧后结束。

2) 合并 2 个视频

全部转换为 TS

ffmpeg -i 1f.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts 1f.ts

ffmpeg -i 2f.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts 2f.ts
Run Code Online (Sandbox Code Playgroud)

合并

ffmpeg -i "concat:1f.ts|2f.ts" -bsf:a aac_adtstoasc -c copy output.mp4
Run Code Online (Sandbox Code Playgroud)

谢谢:

http://www.bogotobogo.com/FFMpeg/ffmpeg_fade_in_fade_out_transitions_effects_filters.php

  • 这不是交叉淡入淡出。 (7认同)
  • @Mulvya 所说的话。交叉渐变会在另一个剪辑淡入的同时使一个剪辑淡出。第一个剪辑的透明度在交叉渐变期间稳步增加;二是透明度稳步下降。 (4认同)

Has*_*ziz 5

OrangeDog 是正确的,原生交叉渐变最近通过过滤器引入了 FFmpeg(版本 4.3.2,于 2020 年 6 月 8 日发布)xfade。然而,他的答案是不完整的,没有解释过滤器的工作原理或考虑到它有多复杂。


使用xfade过滤器

offset参数是您希望转换开始的第一个输入点(以秒为单位),该duration参数是您希望转换在完成转换到第二个输入之前需要多长时间(以秒为单位)。

交叉淡入淡出最常见的用途是从第一个输入的末尾淡入第二个输入的开头。xfade然而,这比乍看起来更棘手:如果offset参数设置得太低,它会过早消失并占用第一个输入末尾的一部分。

如果偏移量设置得太高(超过VIDEO 1 DURATION + FADE DURATION),则交叉淡入淡出将根本无法应用,因为xfade过滤器认为这是无效的 - 我猜测是因为它在计算中完全忽略了第二个输入。

这意味着过滤器可以做的最好的事情xfade就是从第一个输入的末尾截断尽可能少的内容,这通常意味着最后“仅”丢失一两秒的视频。这可能适合您的需求,在这种情况下,xfade过滤器将非常适合您。

如果不是,则跳到最后使用旧的交叉淡入淡出解决方案,尽管设置稍微复杂一些,但它确实在计算中包含了第二个输入,从而产生完全保留了视频流的交叉淡入淡出。两个输入。

首先,获取第一次输入的持续时间(以秒为单位):

ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input1.mp4
Run Code Online (Sandbox Code Playgroud)

然后通过执行 获得上限值VIDEO1 DURATION - FADE DURATION

此上限是offset您可以设置的最高值 - 任何更高的值,xfade滤镜将无法应用交叉淡入淡出。我建议从它作为初始值开始,然后逐渐降低它,直到您对最终结果感到满意。

例如,如果您的第一个输入的持续时间是170.500秒,并且您希望交叉淡入淡出持续2几秒,则上限值将为168.500

ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex \
"[0:v][1:v]xfade=duration=2:offset=168.500[outv];
 [0:a][1:a]acrossfade=duration=2[outa]" -map [outv] -map [outa] Output.mp4
Run Code Online (Sandbox Code Playgroud)

如果该命令的结果是交叉淡入淡出,其中第一个输入流在交叉淡入淡出过渡之前突然结束,则每次逐渐降低偏移值一秒,直到过渡看起来尽可能平滑。

运行这些实验运行时,您可以添加-preset ultrafast选项来加快编码时间 - 只需记住在没有它的情况下运行最终编码即可最大程度地压缩最终输出文件。

使用该transition参数,xfade还允许您使用除默认淡入淡出之外的交叉淡入淡出过渡。此示例使用像素化过渡:

ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex \
"[v0][v1]xfade=transition=pixelise:duration=2:offset=168.721[outv];
 [0:a][1:a]acrossfade=duration=2[outa]" -map [outv] -map [outa] Output.mp4
Run Code Online (Sandbox Code Playgroud)

可用转换的完整列表可以在FFmpeg wiki上找到。


如果您的信号源没有相同的时基和帧速率

请注意,上述任何命令都可能失败并出现以下错误之一:

第一个输入链接主时基 (1/1500) 与相应的第二个输入链接 xfade 时基 (1/30000) 不匹配

第一个输入链接主帧率 (30/1) 与对应的第二个输入链接 xfade 帧率 (30000/1001) 不匹配

这些错误意味着您的输入分别具有不同的时基和帧速率,这在处理来自不同来源的输入时很可能发生。在这些情况下,您将需要以下命令。

由于所有内容都在重新编码,所以仍然让我感到困惑,过滤xfade器要求每个输入的 TBN 和帧速率相同,类似于解concat复用器要求 TBN、分辨率、编解码器和其他属性相同的方式。相同的。

如果您遇到这种情况并且遇到上述错误之一,则需要为每个视频流设置通用的 TBN 和帧速率,然后再将过滤器应用于xfade它们:

ffmpeg -i upscaled.mp4 -i outro.mp4 -filter_complex \
"[0:v]settb=AVTB,fps=30/1[v0];
 [1:v]settb=AVTB,fps=30/1[v1];
 [v0][v1]xfade=transition=fade:duration=2:offset=168.721[outv];
 [0:a][1:a]acrossfade=duration=3[outa]" -map [outv] -map [outa] Output.mp4
Run Code Online (Sandbox Code Playgroud)

据我所知,没有与AVTB帧速率常数等效的值,因此请将30/1上面的内容替换为适合您的输出帧速率。30/1(这是 30 FPS 的 FFmpeg 表示法)可能是一个安全的选择,但我不是帧速率及其影响方面的专家。


使用“传统”交叉淡入淡出

如果像我一样,您对过滤器的结果不完全满意xfade,则可以按照旧方法进行交叉淡入淡出。

这是Gyan的答案的修改版本,本质上与ptQa的答案类似,只是它不太复杂并且不包含任何与实际交叉淡入淡出无关的过滤器。它本质上可以被认为是过滤器的简单性和ptQa解决方案xfade的复杂性之间的中间立场。

ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex \
"color=black:WXH:d=VIDEO1+VIDEO2-FADE[base]; \
[0:v]setpts=PTS-STARTPTS[v0]; \
[1:v]format=yuva420p,fade=in:st=0:d=FADEDURATION:alpha=1,
    setpts=PTS-STARTPTS+((VIDEO1LENGTH-FADEDURATION)/TB)[v1]; \
[base][v0]overlay[tmp]; \
[tmp][v1]overlay,format=yuv420p[fv]; \
[0:a][1:a]acrossfade=d=AUDIOFADEDURATION[fa]" \
-map [fv] -map [fa] \
output.mp4
Run Code Online (Sandbox Code Playgroud)

替换WXH为您的视频分辨率。

替换VIDEO1+VIDEO2-FADE为总和的结果- 将第一个输入的长度(以秒为单位)添加到第二个输入的长度(以秒为单位)减去淡入淡出持续时间得到的结果。用于ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4获取每个输入的持续时间。

最后,将VIDEO1LENGTH和 的每个实例替换VIDEO2LENGTH为它们的,并将FADEDURATIONAUDIOFADEDURATION替换为您希望的值。

因此,如果我想在两个 1920x1080 的视频之间进行交叉淡入淡出,第一个输入的长度为 170.300 秒,第二个输入的长度为 9 秒,并且我希望它们之间的交叉淡入淡出时间为 2 秒,音频交叉淡入淡出时间为 4 秒,我的命令如下所示:

ffmpeg -i input1.mp4 -i input2.mp4 \
-filter_complex \
"color=black:1920x1080:d=177.300[base]; \
[0:v]setpts=PTS-STARTPTS[v0]; \
[1:v]format=yuva420p,fade=in:st=0:d=2:alpha=1,setpts=PTS-STARTPTS+((170.300-2)/TB)[v1]; \
[base][v0]overlay[tmp]; \
[tmp][v1]overlay,format=yuv420p[fv]; \
[0:a][1:a]acrossfade=d=4[fa]" \
-map [fv] -map [fa] Output.mp4
Run Code Online (Sandbox Code Playgroud)