MP3

From Segfault
(Redirected from MP3 errors)
Jump to navigation Jump to search

Merging

To merge multiple MP3 files into one without losing filename and ID3 information, mp3wrap can be used:

$ mp3wrap -v output.mp3 file-01.mp3 file-02.mp3
  50 %  --> Wrapping file-01.mp3 ... OK
 100 %  --> Wrapping file-02.mp3 ... OK

 Calculating CRC, please wait... OK
output_MP3WRAP.mp3 has been created successfully!

The output file is suffixed with _MP3WRAP. The ID3 information is wrapped into the file and can only be read after the file has been unwrapped again:

$ id3v2 -l output_MP3WRAP.mp3 | grep ^COMM
COMM (Comments): ()[]: This file is wrapped with Mp3Wrap. Get mp3splt, the free tool to split original files at
http://mp3splt.sourceforge.net. Please do not remove this comment.

We can also use FFmpeg to concatenate files:[1][2]

ffmpeg -i "concat:file-01.mp3|file-02.mp3" -codec:a copy output.mp3

The resulting file size should be the sum of both source files:

$ ls -lgo file-01.mp3 file-02.mp3 output.mp3
-rw-r--r-- 1 13375616 Oct  9 11:57 file-01.mp3
-rw-r--r-- 1 13863040 Oct  9 11:57 file-02.mp3
-rw-r--r-- 1 27237729 Nov 22 21:07 output.mp3

Concatenating many files with FFmpeg can be done too, although it's a bit awkward to construct a valid command line:

ffmpeg -i "concat:$(ls file*.mp3 | xargs | sed 's/mp3 /mp3|/g')" -codec:a copy output.mp3

While we're at it, let's convert the result into a different format[3] too:

ffmpeg -i "concat:$(ls file*.mp3 | xargs | sed 's/mp3 /mp3|/g')" -codec:a libopus output.opus

Using libopus makes quite a difference on the file size:

$ ls -hlgo file-01.mp3 file-02.mp3 output.opus
-rw-r--r-- 1 13M Oct  9 11:57 file-01.mp3
-rw-r--r-- 1 14M Oct  9 11:57 file-02.mp3
-rw-r--r-- 1 14M Nov 23 00:48 output.opus

Let's try that again but add metadata information to our output file, with opusenc:

ffmpeg -i "concat:$(ls file*.mp3 | xargs | sed 's/mp3 /mp3|/g')" -f wav - | opusenc --artist "Foobar" --album "Baz" --date "2015" --title "Song" --tracknumber 1 - output.opus

Again, with vorbis-tools:

ffmpeg -i "concat:$(ls file*.mp3 | xargs | sed 's/mp3 /mp3|/g')" -f wav - | oggenc  --artist "Foobar" --album "Baz" --date "2015" --title "Song" --tracknum 1 - -o output.ogg

Apparently ffmpeg can add metadata as well,[4] w/o the need for an extra program:

ffmpeg -i "concat:$(ls file*.mp3 | xargs | sed 's/mp3 /mp3|/g')" -metadata title="Foo" -metadata artist="Bar" -acodec copy output.mp3

Re-encoding

Re-encoding might be the easiest way, if no other programs (see above) were able to help. With FFmpeg:

$ file foo.mp3
foo.mp3: Audio file with ID3 version 2.3.0, contains: MPEG ADTS, layer III, v1, 128 kbps, 44.1 kHz, JntStereo

$ ffmpeg -i foo.mp3 -b:a 192k -f mp3 foo_192.mp3
$ ls -lgo foo.mp3 foo_192.mp3
-rw------- 1 4239196 May 28 20:45 foo.mp3
-rw------- 1 5274149 May 28 20:49 foo_128.mp3

A second example[5][6]:

ffmpeg -i foo.mp3 -codec:a libmp3lame -b:a 192k  foo_192.mp3               # CBR,  192 kbps
ffmpeg -i foo.mp3 -codec:a libmp3lame -qscale 2  foo_vbr.mp3               # VBR, ~170-210 kbps

With lame:

