Audio and video · Edition No. 13 · 7 Sep 2026

slhck/ffmpeg-normalize

Normalises every video to the EBU R128 loudness YouTube expects — ten minutes, and viewers stop reaching for the volume.

← Audio and videoRead the whole edition →
04

slhck/ffmpeg-normalize

💎 hidden gem
ffmpeg-normalize: one loudness level. Sets files to the same measured loudness.

1.5k stars · MIT · v1.42.0 (2026-09-02) · Track this in Rising ↗

Normalises every video to the EBU R128 loudness YouTube expects — ten minutes, and viewers stop reaching for the volume.

Verified27 Oct 2026

Radar check

What we found when we opened it. Every bar is one fact, with its date.

Alive90

Last code pushed 14 Oct 2026, 13 days before this check.

Releases100

Latest release v1.43.0 on 14 Oct 2026.

Maturity100

Public since July 2014, a little over 12 years.

Adoption64

1,539 stars and 131 forks.

Activity45

12 commits and 0 new issues in the last 90 days.

Community80

30 contributors. 2 pull requests merged in 90 days.

Security40

No security policy file says how to report a problem. No published security advisories.

Licence MIT: permissive: use it for anything, keep the noticeSetup effort 1 of 5Payoff 4 of 5
How the bars are scored
  • Alive. Days since the last code push: a week or less 100, a month 90, three months 70, six months 50, a year 30, eighteen months 15, older 0.
  • Releases. Age of the latest GitHub release, on a similar scale; no bar when the project publishes no releases.
  • Maturity. Age of the project: eight years 100, five 90, three 70, two 55, one 40, six months 25, younger 10.
  • Adoption. Stars on a log scale: 100,000 stars is 100, 10,000 is 80, 1,000 is 60, 100 is 40.
  • Activity. Commits in the last 90 days: 300 or more 100, 100 85, 30 65, 10 45, any 25.
  • Community. People who have contributed: 100 or more 100, 30 80, 10 60, 5 40, 2 25, one 10.
  • Security. A published security policy 80, none 40; published advisories are listed, not scored.

Checked by Repo Radar on 27 Oct 2026 from the repository on GitHub. Covered in Edition 13.

▶Repo detailsthe review · specs · pros & cons · install

What it does

It measures how loud a file is using EBU R128, the broadcast loudness standard, then rewrites the audio at a level you choose. That is the same measurement the large video platforms use when they quietly raise or lower an upload. It can also do simple peak or RMS adjustment when the standard method is not wanted. It works on a whole folder in one run, and it can write a report of the measurements instead of changing anything. It chooses sensible output settings and lets every part of them be overridden. Version 1.43.0 was released on 14 October 2026. It fixes level only: it does not remove hiss, hum or room echo, and raising a quiet passage raises the noise under it too.

Why it matters

Who it suits. It suits anyone publishing a series, where a viewer moves from one file to the next and hears the difference. It suits a back catalogue recorded at various times, because a whole folder can be fixed in one pass. It also suits any pipeline that mixes sources, such as a recorded voice next to generated speech from #1 or #2, which will arrive at different levels. Skip it for a single file that already sounds right, and skip it if the real problem is noise rather than level.

Verdict. The clearest ten minutes in this edition. The one detail everyone gets wrong first time is the --dual-mono flag, which is needed for a recording where one person speaks on both channels; without it the measurement comes out 3 dB off. Listen to one result before running a batch, since loudness work makes existing noise more audible. Keep it next to #3 and run it second.

Stars1.5k
LicenceMIT
Latestv1.42.0 (2026-09-02)checked 7 Sep 2026
Written inHTML
NeedsDocker, Python 3 and ffmpeg
Summary (Key Points)from the README
Key features
  • EBU R128 loudness: Two-pass by default, with an option for one-pass dynamic normalization.
  • RMS and peak normalization: Adjusts audio to a set RMS level or peak level.
  • Selective streams: `-as 1,2` normalizes only streams 1 and 2, `--audio-default-only` targets default tracks, and `--keep-other-audio` copies the rest unchanged.
  • Skip files at target: `--threshold 0.5` copies files already within that range unchanged instead of re-encoding them (disabled by default).
  • Batch/album mode: `--batch` shifts all files by the same amount, preserving relative loudness. The README example shifts an album so its average RMS is -20 dB.
  • Presets: Built-in `podcast` (EBU R128, -16 LUFS), `music` and `streaming-video` presets, plus custom presets.
  • Reporting: `--print-summary` prints input and output levels and applied gain, and `--print-stats` gives a per-file status.
  • Format handling: Video streams are preserved, and bit depth is kept by default for formats like FLAC.
Ways to install
Platform or methodWhat it needsEffort
pip (`pip3 install ffmpeg-normalize`)A recent ffmpeg and Python 3.10 or higherOne command
uv (`uvx ffmpeg-normalize`)A recent ffmpeg and uv installedOne command
DockerA Docker container; the README gives no setup detailsNot specified in the README
Important
  • ffmpeg dependency: A recent ffmpeg must be installed separately.
  • Python version: Python 3.10 or higher is required for the pip route.
  • Skipped files: With `--threshold`, files within range are copied through unchanged, not re-encoded.
  • Exit codes: A non-zero exit code means at least one file failed, so scripts should check it.
  • Encoder settings tag: `--write-encoder-settings` writes an ENCODER_SETTINGS tag only for Matroska/WebM outputs, and it has no effect with `--metadata-disable`.
  • Output location: The quick start writes output to a `normalized/` folder, for example `normalized/file.mkv`.

Written by an AI model from the project’s README; not part of the review, and it can be wrong.

Setup effort
1 / 5
Payoff
4 / 5
Good
  • Works across a whole folder, so an entire back catalogue is one command.
  • Short to learn and nothing to remember afterwards.
  • MIT licence, and it can be run without a permanent install through uvx.
Watch for
  • It needs ffmpeg installed, and it needs the --dual-mono flag for single-speaker recordings.
  • It changes level only. Noise, hum and echo are untouched.
  • Raising a quiet passage raises the hiss with it, so the number alone is not proof of a good result.
Replaces

This is the step that makes them one video instead of three different sources.

Install
brew install ffmpeg        # or: sudo apt install ffmpeg
pip install ffmpeg-normalize
ffmpeg-normalize lesson-tight.mp4 -c:a aac -b:a 192k -t -14 --dual-mono -o lesson-ready.mp4
Screenshots
slhck/ffmpeg-normalize: GitHub preview cardslhck/ffmpeg-normalize: Screenshot 1slhck/ffmpeg-normalize: Screenshot 2slhck/ffmpeg-normalize: Screenshot 3slhck/ffmpeg-normalize: Screenshot 4

On Stack Radar: Design & Creative › Audio & Voice Production › Audio Editors.

Get the next edition in your inbox

A dozen repositories, opened and checked. The licence read, the last release dated, and the ones that did not make it named with the reason. It is the half most lists leave out.

No tracking pixels. One click to leave. The archive stays free either way.

We use your address to send the edition and nothing else. Confirm by email, leave in one click. How we handle it.