March 18, 2011

Weekend Project: Batch Convert Your Music Collection on Linux

Disk space is cheap, but it still isn't free. So if your inner audiophile persuades you to rip your music collection to a lossless format like FLAC, you can enjoy a pristine sound at home, but it's simply too much information for flash-based storage — you have to come up with another solution for taking your tunes on the road. Luckily this is a weekend project where you can spend a few minutes setting up, and rest of your weekend letting the computer do the work while you relax.

Basically, if you want a lossless and a lossy copy of each track, you will need to encode each track twice. None of the Linux CD rip-and-encoding applications currently support simultaneously encoding two versions of each track, but there are a couple of other strategies that will get to the same place — and potentially faster, since they may not require your presence at the keyboard.

Every Bit You Take

One approach is to use an auto-transcoding filesystem plugin for FUSE, such as MP3FS or Fuse-music. These systems create a virtual directory that appears to be filled with lossy versions of your lossless originals, but which in reality are only generated when accessed by an application — including a music player or file manager you use to copy them onto a portable device. They have the advantage that they don't require any extra disk space: the FUSE module transcodes the FLAC files to the lossy format during the file-access operation.

One big disadvantage is that they are relatively immature code; with lots of files, they may create error-ridden files, or in the worst-case scenario, simply hang. Another disadvantage is that the transcoding happens as the files are being copied, which slows down the copy process. Syncing a big collection could take a while, unless you have a really fast processor and/or lots of cores.

There is, without doubt, something "l33t" about using FUSE to transcode your files on the fly, so for those of us who secretly think Linux has gotten too user-friendly in recent days, it is an attractive approach. But the hidden cost of this approach is that you re-transcode each file every time it is accessed — including if you remove it and later replace it, and including a full complete transcode for every individual device you synchronize.

It's essentially a CPU-versus-disk trade-off. As long as you are expending your processor cycles to perform the work, you'd might as well store the results locally. The only trick is that first time-consuming step of bulk transcoding the big audio directory. There are several tools to automate the process for you, each with its own strengths and weaknesses.

Batch School

If you are looking for a GUI app, SoundConverter is a general-purpose batch conversion tool that can get the job done in a hurry. It uses GStreamer, and it can be used to convert any GStreamer-supported format to any other format — thus FLAC to Ogg Vorbis or FLAC to MP3 is no special task. The preferences let you save your converted files in the same directories as the originals, or in a separate hierarchy, and let you specify file-renaming rules.

It is also very simple to define the output format you prefer in SoundConverter, including bitrate and mode (i.e., constant bitrate or variable bitrate), and even resampling. But that is also SoundConverter's weak point: it only cares about the output format. You can't tell it to ignore (or directly copy-over) existing lossy files. If you have a 100% lossless collection, SoundConverter can make short work of duplicating a lossy version of it, complete with all metadata tags preserved, but it blindly double-converts stray lossy files in a mixed collection. The interface is also so simple (one big, scrolling list of queued files) that it is very difficult to search through it and pick out individual files to remove from the queue.

A better solution would allow you to transcode the lossless files, but leave the already-lossy files untouched. Such flexible strategies are available through a few command-line tools, mostly Bash scripts that leverage existing CLI multimedia utilities like the LAME encoder or FFmpeg. There are a lot of these scripts, and most of them use a variation of the "classical Unix" naming convention flac2mp3.

A good flac2mp3 script is located on the Arch Linux wiki, for example. There are actually four variants on the wiki page, each with a slightly different set of features. The first is a straightforward LAME conversion of all *.flac files in the directory that you supply as an argument, copying artist, genre, date, track number, and album and song title metadata tags with the id3 utility.

The second extends the first to make better use of LAME's improved VBR encoding behavior, although for some reason it also adds a "No ReplayGain" switch (which you can safely remove on the copy of the script you use). It also uses LAME itself to write the MP3 files' metadata tags instead of the id3 tool, so it has one less dependency. The third version adds the ability to recursively step down through subdirectories finding all FLAC files, and the fourth adds the ability to specify a separate output directory.

In my estimation, the fourth version of the script is one you really want, although it doesn't hurt to edit any of the scripts to tweak some of the settings to your personal preferences (e.g., ReplayGain support). Just make sure you install the latest LAME and id3 packages before you start, and run your tweaking experiments on a relatively small subset of your whole music library.

