ffmpegaudioloudnormebu-r128normalizationbucket-doc

FFmpeg loudnorm Filter: EBU R128 Loudness Normalization Guide

·Javid Jamae·6 min read
FFmpeg loudnorm Filter: EBU R128 Loudness Normalization Guide

Your viewers shouldn't need to reach for the volume knob between videos. The EBU R128 standard exists to fix that, and FFmpeg's loudnorm filter is how you implement it. But the filter has quirks that trip people up: two-pass workflows that require parsing JSON from stderr, a linear mode that silently changes behavior, and parameter defaults aimed at broadcast TV instead of streaming.

This guide covers what each parameter does, when to use single-pass vs two-pass, and how to avoid the mistakes that lead to audio that's technically compliant but sounds wrong.

Quick answer: normalize to -16 LUFS for streaming

ffmpeg -i input.mp4 -af "loudnorm=I=-16:TP=-1.5:LRA=11" -c:v copy output.mp4

This targets -16 LUFS (the YouTube and Spotify standard), caps true peak at -1.5 dBTP, and allows 11 LU of dynamic range. The -c:v copy flag passes video through untouched so only audio gets re-encoded.

Without the FFmpeg binary installed, the same operation via the FFmpeg Micro API:

curl -X POST https://api.ffmpeg-micro.com/v1/transcodes \
  -H "Authorization: Bearer $FFMPEG_MICRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"inputs": [{"url": "https://storage.example.com/input.mp4"}], "outputFormat": "mp4", "options": [{"option": "-af", "argument": "loudnorm=I=-16:TP=-1.5:LRA=11"}, {"option": "-c:v", "argument": "copy"}]}'

What I, TP, and LRA actually mean

EBU R128 defines loudness through three measurements:

ParameterWhat it measuresDefaultStreaming target
I (Integrated)Average loudness over the full file-24 LUFS-14 to -16 LUFS
TP (True Peak)Maximum instantaneous sample value-2 dBTP-1 to -2 dBTP
LRA (Loudness Range)Spread between quiet and loud sections7 LU7-20 LU

I (Integrated Loudness) is the number most people care about. YouTube normalizes to -14 LUFS, Spotify uses -14 LUFS, Apple Music uses -16 LUFS. If your audio is louder than the platform's target, it gets turned down. If it's quieter, some platforms leave it alone (YouTube) while others boost it (Spotify).

TP (True Peak) catches inter-sample peaks that a regular peak meter misses. A file can read 0 dBFS on a sample-level meter and still clip at +0.3 dBTP when the DAC reconstructs the signal between samples. The loudnorm filter prevents this.

LRA (Loudness Range) is the spread between quiet and loud sections. A podcast might have an LRA of 5 LU. A movie soundtrack could hit 20 LU. The loudnorm filter compresses or expands this range to match your target.

Single-pass loudnorm (dynamic mode)

The default single-pass mode analyzes and normalizes in real time:

ffmpeg -i input.mp4 -af "loudnorm=I=-16:TP=-1.5:LRA=11" -c:v copy output.mp4

Dynamic mode uses a sliding window to track loudness and adjusts gain on the fly. The tradeoff: it can't see what's coming next, so transitions between very quiet and very loud sections sometimes overshoot.

For podcasts, interviews, and talking-head videos, single-pass is usually fine. The audio is already fairly consistent, so the filter doesn't need to make large corrections.

Two-pass loudnorm (measured mode)

Two-pass gives you precise results because the filter analyzes the entire file before making changes.

Pass 1: Measure the input

ffmpeg -i input.mp4 -af "loudnorm=I=-16:TP=-1.5:LRA=11:print_format=json" -f null - 2>&1 | tail -12

This outputs JSON measurements to stderr:

{
  "input_i": "-22.35",
  "input_tp": "-3.21",
  "input_lra": "8.70",
  "input_thresh": "-33.50",
  "output_i": "-16.02",
  "output_tp": "-1.49",
  "output_lra": "7.80",
  "output_thresh": "-27.12",
  "normalization_type": "dynamic",
  "target_offset": "0.02"
}

Pass 2: Apply with measured values

ffmpeg -i input.mp4 -af "loudnorm=I=-16:TP=-1.5:LRA=11:measured_I=-22.35:measured_TP=-3.21:measured_LRA=8.70:measured_thresh=-33.50:offset=0.02:linear=true" -c:v copy output.mp4

Feeding the measured values back tells the filter exactly what adjustments to make. No guessing, no sliding windows.

Linear vs dynamic mode

The linear=true parameter in two-pass mode changes how the filter works.

Linear mode applies a single constant gain to the entire file. A whisper stays proportionally quieter than a shout. The original dynamic range is preserved. Use this for music and cinematic audio.

Dynamic mode (the default) actively compresses audio to fit within your LRA target. Quiet sections get boosted, loud sections get pulled back. Better for speech content where you want everything consistently audible.

Common pitfalls

Wrong target for the platform. The loudnorm default of -24 LUFS targets broadcast TV (the original EBU R128 spec). Streaming platforms use -14 to -16 LUFS. If you don't override the I parameter, your audio ends up quieter than everything else on YouTube.

Forgetting -c:v copy. Without it, FFmpeg re-encodes the video track too. That takes 10x longer and can reduce quality. Only the audio needs processing.

Two-pass without linear=true. If you run two-pass but leave out linear=true in the second pass, you get dynamic compression with measured values. That works, but you're missing the point. The reason to measure first is to enable linear mode for precise, non-destructive normalization.

Normalizing already-normalized audio. Running loudnorm on audio that's already at your target won't leave it alone. The filter still processes the signal and can introduce subtle artifacts. Check levels first:

ffmpeg -i input.mp4 -af "loudnorm=print_format=json" -f null - 2>&1 | grep input_i

If input_i is within 1 LUFS of your target, skip normalization entirely.

FAQ

What LUFS target should I use for YouTube?

YouTube normalizes playback to -14 LUFS. If your audio is louder, YouTube turns it down. If it's quieter, YouTube leaves it as-is. Target -14 LUFS if YouTube is your primary platform.

Does loudnorm work with all audio codecs?

The loudnorm filter processes decoded PCM audio, so it works with any input codec FFmpeg can decode. Output codec depends on the container. MP4 defaults to AAC. WebM defaults to Opus.

Can I normalize audio without re-encoding video?

Yes. Add -c:v copy to pass the video track through untouched. Only the audio gets decoded, processed, and re-encoded. Faster and preserves original video quality.

What's the difference between loudnorm and the volume filter?

The volume filter multiplies every sample by a fixed value. It doesn't analyze loudness, doesn't respect any standard, and can clip the output. The loudnorm filter uses EBU R128 perceptual loudness measurement, respects true peak limits, and optionally controls dynamic range. Use volume for simple gain adjustments. Use loudnorm when you need broadcast-compliant or platform-compliant results.

How do I normalize a batch of files to the same level?

Two-pass mode is essential for batches. Measure each file first, then apply with linear=true. This ensures every file hits the same target without dynamic compression artifacts that sound different across files.

*Last verified: July 2026 against FFmpeg 7.x and the FFmpeg Micro API v1.*

About Javid Jamae

Founder & CEO at FFmpeg Micro

Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.

Software EngineeringVideo ProcessingFFmpegCloud ArchitectureAPI DesignAutomation

Ready to process videos at scale?

Start using FFmpeg Micro's simple API today. No infrastructure required.

Get Started Free