Batch MP3 transcoding.

Hello everyone, I've made a script and I want to share and get new ideas for improving it. So far, the script

  1. Searches a directory tree for MP3 files;
  2. Check their bitrates;
  3. Change any bitrate higher than 128 kbps to VBR 4
    (It ignores files with a bitrate lower or equal to 128, as well already with variable bitrate);
  4. Remove original files.

The script uses MP3Info, Gawk, and Lame. I've made it for Bash, but I think it would work in others shells too.

Here it is:

#!/bin/bash
#Script made by Eduardo Xavier - eduardoc[dot]xavier[at]yahoo[dot]com[dot]br
#Script license: GPL v3

#Makes a MP3s list in the dir, with bitrates, in "allfiles.list":
find . -name "*.mp3" -exec mp3info -r v -p "%r \"%F\"\n" '{}' \; > allfiles.list

#Filter only files with 160, 192, 224, 256 or 320 bitrates:
gawk '$1 == 160 {$1 = ""; print}
$1 == 192 {$1 = ""; print}
$1 == 224 {$1 = ""; print}
$1 == 256 {$1 = ""; print}
$1 == 320 {$1 = ""; print}' allfiles.list > onlyhigh.list

#Change the filtered files to VBR, quality 4:
gawk '{system("lame -v" $0)}' onlyhigh.list

#Remove original files. Comment the line below if you don't want this happening.
gawk '{system("rm" $0)}' onlyhigh.list

#Remove os arquivos de listas que foram feitos.
rm onlyhigh.list allfiles.list

Troubles until now:
*IDE3 tags are lost (not a great deal since I name all my MP3s with the relevant info);
*The output files are all with extension ".mp3.mp3", I want the script renaming them automatically (however, I made this with KRename).
*The script is slow. Especially in the LAME part.

Anyone got ideas?

One awk command is sufficient, try this:

find . -name "*.mp3" -exec mp3info -r v -p "%r \"%F\"\n" '{}' \; | 
gawk '$1 >= 160{$1 = "";system("lame -v" $0)}'

To rename the files you can use this:

ls *.mp3.mp3 | sed 's/\(.*\)\..*/mv & \1/' | sh

Make sure you get the right files and try it first without te coloured portion.

Regards

Thank you!

I was a bit afraid telling the gawk ">= 160", because I didn't know what it would do for non-number strings (as "variable").

Now the code is much simpler... I've tested it, the awk part works nice.

The renaming part, as you posted, wasn't working for file names with spaces; some quotes made the job :slight_smile: . The last pipe was really needed for interpreting as a command.

find *.mp3.mp3 | sed 's/\(.*\)\..*/mv -f "&" "\1"/' | sh

The over-consuming step - LAME - still remains, but I think it can't be helped...

Just for curiosity... I've noticed that the find command works in a random order, not alphabetically, is this correct?

Regards!
[hr]
EDIT: Contrary what I said before... for gawk, "variable" >= 160. I changed the "more or equal" again to "exactly equal"... here's the code:

#!/bin/bash

find . -name "*.mp3" -exec mp3info -r v -p "%r \"%F\"\n" '{}' \; |
gawk '$1 == 160{$1 = "";system("lame -v" $0)}
$1 == 192{$1 = "";system("lame -v" $0)}
$1 == 256{$1 = "";system("lame -v" $0)}
$1 == 320{$1 = "";system("lame -v" $0)}'

find *.mp3.mp3 | sed 's/\(.*\)\..*/mv -f "&" "\1"/' | sh
echo UFA, TERMINOU =D

Find has no option to sort the result, why don't you use ls instead of find or sort to sort the result?
Edit: I don't see any reason to sort the result of the find command here.

Regards