Two AI voiceover clips never reach the red peak meter, yet one sounds close to the listener while the other seems to recede into the room. Raising the second clip can make sibilants harsh. The voice model is not necessarily the problem: peak level and perceived loudness over a passage are different measurements.
This guide uses FFmpeg's loudnorm for two-pass processing of a narration WAV, then measures the exported file again. It is for editors and operators making courses, explainers and product videos. AI can help write or regenerate the narration; inspectable audio tools handle loudness. There is no need to upload private recordings to a chatbot, and normalization is not a cure for every audio problem.
Specify the delivery target without inventing a platform standard
The demonstration uses integrated loudness of -16 LUFS, a maximum true peak of -1.5 dBTP and a loudness-range target of 11 LU. These are example settings, not a universal video-platform specification. Substitute a client's documented requirements for I, TP and LRA, keeping the targets consistent across all three commands. LUFS and dBTP describe different properties; they are not interchangeable volume scales.
Export authorized narration from a tool such as ElevenLabs, preserve the original and put a practice copy named voice.wav in a separate folder. Work on an edited, reasonably complete passage rather than normalizing every word independently. Changing pace, removing large silent sections, selecting another track or regenerating the narration invalidates the old measurements.
Process the narration separately from music here. The final mix needs its own loudness check: compliant speech does not make speech plus music and effects compliant. loudnorm cannot recover a waveform lost to clipping, and it is not a replacement for noise reduction, de-essing or a better recording.
Check the local filter before processing a copy
Use the official FFmpeg download page to locate a suitable source. FFmpeg itself provides source code; its Windows executable links point to separate build providers. Do not describe an unknown installer as an officially signed binary or disable protection merely because a warning appears. Confirm that ffmpeg is available after extraction. If it is only in your current bin directory, PowerShell can use .\ffmpeg.exe instead of ffmpeg below.
ffmpeg -version
ffmpeg -hide_banner -h filter=loudnorm
Filter help should include loudnorm and measured_I, measured_TP, measured_LRA and measured_thresh. Record the installed version. Our editing environment has no available FFmpeg: we checked official documentation, output-field source code and command structure, but did not process a real recording or perform a listening test. The numbers below are teaching fixtures, not measured audio results.
The first pass measures without saving a finished file
From the folder containing voice.wav, run:
ffmpeg -hide_banner -nostdin -i "voice.wav" -map 0:a:0 -vn -af "loudnorm=I=-16:TP=-1.5:LRA=11:print_format=json" -f null -
-map 0:a:0 selects the first audio stream, while -vn excludes video. The null output discards processed audio instead of writing a deliverable. FFmpeg prints progress and logs; retain the loudnorm JSON at the end as the measurement record. The filter still processes the signal during this pass. Use the input fields for the original, not the output fields as if they measured that original.
The following hypothetical values illustrate the mapping. Replace them with your own results, including minus signs and decimals. Do not treat a whole terminal screen containing other log lines as a valid JSON file.
| First-pass field | Teaching value | Second-pass parameter |
|---|---|---|
| input_i | -24.00 | measured_I |
| input_tp | -10.00 | measured_TP |
| input_lra | 2.50 | measured_LRA |
| input_thresh | -34.00 | measured_thresh |
| target_offset | 0.00 | offset |
If the file is silent or values contain -inf or another non-finite result, inspect track selection and whether the file contains usable audio. Do not replace those values with -99 to force processing. A numerical result also does not make a very short excerpt representative of a full narration.
Feed measurements back and save a separate WAV
This command matches only the teaching values above. Replace all five measured/offset values with results from the same voice.wav before running it:
ffmpeg -hide_banner -nostdin -n -i "voice.wav" -map 0:a:0 -vn -af "loudnorm=I=-16:TP=-1.5:LRA=11:measured_I=-24:measured_TP=-10:measured_LRA=2.5:measured_thresh=-34:offset=0:linear=true:print_format=json" -ar 48000 -c:a pcm_s24le "voice_norm.wav"
-n refuses to overwrite an existing voice_norm.wav. Choose another output name if you need to retain an earlier result. The intermediate is 48 kHz, 24-bit PCM WAV for editing and review. It is not an MP3 conversion, and a WAV cannot recover detail already lost in a lossy source.
linear=true requests linear normalization; it does not guarantee that mode. The official loudnorm documentation requires that the target LRA is not below the source LRA and that the loudness gain does not push true peak beyond its target. Otherwise processing reverts to dynamic mode. Inspect normalization_type and listen for changes to plosives, word endings and breaths, not just the target numbers.
This guide preserves the original channel count and does not add -ac between passes. If mono content is intended for dual-mono playback, establish the measurement and delivery convention before considering dual_mono, and use consistent settings in both passes. Dynamic processing can internally upsample to 192 kHz, so the second pass explicitly sets -ar 48000. That is another reason to remeasure the actual export.
Remeasure the new file's input, not an old report's output
ffmpeg -hide_banner -nostdin -i "voice_norm.wav" -map 0:a:0 -vn -af "loudnorm=I=-16:TP=-1.5:LRA=11:print_format=json" -f null -
The new input_i and input_tp describe voice_norm.wav as measured input. If it misses the agreed target or exceeds the peak ceiling, do not edit the report to pass review. Check for a changed source, measurements copied from another file, dynamic fallback, resampling or subsequent encoding. Inspect both sound and measurements; loudnorm does not guarantee an exact result for every source.
Keep original and processed tracks in your editor and compare matching passages on the same playback equipment. Listen for transitions, sibilants, plosives and background noise. Temporarily match monitoring levels when judging quality; delivery still follows the project specification and final mix. If you prefer a service to command-line work, consider our Auphonic overview, but check current allowances, upload authorization and processing options rather than assuming unlimited free use.
AI can inspect a report, not invent a passing result
A helper such as Claude can check mappings from a numeric excerpt stripped of filenames, client names and audio content. Full logs can contain paths or file metadata. Do not paste them indiscriminately; no recording upload is needed for this check.
Here are five first-pass loudnorm fields, the second-pass filter parameters and input_i/input_tp from remeasuring the exported WAV. Check mappings, minus signs, consistent targets and non-finite values. Distinguish readable parameters, target compliance and acceptable sound. Mark missing remeasurement or listening evidence as unverified. Do not invent or replace values, describe -16 LUFS as a universal platform standard, or recommend overwriting the original.
Hand off the original narration and authorization basis, FFmpeg version, I/TP/LRA targets, five measured values, actual processing mode, export format, final measurements and listening conclusions. Mark passages still needing review. The next editor can then decide whether to remeasure, adjust the mix or regenerate narration with different emphasis, instead of blindly raising the volume again.