Extract FFmpeg loudnorm First Pass Loudness Stats

This article explains how to extract the measured loudness statistics from the first pass of the FFmpeg loudnorm filter. By running an analysis-only pass, you can capture critical audio metrics like integrated loudness, true peak, and loudness range in JSON format, which are essential for performing accurate, high-quality two-pass EBU R128 loudness normalization.

Run the First Pass Command

To extract the loudness statistics, run FFmpeg with the loudnorm audio filter, setting the print_format parameter to json. Since this pass is purely for analysis, you should discard the output audio by routing it to the null muxer (-f null -).

Execute the following command in your terminal:

ffmpeg -i input.mp3 -af loudnorm=print_format=json -f null -

Because FFmpeg sends its progress and filter logs to stderr (standard error) rather than stdout (standard output), the resulting JSON will be printed inside the terminal diagnostic logs.

Locate the JSON Output

At the end of the terminal output, you will see a JSON block labeled [parsed_loudnorm_0 @ ...] that looks like this:

[parsed_loudnorm_0 @ 0x56230f1d93c0] {
    "input_i" : "-14.35",
    "input_tp" : "-1.02",
    "input_lra" : "11.20",
    "input_thresh" : "-25.12",
    "output_i" : "-24.05",
    "output_tp" : "-10.83",
    "output_lra" : "9.10",
    "output_thresh" : "-34.51",
    "normalization_type" : "dynamic",
    "target_offset" : "0.05"
}

The key-value pairs starting with input_ represent the measured values of your source file: * input_i: Measured Integrated Loudness (LUFS) * input_tp: Measured True Peak (dBTP) * input_lra: Measured Loudness Range (LU) * input_thresh: Measured Threshold (LUFS) * target_offset: The offset to hit your target loudness

These five specific values must be fed into the second pass of the loudnorm filter for true linear normalization.

Programmatically Extracting the JSON

If you are automating this process, you need to isolate the JSON from the rest of the FFmpeg log.

Method 1: Save stderr to a text file

You can redirect the stderr output to a text file and parse it using your preferred scripting language:

ffmpeg -i input.mp3 -af loudnorm=print_format=json -f null - 2> loudness_stats.txt

Method 2: Extract directly using Python

You can use a Python script to run the command, capture the stderr stream, and parse out the JSON block automatically:

import subprocess
import json
import re

# Run the FFmpeg command and capture stderr
command = ["ffmpeg", "-i", "input.mp3", "-af", "loudnorm=print_format=json", "-f", "null", "-"]
result = subprocess.run(command, capture_output=True, text=True)

# Use regex to extract the JSON block
match = re.search(r"({.*})", result.stderr, re.DOTALL)

if match:
    stats_json = match.group(1)
    stats = json.loads(stats_json)
    
    # Extract the required variables for the second pass
    print(f"Input Integrated: {stats['input_i']}")
    print(f"Input True Peak: {stats['input_tp']}")
    print(f"Input LRA: {stats['input_lra']}")
    print(f"Input Threshold: {stats['input_thresh']}")
    print(f"Target Offset: {stats['target_offset']}")
else:
    print("Could not find loudness stats in output.")