ffmpeg-normalize
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.
✨ Features
- EBU R128 loudness normalization — Two-pass by default, with an option for one-pass dynamic normalization
- RMS-based normalization — Adjust audio to a specific RMS level
- Peak normalization — Adjust audio to a specific peak level
- Selective audio stream normalization — Normalize specific audio streams or only default streams
- Skip files already at target — Avoid re-encoding files already within a threshold of the target level
- Before/after summary — Print a table of input and output levels and the applied gain for all files with
--print-summary - Self-documenting output — Optionally record the effective encoder settings as an
ENCODER_SETTINGStag - Video file support — Process video files while preserving video streams
- Docker support — Run via Docker container
- Python API — Use programmatically in your Python projects
- Shell completions — Available for bash, zsh, and fish
- Album Batch normalization – Process files jointly, preserving relative loudness
🚀 Quick Start
- Install a recent version of ffmpeg and Python 3.10 or higher
- Run
pip3 install ffmpeg-normalizeandffmpeg-normalize /path/to/your/file.mp4, alternatively installuvand runuvx ffmpeg-normalize /path/to/your/file.mp4 - Done! 🎧 (the normalized file will be called
normalized/file.mkv)
🆕 What's New
-
Version 1.42.0 can optionally write an
ENCODER_SETTINGStag 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-codecunless 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-statsoutput now includes a per-filestatus(normalized,skipped, orerror, plus anerrormessage 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-depthto opt out. It also adds--keep-mtimeto 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), andstreaming-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,2to 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:
- Shell completions (v1.31.0) — Tab completion for bash, zsh, and fish shells. See the installation guide for setup instructions.
--lower-onlyoption — Prevent audio from increasing in loudness, only lower it if needed (works with all normalization types).
See the full changelog for all updates.
📓 Documentation
Check out our documentation for more info!
🤝 Contributors
The only reason this project exists in its current form is because @benjaoming's initial PRs. Thanks for everyone's support!
Metadata
Release files for ffmpeg-normalize 1.43.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ffmpeg_normalize-1.43.0.tar.gz | 46.7 kB | Without provenance | Details for ffmpeg_normalize-1.43.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ffmpeg_normalize-1.43.0-py3-none-any.whl | Python 3 | none | any | Details for ffmpeg_normalize-1.43.0-py3-none-any.whl |
Total release size: 99.6 kB
Release files / ffmpeg_normalize-1.43.0.tar.gz
| Download URL | ffmpeg_normalize-1.43.0.tar.gz |
|---|---|
| Size | 46.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6ff299430650c2b8c0a3e0d7484c44525dedf02541aef4fe0ee23c5149c2e03a
|
|
BLAKE2b-256 checksum How to use checksums |
a752235f2990dfafe030161dcd0c8f9e1c5c9b47cd0ccbf0cad95cfbd2fb39f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / ffmpeg_normalize-1.43.0-py3-none-any.whl
| Download URL | ffmpeg_normalize-1.43.0-py3-none-any.whl |
|---|---|
| Size | 52.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e3ed508061bc246b69c46bf7e7c68cc01b56e3ecd64fcc173b7c4a3c31667291
|
|
BLAKE2b-256 checksum How to use checksums |
cc31c9ca8e2781533d0951f65ca538685898ad636155a4f29b31e9000c0ed5d5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Security for ffmpeg-normalize 1.43.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.