Audio Normalization for Python/ffmpeg
See the code
A utility for batch-normalizing audio using ffmpeg.
This program normalizes media files to a certain loudness level using the EBU R128 loudness normalization procedure. It can also perform RMS-based normalization (where the mean is lifted or attenuated), or peak normalization to a certain target level.
ENCODER_SETTINGS tagpip3 install ffmpeg-normalize and ffmpeg-normalize /path/to/your/file.mp4, alternatively install uv and run uvx ffmpeg-normalize /path/to/your/file.mp4normalized/file.mkv)Version 1.42.0 can optionally write an ENCODER_SETTINGS tag on each normalized audio stream via --write-encoder-settings. The tag holds an ffmpeg-command-equivalent string — the audio codec, bitrate, sample rate and channels, plus the normalization filter including the measured loudnorm values — so a normalized file documents how it was produced. This is a Matroska/WebM convention and has no effect with --metadata-disable.
Example:
ffmpeg-normalize input.wav -c:a libopus -b:a 128k --write-encoder-settings -o output.mkv
Version 1.41.0 automatically picks the correct output audio codec for the output container, so you no longer need to specify -c:a/--audio-codec unless you want to override the default. PCM is chosen for containers that support it; others will use teh default that ffmpeg picks. See the usage guide for details.
Version 1.40.0 can optionally skip files that are already at the target level via --threshold (e.g. --threshold 0.5, disabled by default). Such files are copied through unchanged instead of being re-encoded. The --print-stats output now includes a per-file status (normalized, skipped, or error, plus an error message on failure), and the exit code is non-zero if any file failed to process, so a script can tell what happened to each file.
Example:
ffmpeg-normalize input.flac -nt peak -t 0 -c:a flac --print-stats -o output.flac
Version 1.39.0 preserves the input bit depth by default when encoding to formats like FLAC, so 16-bit input stays 16-bit without needing -e "-sample_fmt s16". Use --no-keep-bit-depth to opt out. It also adds --keep-mtime to copy the input file's modification time to the output, which is useful for preserving when a track was added to a music library.
Example:
ffmpeg-normalize input.flac -nt peak -t 0 -c:a flac --keep-mtime -o output.flac
Version 1.38.0 writes the normalized output directly to the destination without using temporary files
Version 1.36.0 introduces presets with --preset! Save and reuse your favorite normalization configurations for different use cases. Comes with three built-in presets: podcast (AES standard), music (RMS-based batch normalization), and streaming-video (video content). Create custom presets too!
Example:
ffmpeg-normalize input.mp3 --preset podcast
applies the podcast preset (EBU R128, -16 LUFS) to your file. Learn more in the presets guide.
Version 1.35.0 has batch/album normalization with --batch. It preserves relative loudness between files! Perfect for music albums where you want to shift all tracks by the same amount.
Example:
ffmpeg-normalize album/*.flac --batch -nt rms -t -20
shifts the entire album so the average RMS is -20 dB, preserving the original relative loudness as mastered.
Version 1.34.0 brings selective audio stream normalization! You can now:
Normalize specific audio streams with -as/--audio-streams (e.g., -as 1,2 to normalize only streams 1 and 2)
Normalize only default audio streams with --audio-default-only (useful for files with multiple language tracks)
Keep other streams unchanged with --keep-other-audio (copy non-selected streams without normalization)
Example:
ffmpeg-normalize input.mkv -as 1 --keep-other-audio
normalizes stream 1 and copies all other audio streams unchanged.
Other recent additions:
--lower-only option — Prevent audio from increasing in loudness, only lower it if needed (works with all normalization types).See the full changelog for all updates.
Check out our documentation for more info!
The only reason this project exists in its current form is because @benjaoming's initial PRs. Thanks for everyone's support!
Overall
Maintained
Code review
PyPI
Latest release
Releases this year
(top 24 of 26)
579 followers · starred Nov 2025
559 followers · starred Aug 2020
71 followers · starred Jan 2025
146 followers · starred Feb 2021
Audio Normalization for Python/ffmpeg
See the code
A utility for batch-normalizing audio using ffmpeg.
This program normalizes media files to a certain loudness level using the EBU R128 loudness normalization procedure. It can also perform RMS-based normalization (where the mean is lifted or attenuated), or peak normalization to a certain target level.
ENCODER_SETTINGS tagpip3 install ffmpeg-normalize and ffmpeg-normalize /path/to/your/file.mp4, alternatively install uv and run uvx ffmpeg-normalize /path/to/your/file.mp4normalized/file.mkv)Version 1.42.0 can optionally write an ENCODER_SETTINGS tag on each normalized audio stream via --write-encoder-settings. The tag holds an ffmpeg-command-equivalent string — the audio codec, bitrate, sample rate and channels, plus the normalization filter including the measured loudnorm values — so a normalized file documents how it was produced. This is a Matroska/WebM convention and has no effect with --metadata-disable.
Example:
ffmpeg-normalize input.wav -c:a libopus -b:a 128k --write-encoder-settings -o output.mkv
Version 1.41.0 automatically picks the correct output audio codec for the output container, so you no longer need to specify -c:a/--audio-codec unless you want to override the default. PCM is chosen for containers that support it; others will use teh default that ffmpeg picks. See the usage guide for details.
Version 1.40.0 can optionally skip files that are already at the target level via --threshold (e.g. --threshold 0.5, disabled by default). Such files are copied through unchanged instead of being re-encoded. The --print-stats output now includes a per-file status (normalized, skipped, or error, plus an error message on failure), and the exit code is non-zero if any file failed to process, so a script can tell what happened to each file.
Example:
ffmpeg-normalize input.flac -nt peak -t 0 -c:a flac --print-stats -o output.flac
Version 1.39.0 preserves the input bit depth by default when encoding to formats like FLAC, so 16-bit input stays 16-bit without needing -e "-sample_fmt s16". Use --no-keep-bit-depth to opt out. It also adds --keep-mtime to copy the input file's modification time to the output, which is useful for preserving when a track was added to a music library.
Example:
ffmpeg-normalize input.flac -nt peak -t 0 -c:a flac --keep-mtime -o output.flac
Version 1.38.0 writes the normalized output directly to the destination without using temporary files
Version 1.36.0 introduces presets with --preset! Save and reuse your favorite normalization configurations for different use cases. Comes with three built-in presets: podcast (AES standard), music (RMS-based batch normalization), and streaming-video (video content). Create custom presets too!
Example:
ffmpeg-normalize input.mp3 --preset podcast
applies the podcast preset (EBU R128, -16 LUFS) to your file. Learn more in the presets guide.
Version 1.35.0 has batch/album normalization with --batch. It preserves relative loudness between files! Perfect for music albums where you want to shift all tracks by the same amount.
Example:
ffmpeg-normalize album/*.flac --batch -nt rms -t -20
shifts the entire album so the average RMS is -20 dB, preserving the original relative loudness as mastered.
Version 1.34.0 brings selective audio stream normalization! You can now:
Normalize specific audio streams with -as/--audio-streams (e.g., -as 1,2 to normalize only streams 1 and 2)
Normalize only default audio streams with --audio-default-only (useful for files with multiple language tracks)
Keep other streams unchanged with --keep-other-audio (copy non-selected streams without normalization)
Example:
ffmpeg-normalize input.mkv -as 1 --keep-other-audio
normalizes stream 1 and copies all other audio streams unchanged.
Other recent additions:
--lower-only option — Prevent audio from increasing in loudness, only lower it if needed (works with all normalization types).See the full changelog for all updates.
Check out our documentation for more info!
The only reason this project exists in its current form is because @benjaoming's initial PRs. Thanks for everyone's support!
Overall
Maintained
Code review
PyPI
Latest release
Releases this year
(top 24 of 26)
579 followers · starred Nov 2025
559 followers · starred Aug 2020
71 followers · starred Jan 2025
146 followers · starred Feb 2021