How to losslessly concatenate / merge MP3 files
You’d think it would be very easy to combine multiple MP3 files into one, while preserving all the ID3 tag metadata and without re-encoding the audio (which is lossy). Well, it actually isn’t that hard at all, but since Google couldn’t find the answer for me, I thought I’d write it up.
I did this on my Powerbook, so these directions should work fine on any Mac/Linux/BSD/Unix system.
There is a handy command-line utility for combining MP3 files, mp3wrap. Unfortunately, it doesn’t correct the audio duration tags/headers (so iTunes/iPod will only see the first part of the file), and it clobbers your ID3 tags with its own (so that the file can later be unmerged with mp3split — this is a “feature”). There’s also the easy cat solution (cat 1.mp3 2.mp3 > all.mp3), but it doesn’t correct the duration, either. Maybe you don’t care about ID3 tags, and your playback software doesn’t care about a wrong duration header (some ignore it) — in that case, go away! But if you want to get your MP3 files right or you’re using something like iTunes, which does care, read on.
Instructions
Install mp3wrap, ffmpeg and id3lib if you don’t have them already. On Linux, you’ll likely just use your distro’s package manager to do this in a few seconds. On my Mac, I just installed mp3wrap and id3lib from source (easy “./configure && make && make install”) and used the ffmpeg binary from ffmpegX (since Fink mangled dependencies).
Do this (combines 1.mp3, 2.mp3 and 3.mp3 into all.mp3, and copies ID3 tags from 1.mp3):
mp3wrap tmp.mp3 1.mp3 2.mp3 3.mp3
ffmpeg -i tmp_MP3WRAP.mp3 -acodec copy all.mp3 && rm tmp_MP3WRAP.mp3
id3cp 1.mp3 all.mp3
Here’s what’s happening:
- mp3wrap merges the files. Unfortunately, it also leaves wrong file duration headers and clobbers any original ID3 tags.
- ffmpeg fixes the file duration. You could also use something else, like mplayer/mencoder (
-oac copyoption) here. - id3cp copies the ID3 tags from 1.mp3 to all.mp3
ksimonov
March 17, 2009, 12:10 pm
I have an error while trying to convert wraped mp3 with ffmpeg:
It happends only with ‘copy’ codec, not with fair libmp3lame
Could you show exactly command for mplayer? It doesn’t want to encode from mp3. The error is : “Audio file file format detected.Video stream is mandatory!”
sticks
March 17, 2009, 7:16 pm
You definitely want to use the copy “codec” and not lame, because the whole point is not just losslessly append the files, not decode/reencode, which means quality loss and more of that lovely “listening underwater” mp3 ickiness.
Not sure why ffmpeg didn’t work for you … could be your audio files or your ffmpeg build. The error messages suggests that your files are screwy — which would be a totally different problem. You might try experimenting with different files and/or different build on a different machine. Make sure you’ve built ffmpeg with mp3 support, test it on a single, known-clean file etc.
I don’t have an mplayer install handy … my guess is that you’d also have to use the
-of lavf and -lavcopts [...]to use libavcodec to use the mp3 container format.This step is really where you can swap in whatever program you want. For instance I have a similar workflow where I use mp3gain here to normalize the file (so if you don’t mind also normalizing the file,
mp3gain -s rc filename.mp3will also work for step 2. You probably don’t even really need to fix the duration header, just delete it. I only used ffmpeg/libavcodec here because it was the first thing I thought of and it did the trick so I didn’t have to write any code.And as a reminder be sure you’ve tried the easy
cat 1.mp3 2.mp3 > all.mp3way!ksimonov
March 17, 2009, 10:42 pm
But how can I delete header? I think it is all I really need, but I cant find the way to do it.
sticks
March 18, 2009, 12:45 am
Well, I don’t know what the “bad” header is in your case that mp3wrap is leaving behind — ID3 v1 or v2 (ID3 v1 is appended at the end of the file so technically not a “header”), or it could be Ape or Vorbis or some other metadata. To be 100% sure you could just take everything out, so that all you have are MP3 frames in a file.
There seem to be some programs out there (i.e. TidyMP3 and Tag that will do this for you — i.e. they have a mode where they don’t try to identify tags, they just look for MP3 frames and strip everything else. I’m not testing/recommending and don’t want to go any deeper into this, just hoping to point you in the right direction with what I found using the Google. Potentially any tag editor that has the ability to delete things (i.e. the 12 duration bytes in “enhanced” ID3 v1 and/or the TLEN section in ID3 v2) might work, depending on what the issue is with your files.
Personally, I would just look in my actual files (i.e. hex editor) and identify the offending bits, if they’re all from the same place. But I really don’t want to go into that!
ksimonov
March 18, 2009, 11:29 pm
I’ve found the problem case. In my current ffmpeg version (say thx to svn builds) there is a bug with file duration while acodec = copy. It is discussed in authors mailing list. So, I think it will be fixed in next release included into repository (yes, I am Ubuntu user). I’ll try to delete duration information at all as you’ve recomended.
sticks
March 19, 2009, 12:18 am
Cool … good luck!
userwaldo
April 20, 2009, 4:14 am
Found a simple replacement for ffmpeg, since it appears to have a bug in the Ubuntu version.
A little program called vbrfix seemed to do the trick for me.
Lame had been used for the encoding of the original files, before using mp3wrap to combine them.
mp3wrap tmp.mp3 1.mp3 2.mp3 3.mp3
vbrfix -ri1 -ri2 -lameinfo tmp_MP3WRAP.mp3 all.mp3 && rm tmp_MP3WRAP.mp3
id3cp 1.mp3 all.mp3
sticks
April 20, 2009, 7:02 pm
Thanks for the tip, this looks very useful. I’m compiling QT and vbrfix now!
Andy
May 12, 2009, 6:13 am
Great – thanks for the tips – one of those things that you think should be simple but ends up quite complicated (don’t get me started on changing video framerates).
Only thing I couldn’t quite work is what we gain by using mp3wrap vs just cat – since both spit out incorrect headers that we have to fix with ffmpeg, why not use the simpler option?
Paulus
July 25, 2009, 8:26 am
Thanks, very useful information. On ubuntu Jaunty, the following packages are required: ffmpeg libid3-3.8.3-dev
Tom
Sept. 23, 2009, 12:04 am
Thanks for the info. But It seems mp3wrap has got some limit on either the number of input files or total size.
do anyone know of this limitation, is there any way around?
Shelby
Oct. 2, 2009, 8:56 am
There is another way, without going through mp3wrap.
cat file list... | ffmpeg -f mp3 -i - -acodec copy outfile.mp3And then the id3 copy command.
Ron
Jan. 11, 2010, 9:02 pm
If you have wild-carded the mp3 input file list, you just be running into the shell expansion limit. If so, use the xargs trick:
$ find -name \*mp3|xargs mp3wrap all.mp3
nirpius
Feb. 23, 2010, 6:05 am
Just thought you may want to know you can substitute the first line of code for
mp3wrap tmp.mp3 *.mp3to wrap all files in the folder together
Lindylex
May 8, 2010, 11:38 pm
“There is another way, without going through mp3wrap.
cat file list… | ffmpeg -f mp3 -i – -acodec copy outfile.mp3
And then the id3 copy command.”
Shelby, this works perfectly no need to install unnecessary things, Thanks Lex