Music By Numbers

As well as flac2mp3 works, it is still on the "dumb script" end of the transcoding spectrum: essentially providing one pre-determined output format and location. We can do better. If you're keen on Ogg Vorbis output, for example, the acxi script is flexible enough to transcode to both Vorbis and MP3, depending on which flags you supply at the command line, and has adjustable control for Vorbis and MP3 encoding quality, and sensible defaults.

More importantly, acxi supports a --copy argument, after which you can supply a comma-separated list of filetypes for the script to copy as-is into your destination directory. Thus you can run acxi -q 9 --destination /home/yername/music/ogg --copy mp3,ogg,jpg and the script will recursively walk the source directory, converting the FLACs but copying over the MP3s, Oggs, and JPEG files. Why would you need to copy over JPEG files, you ask? Simple: album cover artwork.

This is almost exactly the behavior that you want for our example scenario: you get a mirror-image of your almost-all-lossless music collection, but in the lossy format of your choosing, and there are no double-encodes. The only reason I do not outright recommend acxi as the perfect solution is that it doesn't handle ID3 tag conversion when outputting MP3s. If you are after Vorbis output,of course, it works fine. Acxi is also written in Perl, which I don't find particularly friendly to alteration (although that's just me), but if you want to hack the script to add MP3 tag support, it should be possible with LAME.

In practice, I find the Python-based music-collection-sync script to be the easiest option of all. Like acxi, it copies lossy files over into the destination fold hierarchy, but it preserves metadata tags, and even supports WAV file input in addition to FLAC. The version hosted on the site copies over .m3u playlist files (which is nice), but not JPEGs, but the code is simple enough that adding .jpg to the "convert_map" structure is trivial. This script is also far less wordy than acxi, both in its code and in its command-line output. I trust LAME enough that if a test directory turns out fine, I don't need a constant stream of "updating" lines written to stdout when I pull the trigger for the main library.

The big trade-off is that music-collection-sync is designed for MP3 output only. Whether or not this is a deal-breaker for you is strictly a matter of personal preference. Many open source advocates objected to MP3 for a long time due to the patent-owners' harassment and public disparaging of Vorbis, and insist that Vorbis still produces better audio quality for a fixed file size. I think they are probably right, but the bit-perfect FLAC copies of my music at home keep me from caring too much about the information lost in the last few ones and zeroes of the lossy copy on my phone — and on more than one occasion I've found that lending someone an Ogg copy of a song just leads to confusion.

Your mileage may vary, of course. In addition, music-collection-sync is nice because it separates the transcodign functionality (wav_to_mp3 and flac_to_mp3) into separate functions. A few minutes of study with oggenc, and you could easily swap in a flac_to_ogg function of your own.

Bombs Away

If you do that, sending a patch back to music-collection-sync is obviously the best use of the time you save not attempting all of these transcodes by hand. Which leads to one final point of discussion: I haven't actually laid out how to use any of the CLI tools to generate the lossy copy of your audio collection in step-by-step fashion. That's because how best to attack a large job like this is very context-dependent. If this is the first time you've set out to create a bulk-transcode, you might not know how to estimate the amount of time it will take to churn through the entire job. If you fire it up Sunday evening expecting it to be finished before you get up Monday morning, you could be in for a nasty surprise if your numbers are off — as well as the dilemma of whether or not to kill the process mid-batch and try again later.

A simple piece of advice to help with making the estimate would be to pick a medium-sized folder and run the transcode job on it alone, clocking the whole job with the time program. For instance, time music-collection-sync.py music/flac/The_Police music/mp3/The_Police. You can pull up Sting & company in your favorite music player to get a quick count of the total time taken up by their collected works (a statistic most music players provide automatically when you select an artist), and build your estimate from there.

If the estimate turns out to be longer than you can leave a process running on your machine without interfering with other tasks, I'd advise pulling up a graphical disk usage monitor like Filelight to get a quick visual perspective on how your different subdirectories contribute to the total. That way you can roughly split the task into two, three, or four chunks, depending on the time estimate, and tackle one per night. However you divide up the initial bulk job, on each subsequent addition of a single album, you have far less to worry about: just rip the CD as usual, and run the transcoder to synchronize only the new songs.

Click Here!