Indiscipline

Mild achievements and severe disappointments

posted by Kirill on 2019-10-16

ffmpeg-loudnorm-helper logo

Post updated for v0.2.0 release at 2023-04-18

ffmpeg-loudnorm-helper is a new ultra-simple helper utility for performing loudness normalization using ffmpeg’s loudnorm audio filter. This awesome filter provides EBU R128 loudness normalization, but it requires two passes to linearly normalize audio, measuring input file on the first pass. The only thing ffmpeg-loudnorm-helper does, is it automates that first pass and formats a complete copy-pasteable string of loudnorm settings for the second pass.

ffmpeg-lounorm-helper demonstration

Motivation

First of all, if you don’t use ffmpeg for your run-of-the-mill audio/video processing, you really should reconsider. It’s terrifyingly capable and deep, making it an indispensable tool for anyone dealing with media: podcasters, youtubers, musicians and just about every other person sharing their videos on social media.

Why might you need this ffmpeg-loudnorm-helper? The simplest scenario, which covers the majority of situations I use it in, is converting video/audio recordings made with smartphones or specialized recording devices, such as Zoom Q2n. In case the material has some music in it, it’s undesirable to use loudnorm in a single-pass mode, as it introduces dynamic fluctuations to the audio. I prefer to not use auto-gain functionality of recorders for the same reasons. Linear normalization preserves source macro-dynamics and just sets the loudness to the desired level.

I also like to suggest using it whenever someone uploads a YouTube video or a podcast with barely-hearable audio, which happens way too often. People are more easily persuaded to do something when it’s just a single command to copy and run.

This program is an alternative for the ffmpeg-normalize Python script. The main difference is ffmpeg-loudnorm-helper doesn’t try to wrap any ffmpeg features, aiming for smooth cooperation instead. Being a statically-built binary is also a plus. It’s written in stable Rust using, as usual, the wonderful Clap crate.

Usage

Summary: Perform a single pass with ffmpeg-lh input.wav or use command substitution to combine both passes.

ffmpeg-loudnorm-helper expects to have the ffmpeg executable reachable in your environment (you really should have it in your PATH). The output of a successful run of ffmpeg-loudnorm-helper is a formatted ffmpeg audio filter -af string with all the desired settings in place, so I advise everyone to use your shell’s command substitution capability and inline ffmpeg-lh in your ffmpeg command. This is the intended usage.

If the requested loudness target is provably unattainable with linear normalization, the program will issue a warning. However, loudnorm is a bit picky, so there’s no guarantee it will not fall back onto dynamic normalization.

Bash example:

$ ffmpeg -i input.mov -c:v copy -c:a libopus $(ffmpeg-lh input.mov) normalized.mkv

Windows CMD (what a monstrosity!):

> for /f "tokens=*" %i in ('ffmpeg-lh input.mov') do ffmpeg -i input.mov -c:v copy -c:a libopus %i normalized.mkv

Full help available with --help switch.

Downsampling

When the loudnorm filter falls back to dynamic normalization it starts upsampling the audio to 192kHz samplerate to control intersample peaks. This happens automatically and sometimes can be missed by the user, resulting in a much bigger file with non-original samplerate. As a basic protection from this, since v0.2.0 ffmpeg-loudnorm-helper provides a --resample flag that simply adds to its output the aresmaple filter with the hardcoded rate of 48kHz right after loudnorm.

Download

Latest binaries for all major platform are provided on the GitHub releases page, but I encourage everyone to build the program themselves. It’s a simple cargo build --release run, provided you have Rust installed.

ffmpeg-loudnorm-helper is a Free Software program licensed under GPLv3.

Contributing

Feel free to file a bug report or feature request via Issues.