EBU R volume levelling across songs
-
I basically always use "Shuffle Albums" when listening to my music. A fair number of albums (not a lot, but enough) have songs that seamlessly transition between each other. EBU R normalization, right now, normalizes them independently of each other, making the transitions a bit rough. It would be nice if there was an option to perform normalization across entire albums.
With some more involved heuristics, it might be possible to only groups those songs which do transition between each other (or have some way of flagging them manually).
Here's a little script I wrote to do that normalization manually with ffmpeg:
#!/bin/env fish set target_i "-24.0" set target_lra "+11.0" set target_tp "-2.0" echo '' > /tmp/files.txt for f in $argv; echo "file '"(realpath $f)"'" >> /tmp/files.txt end set ffmpeg_args -hide_banner -safe 0 -f concat -i /tmp/files.txt -af loudnorm="print_format=json:i=$target_i:lra=$target_lra:tp=$target_tp" -f null - set jq_args -s --stream-errors -- '[.[]|select(.[0]|type=="array")|flatten]|map({key:.[0],value:.[1]})|unique_by(.key)|from_entries' set json (ffmpeg $ffmpeg_args 2>&1 | jq $jq_args) set input_i (echo "$json" | jq -r .input_i) set input_lra (echo "$json" | jq -r .input_lra) set input_tp (echo "$json" | jq -r .input_tp) set input_thresh (echo "$json" | jq -r .input_thresh) set target_offset (echo "$json" | jq -r .target_offset) set loudnorm "print_format=summary:linear=true:i=$target_i:lra=$input_lra:tp=$target_tp" set loudnorm "$loudnorm:measured_i=$input_i:measured_lra=$input_lra:measured_tp=$input_tp" set loudnorm "$loudnorm:measured_thresh=$input_thresh:offset=$target_offset" for f in $argv; mkdir -p out/(dirname $f) ffmpeg -hide_banner -i "$f" -af loudnorm="$loudnorm" -c:a flac -compression_level 12 out/(dirname $f)/(basename $f).flac end
I'm not particularly happy using it over my entire library, for preservation reasons if nothing else. It's also probably not particularly smart; there may be a way to use the results of individual normalization to produce something at least mostly correct for their aggregate.
I may also take a crack at this myself at some point, though I don't know when that might be.