lame --strictly-enforce-ISO -p --mp3input --bitwidth 192 foo.mp3 foo_192.mp3      # CBR,  192 kbps
lame --strictly-enforce-ISO -p --mp3input -V 2 foo.mp3 foo_192.mp3                # VBR, ~190 kbps[7]

Note: the -p option adds a 16 bit checksum to every frame, for error protection.

On performance: LAME is not multi-core aware and thus will only use one CPU. There is a multithreaded version[8] called fpMP3Enc[9], but the project appears to be dead. Their development kit can still be downloaded[10] though.

Splitting

With mp3splt it's easy to split big files into smaller ones.

To split a 300 MB file into two smaller ones:

$ mp3splt -S 2 /mnt/media/big.mp3 -d . -o small-@n.mp3
Processing file '/mnt/media/big.mp3' ...
info: file matches the plugin 'mp3 (libmad)'
info: found Xing or Info header. Switching to frame mode...
info: MPEG 1 Layer 3 - 44100 Hz - Joint Stereo - FRAME MODE - Total time: 209m.00s
info: starting 'split in equal tracks' mode
  File "./small-01.mp3" created
  File "./small-02.mp3" created
Processed 480054 frames - Sync errors: 0
split in equal tracks ok

$ ls -hgo /mnt/media/big.mp3 small*.mp3
-rw------- 1 152M Mar 26 23:31 small-01.mp3
-rw------- 1 150M Mar 26 23:31 small-02.mp3
-rw-r--r-- 1 302M Feb 20  2013 /mnt/media/big.mp3

We can also do splitting tricks[11] with FFmpeg. When -acodec copy is used, the file is not re-encoded.

pull out a half hour chunk from the start of an audio file:

Extract the first 30 minutes from an audio file:

ffmpeg -i file.mp3 -acodec copy -ss 00:00:00 -t 00:30:00 file_30min.mp3

Split a 5 hour audio file into 30min tracks:

$ ffmpeg -i big-file.mp3 2>&1 | grep Duration
  Duration: 04:52:00.69, start: 0.025056, bitrate: 325 kb/s                       # That'd be ten 30min tracks

To do this, we create two files per hour:

mkdir split
i=0
while [ $i -lt 5 ]; do
    echo "Hour: ${i}"
    ffmpeg -i big-file.mp3 -acodec copy -ss 0${i}:00:00 -t 00:30:00 split/${i}a.mp3
    ffmpeg -i big-file.mp3 -acodec copy -ss 0${i}:30:00 -t 00:30:00 split/${i}b.mp3
    i=$((i+1))
done

Fixing

There are several programs out there that might be able to fix a broken MP3 file.

mp3val

mp3val will analyze (and fix) corrupted MP3 files:

svn checkout https://svn.code.sf.net/p/mp3val/subversion/trunk mp3val-svn
cd mp3val-svn
make -C sources/ -f Makefile.linux 
sudo install -o root -g root -m 0755 sources/mp3val /usr/local/bin/mp3val

Usage:

$ mp3val -f file.mp3
Analyzing file "file.mp3"...
WARNING: "file.mp3": Wrong number of MPEG frames specified in Xing header (1817 instead of 144584)
WARNING: "file.mp3": Wrong number of MPEG data bytes specified in Xing header (759848 instead of 60430192)
INFO: "file.mp3": 144584 MPEG frames (MPEG 1 Layer III), +ID3v1+ID3v2, CBR, CRC
Rebuilding file "file.mp3"...
FIXED: "file.mp3": File was rebuilt
Done!

When no corruptions are found, the file will be left alone.

Removing cover art

Transcoding an MP3 file failed with:

[mp3 @ 0x7f8419010600] Skipping 0 bytes of junk at 73436.
[png @ 0x7f8419812600] Invalid PNG signature 0xFFD8FFE000104A46.
[mp3 @ 0x7f8419010600] decoding for stream 1 failed

The trick was to discard[12] the cover art, that was somehow mangled:

ffmpeg -y -i foobar.mp3 -map 0:a -vn -codec:a libopus -map_metadata -1 foobar.opus

Links

References