10

As per title. I have lots of MP3s in 320kbps format that I need to convert to 192kbps. Currently I'm using lame --mp3input -b 192 which creates a file of the same name but with an extra .mp3 extension. So I end up with foo.mp3.mp3.

I need to be able to enter a directory, scan the sub directories for any 320kbps and convert to 192kbps and overwrite if any are found. Is Lame even the best tool for this?

Thanks

2 Answers 2

12

lame is perfectly suited to this task, but I'm going to use ffmpeg and ffprobe for this answer, because I know them like the back of my hand and because they can be generalised to more than just MP3s. First of all:

sudo apt-get install ffmpeg

There is no tool that I am aware of that can read media files and then over-write the input straight away: you need to use an intermediate file. For a single file, you could do:

ffmpeg -i file.mp3 -c:a libmp3lame -b:a 192k temp.mp3
mv temp.mp3 file.mp3

You could combine these into a single line:

ffmpeg -i file.mp3 -c:a libmp3lame -b:a 192k temp.mp3 && mv temp.mp3 file.mp3

the && there means that the mv command won't be executed unless ffmpeg exits with a status of 0 (which means success).

To check that what bit rate a file has, you can use ffprobe:

ffprobe -show_streams -select_streams a:0 -v quiet file.mp3 | grep -F 'bit_rate=320000'

-show_streams tells ffprobe to show information about individual streams; -select_streams tells it which ones to select, and a:0 means 'the first audio stream (this is important for MP3 files in the case of cover art, which is stored as a video stream). The pipe (|) takes the standard output of ffprobe and feeds it to grep. grep will only print those lines that match a given pattern -- in this case, lines that contain the string bit_rate=320000. If you run this on a 320k kbps MP3, you'll get a line like this:

bit_rate=32000

If you run it on anything with a different bit rate, you won't get any output at all; grep will fail to make a match, and will exit with a status of 1. This means that you can chain that command with the ffmpeg command:

ffprobe -show_streams -select_streams a:0 -v quiet file.mp3 | grep -F 'bit_rate=320000' && ffmpeg -i file.mp3 -c:a libmp3lame -b:a 192k temp.mp3 && mv temp.mp3 file.mp3

Or, a bit more readably:

ffprobe -show_streams -select_streams a:0 -v quiet file.mp3 | grep -F 'bit_rate=320000' &&
ffmpeg -i file.mp3 -c:a libmp3lame -b:a 192k temp.mp3 &&
mv temp.mp3 file.mp3

That will only act on 320 kbps MP3s. Try it with a couple of test files.

The next step is to get this working with multiple files. There are two standard ways of doing this: a for loop, and the find command. The following will act on every MP3 in a directory:

for f in *.mp3; do 
ffprobe -show_streams -select_streams a:0 "$f" | grep -F 'bit_rate=320000' &&
ffmpeg -y -i "$f" -c:a libmp3lame -b:a 192k /tmp/temp.mp3 && mv /tmp/temp.mp3 "$f"
done

This will not go into subdirectories; in order to do so, you have to set the globstar shell option:

shopt -s globstar
for f in **/*.mp3; do
ffprobe -show_streams -select_streams a:0 "$f" | grep -F 'bit_rate=320000' &&
ffmpeg -y -i "$f" -c:a libmp3lame -b:a 192k /tmp/temp.mp3 && mv /tmp/temp.mp3 "$f"
done

With find:

find . -name '*.mp3' -exec sh -c 'ffprobe -show_streams -select_streams a:0 "$0" | grep -F "bit_rate=320000" &&
ffmpeg -y -i "$0" -c:a libmp3lame -b:a 192k /tmp/temp.mp3 && mv /tmp/temp.mp3 "$0"' '{}' \;

All of these will run strictly sequentially -- they'll only convert one file at a time. Your processor is almost certainly capable of more than that, though; to speed things up, you could use GNU parallel:

sudo apt-get install parallel
shopt -s globstar
parallel 'ffprobe -show_streams -select_streams a:0 {} | grep -F "bit_rate=320000" &&
ffmpeg -y -i {} -c:a libmp3lame -b:a 192k {.}.temp.mp3 && mv {.}.temp.mp3 {}' ::: **/*.mp3

Or:

find . -name '*.mp3' | parallel 'ffprobe -show_streams -select_streams a:0 {} | grep -F "bit_rate=320000" &&
ffmpeg -y -i {} -c:a libmp3lame -b:a 192k {.}.temp.mp3 && mv {.}.temp.mp3 {}' 
3
  • Spectacular answer. I've cobbled something together using lame but I'll be giving this ago. Will report back. Oct 14, 2014 at 20:04
  • I'm getting this error: Unrecognized option 'select_streams' Failed to set value 'a:0' for option 'select_streams' Oct 15, 2014 at 10:06
  • with avconv, replace it to: avconv -i {} -b:a 192k {.}.temp.mp3 && mv {.}.temp.mp3 {}
    – lepe
    Jun 23, 2016 at 11:33
3

Lame is one of the best you can find to do this task

You can use the command lame -b 192 input.mp3 output.mp3

im not good with piping commands but you can use exiftool to get the bit rate of the mp3 file

exiftool -AudioBitrate File.mp3 

but you still need a way to pipe the commands of finding mp3 file, checking the bitrate and converting...

1
  • edited twice, fixing the command and adding bitrate
    – AdigaJo
    Oct 13, 2014 at 22:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.