ffmpeg-normalize
ffmpeg-normalize copied to clipboard
Multiple file normalization in master release (aka "album") context
Perhaps this can best be explained with an excerpt from the manual of normalize-audio:
When operating on a group of unrelated files, you usually want all of them at the same level, and this is the default behavior. However, a group of music files all from the same album is generally meant to be listened to at the relative volumes they were recorded at. In batch mode, all the specified files are considered to be part of a single album and their relative volumes are preserved. This is done by averaging the volumes of all the files, computing a single adjustment from that, and applying the same adjustment to all the files.
Variations per track and side can be seen here is Side A of Radiohead's 45RPM In Rainbows:
I rip my vinyl per side but I end up with two (or 4) 24bit pcm files. Is there currently a way to analyze across multiple files and apply the same normalization (ebu, peak or rms) to the entire lot? If Side D is quiet, I want it to maintain its quiet in relation to Side A, etc. I typically rip with a fair amount of headroom in 24bit converters.
Regarding https://github.com/slhck/ffmpeg-normalize/issues/43#issuecomment-346541690 I can't seem to determine any alternative to the default behavior mentioned here.
Interesting use case – I never considered that before. It's not possible to do this at the moment; each file is normalized in isolation. It'd be nice to implement this behavior, but it seems like that's a bit more work.
You can achieve what you want with a manual approach, basically replicating what normalize-audio does.
- Find out the individual volume of each file using the
--print-statsoption and RMS normalization - Calculate the average volume
- Calculate the difference to the needed target for each file
- Construct the commands individually for each file
For point 1, you may use the new version I just released (it had a bug with printing multiple JSON values) and extract the mean volume using jq:
ffmpeg-normalize --print-stats --dry-run -nt rms --quiet ~/Downloads/test1.wav ~/Downloads/test2.wav | jq '.[].mean'
I was doing something close to that but left off why the output was 4 single item json arrays rather than an array of 4 items. I am parsing the results. It was still very useful.
ffmpeg-normalize SIDE_A.wav SIDE_B.wav SIDE_C.wav SIDE_D.wav -p -n -f -nt peak
Then, finding the highest max_volume (for example -4.6 dB) and applying the same gain adjustment to all files with:
ffmpeg -i SIDE_A.wav -af "volume=4.6dB" -c:a pcm_s24le SIDE_A_NORM.wav
# ... for the rest of the files
This issue becomes more obvious when you get into these 4-sided 45rpm releases where you're much more likely to end up with a side consisting of 2-3 quieter songs, etc.
Thanks for the response, very helpful!
Yeah, I just fixed the JSON bug when I responded to you, so please try with the newest version!
Sorry for not being able to provide a getter solution. It'd require quite a bit if work. I'll keep this open as an enhancement suggestion though.
I'm working a bash script to do this, and I'm not sure on the logic.
I've got the individual loudnesses, I've got the average. I'm then getting the differences by average - track_loudness. Is that the right way?
Once I've got the difference, how do I apply it?
Is using RMS different than the default EBU?
You would apply the difference by calculating the new target loudness and using that with the -t version (beware of clipping).
I am not sure that EBU-type normalization would even work for this type of album context. Wouldn't you just set everything to the same LUFS level and keep that? This is assuming albums have been mixed for more-or-less equal loudness — which I would do as a mastering engineer, so that people don't constantly turn the volume up or down between songs. (This is also why YouTube and Spotify and all other services have LUFS targets they apply to all tracks equally.)
An RMS-based album normalization makes sense for me, basically shifting everything up and down together by a specified amount in case you need more gain for some output devices.
Wouldn't you just set everything to the same LUFS level and keep that?
If LUFS works how I think it works, then yeah, it should. I must try that next - I've been trying lots of different things this afternoon as I've been working on the bash script. When I just let ffmpeg-normalize do it's thing with the defaults, it seems to match very closely. I've got a very specific album that is excellent for noticing these problems - the first track fades in from silence over the course of a minute, and it's supposed to be a seamless transition to the next track. (It's actually what made me realise the differences between replaygain track and album adjustments). So if it's not quite right then you hear it instantly. Unfortunately, the first track is the one I was telling you about in the other thread that I have to force lrt on. So the results of the first track being dynamic with a forced lrt, and the second track with pure defaults, is very close but there is a noticeable step in loudness.
EDIT: To be honest, I don't really care how it's done, all I want is for audio to be at the same comparative loudness, and the comparative loudness of tracks within an album to remain (so I don't get stepped loudness like I described).
Ok, now that they lra limit has been raised in loudnorm, I can get my reference tracks.
This is the line that I'm using:
ffmpeg-normalize *.flac -f -vn -c:a libopus -b:a 75k -ar 48000 -ext opus -e="-vbr on -compression_level 10" -pr --keep-loudness-range-target
and that produces a noticeable change in loudness between the two reference tracks. I even tried -lrt 50 for fun and it still does the same thing. This is proving an interesting little puzzle!