I recently revisited a previous how-to I wrote up two years ago, thinking that there must be a better way to losslessly combine multiple MP3 files than to use 3 separate utilities.
The good news is, I think I’ve found the one true method. The bad news is, it still uses 3 programs. But, just like last time, the commands are short and sweet, and it’s easy to throw them into a shell script.
To summarize from before, we want to:
- Losslessly join multiple files together (no re-encoding).
- Correctly copy metadata (ID3 tags, including cover art etc.) to the final file, while stripping the metadata of the other input files (i.e., we don’t want to just do
cat 1.mp3 2.mp3 > all.mp3and end up with leftover tags in the middle of the MPEG data stream).
- Either remove the VBR (aka Xing) header or else correct it so that file duration is correct and seeking works in iTunes and on iPods, among others.
So, what’s new? The old way produces a file with no VBR header, while the new way corrects the VBR header. Should you care about this? Well, if you ask me, this Xing header should go the way of the company that spawned it back in the 1990s. But, until then … both files work the same in i(Tunes|Pod). There are some other programs (VLC is one) that display the wrong file duration with the old method, although playback and seeking aren’t affected.
I think the internals of the file created by the new method are cleaner, and including the VBR header can improve seek performance. But for you, the choice might only come down to which set of utility programs you’d rather use.
The revised method
First, we use mp3cat, which takes a bunch of mp3 files and joins their data frames together, dumping everything else. Then, like last time, we’ll use
id3cp from id3lib to copy the metadata we want onto the joined file. Finally, VBRFix will re-sync the VBR header to the actual size of the resulting file.
In this example,
2.mp3 are merged into
all.mp3, and metadata is copied from
cat 1.mp3 2.mp3 | mp3cat - - > tmp.mp3 id3cp 1.mp3 tmp.mp3 vbrfixc --XingFrameCrcProtectIfCan tmp.mp3 all.mp3 && rm tmp.mp3
That’s it! I’ve tested this on both a Linux system and my trusty Powerbook, so it should work on any reasonable *nix.
Some tips: You can also use
mp3cat to operate on a directory of files. The command-line version of VBRFix is a little hard to find (I did an
svn export of the source, then ran
setupNonQtBuild.sh). I also tried mp3tool for this purpose, and while iTunes liked the result end, VLC displayed an incorrect file duration.
Let me know what you think.