I have an Apple iPod. I'm not sure why, because most of my music is ripped to Ogg Vorbis format, which the iPod doesn't play natively. Since I've had the iPod, I've had Rockbox on it in order to play all my music. But the Rockbox UI is pretty rough, and I'd like to be able to just plug the thing into my Mac and have it sync with iTunes, which requires actual thought one way or another if it's not running the native iPod OS, and I really have enough thinking to do without thinking about this. So I've decided for better or worse to transcode all my Ogg Vorbis music to MP3 and get rid of Rockbox in favor of running the iPod OS. Yes, I am lame, but I don't care. Here's the Python code I'm using to transcode my music directory into a (shadowed) directory that is Ogg-free. It requires PyOgg as well as system-invocable "oggdec" and "lame" binaries. It probably also has bugs because I haven't actually let it run all the way through my music (this will take a few days) :
"""Usage: transcode <oggdir> <outdir>"""
import errno
import os
import shutil
import sys
import tempfile
def usage():
print __doc__
sys.exit(2)
def normalize(dir):
return os.path.abspath(os.path.normpath(os.path.expanduser(dir))) + os.sep
def main(argv):
try:
infolder, outfolder = map(normalize, argv[1:])
except TypeError:
usage()
transcoder = MP3Transcoder()
transcoder.walk(infolder, outfolder)
class MP3Transcoder:
def do_ogg(self, name, inpath, outpath):
from ogg.vorbisutils import getVorbisComments
if os.path.exists(outpath):
return
tempdir = tempfile.mkdtemp()
vendor, comments = getVorbisComments(inpath)
comments = dict(comments)
unknown = 'Unknown'
if not comments.get('TITLE'):
comments['TITLE'] = name
if not comments.get('ARTIST'):
comments['ARTIST'] = unknown
if not comments.get('ALBUM'):
comments['ALBUM'] = unknown
if not comments.get('TRACKNUMBER'):
comments['TRACKNUMBER'] = '0'
if not comments.get('TRACK'):
comments['TRACK'] = comments['TRACKNUMBER']
if not comments.get('YEAR'):
comments['YEAR'] = '1'
comment = comments.get('COMMENT', '') + ' (retranscoded)'
comments['COMMENT'] = comment.lstrip()
try:
tempwav = os.path.join(tempdir, '%s.wav' % name)
os.system('oggdec -o "%s" "%s"' % (tempwav, inpath))
tempmp3 = os.path.join(tempdir, '%s.mp3' % name)
comments['infile'] = tempwav
comments['outfile'] = tempmp3
print comments
cmd = ('lame '
'--preset 192 '
'--ignore-tag-errors '
'--tt "%(TITLE)s" '
'--ta "%(ARTIST)s" '
'--tl "%(ALBUM)s" '
'--ty "%(YEAR)s" '
'--tc "%(COMMENT)s" '
'--tn "%(TRACK)s" '
'-ms -h "%(infile)s" "%(outfile)s"' % comments)
print cmd
os.system(cmd)
shutil.copyfile(tempmp3, outpath)
finally:
shutil.rmtree(tempdir)
def do_mp3(self, name, inpath, outpath):
if not os.path.exists(outpath):
shutil.copyfile(inpath, outpath)
do_m4a = do_mp3
do_m4p = do_mp3
do_flac = do_mp3
def walk(self, inroot, outroot):
for root, dirs, files in os.walk(inroot):
print root, dirs, files
for dir in dirs:
outpath = os.path.join(outroot, root[len(inroot):], dir)
try:
os.makedirs(outpath)
except OSError, why:
if why[0] != errno.EEXIST:
raise
for file in files:
name, ext = os.path.splitext(file)
realext = ext[1:]
doer = getattr(self, 'do_%s' % realext, None)
if doer is not None:
inpath = os.path.join(root, file)
outname = name + '.mp3'
outpath = os.path.join(outroot, root[len(inroot):], outname)
doer(name, inpath, outpath)
if __name__ == '__main__':
main(sys.argv)