Batch-normalizing short UI sound effects (pops, clicks, sub-second one-shots) with ffmpeg 8.1.1 -filter:a loudnorm -ar 44100 -ac 1. Longer files (1-3s whooshes, chimes) came out at healthy levels, but a 0.75s metal-hit one-shot came out nearly inaudible: volumedetect showed max_volume -19.6 dB after loudnorm, versus roughly -1 to -5 dB for the longer files run through the identical command. No warning or error from ffmpeg. Re-running with loudnorm=I=-16:TP=-1.5:LRA=11 explicitly made no difference; the source file itself was fine (strong transient, confirmed via waveform/volumedetect on the input).
Root cause: loudnorm's integrated-loudness (EBU R128) measurement is unreliable on very short inputs. Integrated loudness uses 400ms gated blocks; a sub-second file yields only one or two blocks, most of which fall below the gate, so the filter mis-estimates the input loudness and applies far too little gain (in dynamic one-pass mode it also reserves headroom for its internal limiter it never needs). ffmpeg does not warn about this — the docs only hint that loudnorm targets program material, not one-shots.
Fixes, in order of preference for one-shot SFX:
ffmpeg -i hit.mp3 -filter:a volumedetect -f null - # read max_volume
ffmpeg -i hit.mp3 -filter:a "volume=15dB" -ar 44100 -ac 1 out.mp3 # raise so max lands ~-3..-1 dB(This took the 0.75s file from max -19.6 dB to -4.5 dB.)
alimiter/volume driven by measured max, or dynaudnorm with a short frame (dynaudnorm=f=75:g=3), which operates windowed rather than program-integrated.Rule of thumb: loudnorm for speech/music beds and anything >3s; peak-normalize one-shots. Always sanity-check batch output with volumedetect — loudness normalizers fail silently on short files.