Mercurial > ~darius > hgwebdir.cgi > itunes2mp3
changeset 1:0ca90a90e723
Complete rework to make MP3 CDs from iTunes plist (XML) playlists.
Use ffmpeg as it doesn't barf on long file names or some m4as (like faad) nor does it display unwanted album images and hang wasting CPU (mplayer).
Shuffle now creates a directory and fills it with hardlinks in random order.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Thu, 13 Jun 2013 00:16:23 +0930 |
parents | 7ca49dff763a |
children | 1681a628ceb4 |
files | itunes2mp3.py |
diffstat | 1 files changed, 53 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/itunes2mp3.py Wed Jun 12 22:36:44 2013 +0930 +++ b/itunes2mp3.py Thu Jun 13 00:16:23 2013 +0930 @@ -3,51 +3,77 @@ import errno import glob import os +import plistlib import random import shutil import subprocess +import sys +import urllib2 def compress(srcfile, destdir): - f = file(srcfile, 'rU') - for line in f: - s = line.strip().split('\t')[-1] - path = reduce(lambda a, b: a + '/' + b, s.split(':')[1:], '') + plist = plistlib.readPlist(srcfile) + playlist = plist['Playlists'][0] + + failures = [] + for item in playlist['Playlist Items']: + track = plist['Tracks'][str(item['Track ID'])] + if 'Location' not in track: + print "No location for " + track['Name'] + continue + + location = track['Location'] + + path = urllib2.unquote(urllib2.urlparse.urlparse(location).path) print "Path is " + path + destmp3 = destdir + '/' + path.split('/')[-1][:-3] + 'mp3' if os.path.isfile(destmp3): - print "Skipping" + print "Already done" continue + devnull = file('/dev/null', 'w') if path.lower().endswith('.mp3'): shutil.copy(path, destmp3) elif path.lower().endswith('.m4a'): - faad = subprocess.Popen(['faad', '-qw', path], stdout = subprocess.PIPE) - lame = subprocess.Popen(['lame', '--abr', '160', '-', destmp3], stdin = faad.stdout) - faad.stdout.close() # So lame will get SIGPIPE - rtn = lame.communicate() - print "Returned " + str(rtn) + ffmpeg = subprocess.Popen(['ffmpeg', '-y', '-v', 'quiet', '-b', '160', '-i', path, destmp3]) + rtn = ffmpeg.wait() + + if rtn != 0: + print "Failed to convert %s, return code %d" % (path, rtn) + failures.append(path) + try: + os.unlink(destmp3) + except OSError, e: + if e.errno != 2: + raise e else: print "Don't know how to convert " + path + if len(failures) > 0: + print + print "Failures:" + for f in failures: + print f def shuffle(srcdir): + try: + os.mkdir(srcdir + '/burn') + except OSError, e: + if e.errno != 17: + raise e files = glob.glob(srcdir + '/*.mp3') random.shuffle(files) - for i in range(6): - destdir = srcdir + '/CD%02d' % (i + 1) - try: - os.mkdir(destdir) - except OSError, e: - if e.errno == errno.EEXIST: - pass - for j in range(99): - try: - shutil.move(files.pop(), destdir) - except IndexError, e: - break - print "Ran out of space, %d left" % (len(files)) + + i = 0 + for f in files: + dest = srcdir + '/burn/%03d - %s' % (i, f.split('/')[-1]) + i += 1 + os.link(f, dest) if __name__ == "__main__": - srcfile = 'Stuff I like.txt' - destdir = '/tmp/music' - compress(srcfile, destdir) - shuffle(destdir) + if len(sys.argv) != 2: + print "Bad usage" + print "%s playlist.xml destdir" + sys.exit(1) + + compress(sys.argv[1], sys.argv[2]) + shuffle(sys.argv[2])