Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Normalising MP3 volume under Linux (Read 6325 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Normalising MP3 volume under Linux

Trying to get all my music to the same level under Linux.  I have tried R128GAIN and BS1770GAIN and having some problems with them.  Are there any other tools that can do this from the console?

R128GAIN appears to be abandoned and doesn't compile, nor come in armhf  binary form, but seems capable of both scanning and saving MP3.

BS17700GAIN seems supported, can scan MP3, but only write FLAC.  This doesn't help me.  I don't really want to create huge temporary FLAC files on my embedded SDCard, and then convert them back down to 1/10th size MP3.
 
Both seem to horribly hobbed for scripting, by trying to be "too smart" on the commandline  (for example, trying to get it to process a single named file in a directory, but not process everything else in there and have a single defined output file)
Are there any solutions?

Re: Normalising MP3 volume under Linux

Reply #1
What you want is something like mp3gain (changes the volume of mp3 without reencoding), but with r128 algo in place, pretty sure you could script something like that, but I'd just do

1. 'wine foobar2000.exe'.
Look how pretty that is:

Is that is an ARM/server only stuff, this might be harder.

2. Scriptin way
Compile mp3gain (compiles on Debian Jessie), then:
either (hard one)
a. Use ffmpeg with EBUr128 to calculate the gain needed, then use mp3gain to write this to mp3 files. Assuming mp3gain is still using old replaygain calculus (no idea).
example:
Code: [Select]
ffmpeg -nostats -i file.mp3 -vn -filter_complex ebur128 -f null - 2>&1 | tail | grep I: | awk '{print $2}'
should echo integrated loudness (use that to calc the dB level needed for mp3gain to change).
Code: [Select]
correct=$(echo "(-23)-($integrated)+6" | bc) # example with 6dB boost
Before all that you may want to check if your ffmpeg is correctly equipped
Code: [Select]
ffmpeg -filters 2>/dev/null | grep -q 'EBU R128' || { echo "your ffmpeg doesn't have EBU R128 scanner, exiting." ; exit 1; }
or (easy one)
b. Just use mp3gain and its calculus (mp3gain -r *.mp3)

edit: I'am ignoring tagging possibilities.
PANIC: CPU 1: Cache Error (unrecoverable - dcache data) Eframe = 0x90000000208cf3b8
NOTICE - cpu 0 didn't dump TLB, may be hung

 

Re: Normalising MP3 volume under Linux

Reply #2
quod libet and his replaygain plugin.
scan all formats
Music is my first love.

Re: Normalising MP3 volume under Linux

Reply #3
I used loudness-scanner, but only to compute/display the value, didn't try tagging.

Re: Normalising MP3 volume under Linux

Reply #4
DeaDBeeF and his replaygain plugin.
Music is my first love.

Re: Normalising MP3 volume under Linux

Reply #5
Thanks for the suggestions.  but perhaps a couple of things I should mention.

  • This needs to be CLI, there is no desktop or Linux GUI, it's a headless RPI. (so X-Server GUI apps are no use)
  • As far as I can tell neither ezstream or icecast support Replaygain tags, so the changes need to be applied to the file by re-encoding, simply tagging replaygain values is not sufficient..
  • I need to limit the amount of data written to SD card during the process.  This is an embedded system running from a MicroSD card.

I have got something working with lots of cardboard and string.  I dumped 30 files in the drop folder, and it chugged though and processed them, and then updated my radio playlist with the normalised output.  It's less than ideal, as due to limitations of programs, it has to write 2xMP3 and 1xFLAC in the process.  If anything fails, the cardboard and sting solution all falls apart.  Any suggestions on simplifying or improving most welcome....

My bash script:
http://pastebin.com/raw/fjHsnJ7E

Re: Normalising MP3 volume under Linux

Reply #6
Quote
the changes need to be applied to the file by re-encoding
Now I'am sorry I even bothered.
PANIC: CPU 1: Cache Error (unrecoverable - dcache data) Eframe = 0x90000000208cf3b8
NOTICE - cpu 0 didn't dump TLB, may be hung

Re: Normalising MP3 volume under Linux

Reply #7
Sorry, for some reason on my phone, it didnt render the lower part of the message.  I see you posted a far simpler way of doing this, but had some problems stitching those bits together.

A Google came up with this: https://github.com/chrishunt/dot-files/blob/e7b70453bc0f2beb48c5a57796aa068eb1b98636/bin/lufs

 It's just I am having some problems getting either of these working.

This is what I have:

Code: [Select]
#!/bin/bash -x
target=18
command="ffmpeg -nostats -i $1 -filter_complex ebur128=peak=true -f null -"
lufs=$(eval $command 2>&1 | grep -v ebur128 | grep I: | awk {'print $2'})
adjust=$(bc <<< "-1 * ($lufs + $target)")
echo $adjust

and this is what it complains about:

Code: [Select]
root@RPI:~# ./test.sh "/media/The Rolling Stones - Bitch (Extended Version).mp3"
+ target=18
+ command='ffmpeg -nostats -i /media/The Rolling Stones - Bitch (Extended Version).mp3 -filter_complex ebur128=peak=true -f null -'
++ grep -v ebur128
++ eval ffmpeg -nostats -i /media/The Rolling Stones - Bitch '(Extended' 'Version).mp3' -filter_complex ebur128=peak=true -f null -
++ awk '{print $2}'
++ grep I:
+ lufs=
++ bc
(standard_in) 1: syntax error
+ adjust=
+ echo


Re: Normalising MP3 volume under Linux

Reply #8
Run through http://www.shellcheck.net first. Not sure if you should assign command to $command like that, probably not.
PANIC: CPU 1: Cache Error (unrecoverable - dcache data) Eframe = 0x90000000208cf3b8
NOTICE - cpu 0 didn't dump TLB, may be hung

Re: Normalising MP3 volume under Linux

Reply #9
This
Code: [Select]
#!/bin/bash

# this is not working correctly!!!

# set -x

# mp3ebuGain
# burn mp3gain based on ebur128 to mp3 files

# check
ffmpeg -filters 2>/dev/null | grep -q 'EBU R128' || { echo "your ffmpeg doesn't have EBU R128 scanner, exiting." ; exit 1; }
command -v mp3gain >/dev/null 2>&1 || { echo "I need mp3gain." ; exit 1; }

while [ $# -gt 0 ]; do

    echo "$1"

    lufs=$(ffmpeg -nostats -i "$1" -vn -filter_complex ebur128 -f null - 2>&1 | tail | grep I: | awk '{print $2}')
    echo "$lufs lufs"

    correct=$(echo "print ((-23)-($lufs)+6)" | python3 ) #float
    echo "$correct correct"
   
    correct=$(echo "print (round((-23)-($lufs)+6))" | python3 ) # integer
    echo "$correct correct int"

    mp3gain -g "$correct" "$1"
       

shift
   
done
should theoretically work, but it isn't for some reason. If I run this few times, always new adjustments are made, which might be a bug or perhaps some sort of ffmpeg/metadata behaviour or ....
PANIC: CPU 1: Cache Error (unrecoverable - dcache data) Eframe = 0x90000000208cf3b8
NOTICE - cpu 0 didn't dump TLB, may be hung

Re: Normalising MP3 volume under Linux

Reply #10
Hmm, the script is very close to working.  It seems to work better if I feed mp3gain the integer value, not the float.

Obviously this means it will do less precision in it's adjustments, but I guess loudness measurement isn't an exact science anyway.

Re: Normalising MP3 volume under Linux

Reply #11
Hmm, still seeing some strangeness trying to get everything to -18LUFS.    Seems I need to divide the value by 1.5...

Code: [Select]
 correctionsteps=$(echo "print (round(((-18)-($lufs))/1.5))" | python3 ) # integer
    echo "$correctionsteps correct steps"


    if [ $correctionsteps -ne 0 ]
    then
      mp3gain -g "$correctionsteps" "$1"
    else
      echo "LUFS is already correct (or very close) to target."
    fi


Everything then seems to work.  (using ffmpeg and bs1770 to verify the result and running multiple times)

Code: [Select]
root@RPI:~# bs1770gain --replaygain "/media-drop/Soundgarden - Spoonman.mp3"
analyzing ...
  [1/1] "Soundgarden - Spoonman.mp3":
      integrated:  -7.31 LUFS / -10.69 LU
  [ALBUM]:
      integrated:  -7.31 LUFS / -10.69 LU
done.
root@RPI:~# ./test.sh "/media-drop/Soundgarden - Spoonman.mp3"
/media-drop/Soundgarden - Spoonman.mp3
-7.3 lufs
-7 correct steps
Applying gain change of -7 to /media-drop/Soundgarden - Spoonman.mp3...

done
root@RPI:~# bs1770gain --replaygain "/media-drop/Soundgarden - Spoonman.mp3"
analyzing ...
  [1/1] "Soundgarden - Spoonman.mp3": 99Error decoding audio, skipping audio package: frame_reader_run(), "ffsox_frame_reader.c" (151).                                       
      integrated:  -17.85 LUFS / -0.15 LU
  [ALBUM]:
      integrated:  -17.85 LUFS / -0.15 LU
done.
root@RPI:~# ./test.sh "/media-drop/Soundgarden - Spoonman.mp3"
/media-drop/Soundgarden - Spoonman.mp3
-17.8 lufs
0 correct steps
LUFS is already correct (or very close) to target.
root@RPI:~# ./test.sh "/media-drop/Soundgarden - Spoonman.mp3"
/media-drop/Soundgarden - Spoonman.mp3
-17.8 lufs
0 correct steps
LUFS is already correct (or very close) to target.


Re: Normalising MP3 volume under Linux

Reply #12
Yes, but I don't see why would this need to be run multiple times, luckily for us this forum is full of fancy coders who can't wait to fix this (5 liner).
PANIC: CPU 1: Cache Error (unrecoverable - dcache data) Eframe = 0x90000000208cf3b8
NOTICE - cpu 0 didn't dump TLB, may be hung

Re: Normalising MP3 volume under Linux

Reply #13
Yes, but I don't see why would this need to be run multiple times, luckily for us this forum is full of fancy coders who can't wait to fix this (5 liner).

It doesn't.  I ran it multiple times to see if it wanted to make changes every time.  It didn't.  It consistently got it right first time.

Re: Normalising MP3 volume under Linux

Reply #14
Then we have a working solution?
PANIC: CPU 1: Cache Error (unrecoverable - dcache data) Eframe = 0x90000000208cf3b8
NOTICE - cpu 0 didn't dump TLB, may be hung