如何淡入/淡出持续时间未知的视频/音频片段?


19

我正在使用ffmpeg批量转换一些视频文件,并在每个剪辑的头部和尾部添加淡入/淡出效果的项目。

我一直在使用以下代码在持续时间已知的剪辑上添加淡入淡出效果:

ffmpeg -i clip.mp4 -filter:v 'fade=in:0:30,fade=out:9650:30' -c:v libx264 -crf 22 -preset veryfast -c:a copy fadeInOut.mp4

我的两个问题是:

  1. 如何同时淡入/淡出音频?
  2. ffmpeg可以自动找出剪辑的持续时间,并告诉他们淡出最后30帧吗?

谢谢!

Answers:


15

#1要同时淡入/淡出音频,请执行以下操作:

ffmpeg -i clip.mp4 -vf 'fade=in:0:30,fade=out:960:30'
                   -af 'afade=in:st=0:d=1,afade=out:st=32:d=1'
       -c:v libx264 -crf 22 -preset veryfast fadeInOut.mp4

出现时间以秒为单位

#2自动吗?否。但是请参阅下面的解决方法

您可以先运行ffprobe以获得持续时间。

ffprobe -i clip.mp4 -show_entries stream=codec_type,duration -of compact=p=0:nk=1

您将获得如下内容:

video|13.556000
audio|13.816000

然后,您可以使用上面的颜色放置渐变。这些时间以秒为单位。

解决方法

ffmpeg -i clip.mp4 -sseof -1 -copyts -i clip.mp4 -filter_complex
       "[1]fade=out:0:30[t];[0][t]overlay,fade=in:0:30[v];
        anullsrc,atrim=0:2[at];[0][at]acrossfade=d=1,afade=d=1[a]"
       -map "[v]" -map "[a]" -c:v libx264 -crf 22 -preset veryfast -shortest fadeInOut.mp4

FFmpeg有一个sseof选项,允许用户从末尾寻求输入。我们可以用它来实现我们的目标。因此,我们两次输入输入,第二次只摄取最后一秒。我们告诉FFmpeg保留时间戳,以便ffmpeg保留此尾部的时间位置。

我们对此尾巴进行淡出,然后将结果覆盖到完整的输入上。由于它们是相同的媒体文件,因此前景完全覆盖了背景,并且由于copyts应用了前景,因此叠加会发生在背景输入中相应的相同帧上。

对于音频,我们创建一个持续时间为2秒的空白虚拟音频,然后将主音频的音频淡入淡出应用到该虚拟音频。由于第二音频为空白,因此实际上是主输入的淡出。将-shortest被添加到离开了哑音频部分发生了交叉淡入淡出后。


这给出了错误“没有这样的过滤器!” 用于音频过滤器。
felwithe

1
使用了4个音频过滤器。哪一个?运行-report添加的命令并共享报告。
Gyan

7

这是一个可怕的技巧,但是如果您只想让音频淡入/淡出但不知道剪辑有多长时间,这可能会起作用:

ffmpeg -i input.mp4 -filter_complex "afade=d=0.5, areverse, afade=d=0.5, areverse" output.mp4

[编辑2019-07-24:请注意,此解决方案不适用于流解决方案,因为它要求在处理第一个字节之前必须先处理完整轨道]

我的另一个选择是acrossfade与无声轨道配合使用:

ffmpeg -i input.mp4 -filter_complex "aevalsrc=0:d=0.6 [a_silence]; [0:a:0] [a_silence] acrossfade=d=0.6" output.mp4

3
这实际上非常优雅:-)
bk138

这很好。你能解释一下它是如何工作的。试图使文档的感觉..
oberhamsi

1
@oberhamsi:选项1:第一个过滤器在曲目的开头添加淡入淡出。然后,它会反转音频,并在开头(实际上是结尾)处添加另一个淡入。最后,轨道再次反转。选项2创建一个0.6秒的静音轨道,并使其与原始轨道交叉淡入淡出相同的时间。所有过滤器及其用法都记录在这里:ffmpeg.org/ffmpeg-filters.html(尽管我必须同意它有点神秘)
marekventur

3

问题2的答案是肯定的!我一直在寻找相同的功能,最后写了一个bash脚本,要求以秒为单位的淡入淡出时间,并计算淡出的初始帧:

#!/bin/bash

f="$*" # all args
p="${f##*/}" # file
fn="${p%.*}" # name only
e="${p##*.}" # extension

echo
echo $f
echo $p
echo $fn
echo $e
echo

read -e -p "Number of seconds of fade-out: " -i 1 sec # prompt for fade duration in seconds

r=$(ffprobe -show_streams "$f" 2> /dev/null | grep r_frame_rate | head -1 | cut -d \= -f 2) # frame rate
let "frames = $r * $sec" # duration of fade as number of frames
echo $r
echo $sec
echo $frames
lf=$(ffprobe -show_streams "$f" 2> /dev/null | grep nb_frames | head -1 | cut -d \= -f 2) # total number of frames
let "lf = $lf - $frames" # initial frame to start fade at

ffmpeg -loglevel quiet -i "$f" -vf fade=out:$lf:$frames -r $r -vcodec libx264 -preset slow -crf 12 -bf 2 -flags +cgop -pix_fmt yuv420p -acodec copy "$fn $sec sec fade-out.$e"
open "$fn $sec sec fade-out.$e"

淡入淡出需要重新编码,因此使用较低的crf值可以libx264得到高质量的重新编码。评论应解释其他所有内容。


问题2的答案是肯定的!->仍然不是。问号是ffmpeg是否可以自动计算持续时间...但是您编写了一个脚本,该脚本运行多个ff *命令来执行此操作。但是,对于* nix系统很有用。
吉安

我明白了,所以您坚持认为您的答案仍然正确吗?如果遵循我的脚本,您将看到它确实在automatically figure out the duration使用ffprobe,并随一起安装了ffmpeg。谁说过关于命令数量的任何限制*nix?看来OP使用的是UNIX版本。.exeffmpeg命令中否。我本人正在使用OS X构建于UNIX但不是构建于其中的内容UNIX
hmj6jmh

1
*如果遵循我的脚本,您会发现它确实可以自动找出*->您的脚本可以,ffmpeg不会。
吉安(Gyan)

但它ffprobeffmpeg分发的组成部分。您正在挑剔,以挽救IMO。
hmj6jmh

我不得不承认,一些由bash脚本正在做的是没有东西能够自动地被ffmpeg的完成。但是,如果这可行,则这是解决该问题的一种方法。因此,术语“解决方法”。我不能说它是否有效,因为像大多数人一样,我没有bash或Unix系统。无论如何+1。
ashleedawg
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.