MP3+G to MP4

This is a very old article. It has been imported from older blogging software, and the formatting, images, etc may have been lost. Some links may be broken. Some of the information may no longer be correct. Opinions expressed in this article may no longer be held.

I suppose this is mostly a reminder to myself.

MP3+G is a format for karaoke music. Each song comes as a pair of files; an MP3 file containing the audio, and a CDG file containing the lyrics. CDG is not a text-like format; it’s more like a low-resolution video.

This is reasonably easy to convert to a MP4 video which will play nicely on, say, an Android device or smart TV. You just need the right software.

Preparing the Ground

Firstly you want PyKaraoke which is already packaged for Debian/Ubuntu, so is easy enough to install with apt-get.

Also you want ffmpeg. Bear in mind that Debian and Ubuntu ship with libav, which is a somewhat poor fork of the real ffmpeg. However, Jon Severinsson’s FFmpeg PPA provides an easy way to install the real ffmpeg program. (The following instructions may indeed work with libav, but have only been tested with ffmpeg.)

Step by Step

Step one; dump the frames of the CDG file as a series of JPEGs:

$ python /usr/lib/python2.7/dist-packages/pycdg.py --dump=tmp#####.jpeg --dump-fps=15 MySong.cdg

(Yes, you really do want those hashes in the command.)

Step two; find out the height and width of the frames in pixels. I’m going to use identify which is part of ImageMagick, but any other tool will do. All the files I’ve tried come out as 1024 by 572 pixels; perhaps PyKaraoke always uses those dimensions (?) but you should probably check!

$ identify tmp00001.jpeg

Step three; use ffmpeg to combine the JPEG frames with the MP3:

$ ffmpeg -r 15 -f image2 -s 1024x572 -i tmp%05d.jpeg -i MySong.mp3 -vcodec libx264 -acodec copy MySong.mp4

Notice that in steps one and three, the magic number 15 came up. This is the frames per second of the resulting video. You can use any number you like, but make sure you use the same in both places. Somewhere between 10 and 30 is probably best. I think 15 seems fine.

Lastly, clean up the temporary files created:

$ rm tmp*.jpeg

Done!