Add fade-in and fade-out programmatically with FFmpeg

There is always a need to add fade-in and fade-out to audio tracks. Here is a way of doing it for a bunch of video files. It may come in handy with the audio normalization script I have shown previously. That script is based on continuously normalizing the audio, which may result in some noise in the beginning and end (because there is little/no sound in those parts, hence they are normalized more).

It is easy to add a fade-in to the beginning of a file using FFmpeg’s afade function. From the documentation, you can do a 15-second fade-in like this:

afade=t=in:ss=0:d=15

And a 25-second fade-out like this:

afade=t=out:st=875:d=25

Unfortunately, the latter requires that you specify when to start the fade-out. That doesn’t work well in general, and particularly not for batch processing.

A neat trick

Searching for solutions, I found a neat trick that solved the problem. First, you create the normal fade-in. Then you make the fade-out by reversing the audio stream, applying a fade-in, and then reversing again. The whole thing looks like this:

ffmpeg -i input.mp4 -c:v copy -af "afade=d=5, areverse, afade=d=5, areverse" output.mp4

A hack, but it works like a charm! And you don’t need to re-encode the video (hence the -c:v copy message above).

Putting it together

If you want to run this on a folder of files and run a normalization in the same go (so you avoid recompressing more than once), then you can use this bash script:

#!/bin/bash

shopt -s nullglob
for i in *.mp4 *.MP4 *.mov *.MOV *.flv *.webm *.m4v; do 
   name=`echo $i | cut -d'.' -f1`; 
   ffmpeg -i "$i" -c:v copy -af "loudnorm=I=-16:LRA=11:TP=-1.5,afade=d=5, areverse, afade=d=5, areverse" "${name}_norm.mp4"; 
done

Save, run, and watch the magic!

Published by

alexarje

Alexander Refsum Jensenius is a music researcher and research musician living in Oslo, Norway.