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!

Removing audio hum using a highpass filter in FFmpeg

Today, I recorded Sound Action 194 – Rolling Dice as part of my year-long sound action project.

The idea has been to do as little processing as possible to the recordings. That is because I want to capture sounds and actions as naturally as possible. The recorded files will also serve as source material for both scientific and artistic explorations later. For that reason, I only trim the recordings non-destructively using FFmpeg.

Recording the dice example, however, I noticed an unfortunate low-frequency hum in the original recording:

The original recording has an unfortunate low-frequency hum.

I like the rest of the recording, so I thought it would be a pity to skip publishing this sound action only because of the hum. So I decided to break my rule of not processing the sound and apply a simple highpass filter to remove the noise.

Fortunately, FFmpeg, as always, comes to the rescue. It has myriad audio filters that can be combined in various ways. I only needed to add a highpass filter, which can be accomplished using this one-liner:

ffmpeg -i input.mp4 -c:v copy -af highpass=400 output.mp4

Here I use the -c:v copy to copy the video stream directly. This avoids re-compressing the file and saves time. Then I use the -af highpass=400 function to add the highpass filter to the audio stream with a frequency of 400 Hz. This is relatively high but works well for this example.

The recording with highpass-filtered audio.

Adding a filter means that the audio stream needs to be re-compressed. So it breaks with the original (conceptual and technical) idea. However, the result sounds more like how I experienced it. I didn’t notice the hum while recording, and this project is focused on foreground sounds, not the background. However, this example is relevant for my upcoming project, AMBIENT, in which I will focus on the background sound of various in-door environments.

Export images from a PDF file

I have previously written about how to export each of the pages of a PDF file as an image. That works well for, for example, presentation slides that should go on a web page. But sometimes there is a need to export only the images within a page. This can be achieved with a small command line tool called pdfimages.

One way of using it is:

pdfimages -p -png file.pdf image

This will export all images in file.pdf and label them with something like image-001-010.png, where the first number refers to the page and the second is a count of images.

Sometimes I just take a screenshot if I want to grab something from a PDF. But this is a more robust method if you want to grab several different images from a PDF file.

Merge multiple MP4 files

I have been doing several long recordings with GoPro cameras recently. The cameras automatically split the recordings into 4GB files, which leaves me with a myriad of files to work with. I have therefore made a script to help with the pre-processing of the files.

This is somewhat similar to the script I made to convert MXF files to MP4, but with better handling of the temp file for storing information about the files to merge:

Save the script above as mergevideos.sh, put it in the folder of your files, make it executable, with a command like:

chmod u+x mergevideos.sh

run the file:

./mergevideos.sh

and watch the magic.

The script above can be remixed in various ways. For example, if you want a smaller output file (the original GoPro files are quite large), you can use FFmpeg’s default MP4 compression settings by removing the “-c copy” part in the last line above. That will also make the script take much longer, since it will recompress the output file.

Preparing video for Matlab analysis

Typical video files, such as MP4 files with H.264 compression, are usually small in size and with high visual quality. Such files are suitable for visual inspection but do not work well for video analysis. In most cases, computer vision software prefers to work with raw data or other compression formats.

The Musical Gestures Toolbox for Matlab works best with these file types:

  • Video: use MJPEG (Motion JPEG) as the compression format. This compresses each frame individually. Use .AVI as the container, since this is the one that works best on all platforms.
  • Audio: use uncompressed audio (16-bit PCM), saved as .WAV files (.AIFF usually also works fine). If you need to use compression, MP3 compression (MPEG-1, Layer 3) is still more versatile than AAC (used in .MP4 files). If you use a bitrate of 192 Kbs or higher, you should not get too many artefacts.

Many people ask me how to convert from typical MP4 files (with H.264 video compression and AAC audio compression). The easiest solution (I think) is to use FFMPEG, the versatile command-line utility. Here is a oneliner that will convert from an .MP4 file into a .AVI file with MJPEG and PCM audio:

FFmpeg -i input.mp4 -c:a pcm_s16le -c:v mjpeg -q:v 3 -huffman optimal output.avi

The resultant file should work well in Matlab and other video analysis tools. We have included this conversion by default in the new Musical Gestures Toolbox for Python. So there, you can directly load an MP4 file, which will be converted to an AVI file using a script similar to the one above.