(Download the script from this article flac2mp3.sh)
When converting FLAC files to MP3, the first problem you will notice is that lame does not support FLAC files. This might now seem like big problem, because you can easily decode FLAC files using the command line tool flac and then use the decoded file with lame.
The real problem is that you will loose your metadata in this process, so the tags you added to your FLAC won’t be copied to the MP3 file. While you could “easily” add them by hand, it is pretty annoying to do that even if you only want to convert a handful of files.
The solution is to extract the metadata from the FLAC file using metaflac and to use the options lame provides to inject the tags into the MP3 file when calling lame.
This section is merely provided to explain the steps involved. You do not need to read this nor do you need to do this by hand, since I offer you a small script that will do these steps for you (look at the very first line of the article or below under “Download” to download the script).
Step 1 – Extract the Metadata
To extract a single tag, you can use metaflac like this:
metaflac --show-tag=<tag> <file>
To extract the artist of the track from the file named “1 – Let It In.flac”, you could call:
metaflac --show-tag=ARTIST "1 - Let It In.flac"
In general you will get a result like this:
In the mentioned example you might get the following:
Step 2 – Fomat the Metadata
We only need the name of the artist, so we need to get rid of “ARTIST=”. This can be easily achieved with sed. The general way of replacing something with sed is this:
OLD is the part that you want to replace and NEW is the part that you want to replace it with. What we want to replace is “ARTIST=” (which is our OLD) and what we want to replace it with is nothing (which will essentially remove OLD), so our NEW is empty. And this is what we get:
But that would only work for the ARTIST tag. A general solution would be to remove anything up to and including the equal sign. I won’t go into detail on this one, but this would be achieved by setting OLD to “.*=” and the line would look like this:
To make this work, we need to we need to pass the output of metaflac to our sed command, which we would do like this:
metaflac --show-tag=ARTIST "1 - Let It In.flac" | sed 's/.*=//'
This way the output of metaflac (“ARTIST=Josh Woodward”) is send to our sed command, which then removes the “ARTIST=” part and thus we get the output:
Step 3 – Store the tag
While the line from Step 2 works, it merely prints the tag. What we need to do is to store the tag somehow, so that we can use it again later for adding the tag to the MP3 file. To store the output of a command in a variable, you generally type:
(Those are not single quotes in this line, but backticks/grave accents) This will execute <command> and then store the output to the variable <var>.
In this example we could do this:
ARTIST=`metaflac –show-tag=ARTIST “1 – Let It In.flac” | sed ‘s/.*=//’`
This would execute out metaflac command and save the output (“Josh Woodward”) in the variable ARTIST.
We can test if everything worked by printing the value of ARTIST:
which should now give us:
Step 4 – Passing the tags to lame
In general, calling lame (and using VBR mode) would work like this:
lame -V <oldfile> <mp3file>
If you want lame to save metadata to the mp3 file, you can use several options do to this. To continue our example, let’s assume we want to add the name of the artist (that we have stored in the variable ARTIST in the last step) to the new MP3 file. This can be done with the –ta option:
lame -V --ta "$ARTIST" <oldfile> <mp3file>
In a similar way, we can add other tags to the mp3 file as well. Here is a small table that shows you the options lame offers to add metadata, the name of the FLAC tag that theese options correspond to and what they mean.
|FLAC tag||Lame option||Description|
|The title of the track|
|The title artist|
|The album name|
|The year of the album|
|a comment for this track|
|The number of the track and the total number of the tracks|
|the genre of the track|
Step 5 – Passing the FLAC to lame
We have not solved the original problem yet: you can not pass a flac file to lame. We could decode the FLAC to WAV and then pass the WAV file to lame, but we don’t need do really create a WAV file, because we can just decode the FLAC and pass the decoded data directly to lame. To do this, we need to call flac with two options:
- -d to tell it we want to decode a flac file
- -c, so that the decoded data is not written to a file, but to stdout
Then, we can tell lame that it should read the data from stdin instead of from a file, which can be done by providing a dash for the <oldfile> parameter. Now we can connect them both with a pipe and the decoded flac data will directly flow into our lame command:
flac -c -d <flacfile>| lame - <mp3file>
In our example, we would get something like this (which includes adding the ARTIST tag and a VBR quality of 6):
flac -c -d "1 - Let It In.flac" | lame -V 6 --ta "$ARTIST" - "1 - Let It In.mp3"
Now that the basic steps involved are covered, we can let a script do the work.
I wrote a small script that converts a FLAC file to MP3 while preserving the following tags (=all the tags listed in “Step 4″ above):
- Track Title
- Track Artist
- Album Title
- Total number of tracks
You can download the script here: flac2mp3.sh
The script takes three arguments:
- The VBR quality (This corresponds to the -V option of lame, which means that you can use a number between 0 and 9, with smaller numbers meaning higher quality and bigger files). If you omit this option, -V 4 will be used.
- The filename of the FLAC file you want to convert
- The filename of the new MP3 file that you want to create.
- You can (but don’t have to) add “mtime” as the fourth argument in which case the script will not start the conversion if the MP3 file is newer than the FLAC file, which indicates that a conversion is not necessary. (If you don’t add “mtime”, the script will convert the files no matter what)
If you want to convert the file “1 – Let It In.flac” to “1 – Let It In.mp3″ with a VBR quality level of 3, you would call the script like this:
flac2mp3.sh 3 "1 - Let It In.flac" "1 - Let It In.mp3"
flac2mp3.sh 3 "1 - Let It In.flac" "1 - Let It In.mp3" mtime
The script generally works as described under “The Solution”, but instead of repeating the line from “Step 3″ for every tag, it uses a more elegant approach (which in this case just means less code). But instead of posting the complete source code (which you can look at by download the script), let me just show you the meat of the script (extracting the 8 tags and passing them to lame for conversion):
for tag in TITLE ARTIST ALBUM DATE COMMENT TRACKNUMBER TRACKTOTAL GENRE; do eval "$tag=\"`metaflac --show-tag=$tag "$FLAC" | sed 's/.*=//'`\"" done flac -cd "$FLAC" | lame -V "$V" --tt "$TITLE" --ta "$ARTIST" --tl "$ALBUM" --ty "$DATE" --tc "$COMMENT" --tn "$TRACKNUMBER/$TRACKTOTAL" --tg "$GENRE" - "$MP3"
I have updated the script a little. It’s now possible to append a “mtime” after the three arguments. When adding “mtime”, the script will only start the conversion if the MP3 file does not exist yet or the FLAC file is newer than the MP3 file.
This will avoid unnecessary conversions in case the MP3 is newer than the FLAC file, which indicates it is up-to-date. This is useful when using this script to somehow manage your library as it will reduce a large number of conversions.