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.txtMethod 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.")