Run pass 1 to measure the file's loudness statistics: 'ffmpeg -i input.wav -af loudnorm=I=-23:TP=-1:LRA=11:print_format=json -f null -' — capture the JSON output from stderr, which contains measured_I, measured_TP, measured_LRA, and measured_thresh values
Parse the JSON output from pass 1 to extract all four measured values — you will supply these to pass 2 to enable linear normalization mode
Run pass 2 applying linear normalization using the measured values: 'ffmpeg -i input.wav -af loudnorm=I=-23:TP=-1:LRA=11:measured_I=<value>:measured_TP=<value>:measured_LRA=<value>:measured_thresh=<value>:linear=true:print_format=summary output.wav' — supplying all four measured values activates linear gain mode
Set 'linear=true' to apply a single consistent gain across the whole file rather than dynamic moment-to-moment compression — this preserves the original dynamic character of the audio while achieving the target integrated loudness
Verify the output by running the same ebur128 measurement on the result: 'ffmpeg -i output.wav -af ebur128=framelog=verbose -f null -' and confirm integrated loudness is within ±1 LU of the target
Use -ar to set the output sample rate if needed (e.g., '-ar 48000' for broadcast delivery) and choose a lossless container like WAV or FLAC for intermediate files to avoid generation loss
Known gotchas
Omitting the measured values from pass 2 causes FFmpeg to run in single-pass dynamic mode, which applies time-varying gain and alters the audio's dynamics — always supply all four measured values for a two-pass linear normalization
The loudnorm filter's output in single-pass mode can introduce audible pumping artifacts on music or complex audio — two-pass linear mode is mandatory for professional post-production use
FFmpeg prints loudnorm statistics to stderr, not stdout — capture stderr when scripting pass 1 (e.g., redirect '2>&1' or use subprocess stderr capture) or the JSON will be lost
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp