#!/usr/bin/env python # Author: Sean McLean # License: GPLv2 # # Requires: pyid3lib import pyid3lib, optparse, sys, os # file extension mime mappings mimes = {"jpg": "image/jpeg", "jpeg": "image/jpeg", "png": "image/png"} # set up option parser usage = "%prog [options] [cover art file] [target MP3 file]" opts = optparse.OptionParser(usage = usage) opts.add_option('-f','--force',action='store_true',dest='force',help='force overwriting of existing images') opts.add_option('-l','--listtypes', action='store_true',dest='listtypes',help='list image types') opts.add_option('-t','--type', action='store',dest='imgtype',help='image type (use -l to list types)') opts.add_option('-d','--description', action='store',dest='description',help='image description') options,files = opts.parse_args() # print image types if selected if options.listtypes: print """ID3 Image Types: 01 - 32x32 pixels 'file icon' (PNG only) 02 - Other file icon 03 - Cover (front) ***Default*** 04 - Cover (back) 05 - Leaflet page 06 - Media (e.g. label side of CD) 07 - Lead artist/lead performer/soloist 08 - Artist/performer 09 - Conductor 10 - Band/Orchestra 11 - Composer 12 - Lyricist/text writer 13 - Recording Location 14 - During recording 15 - During performance 16 - Movie/video screen capture 17 - A bright coloured fish 18 - Illustration 19 - Band/artist logotype 20 - Publisher/Studio logotype""" sys.exit() # validate file arguments if len(files) != 2: print "Invalid parameter count.\n" opts.print_help() sys.exit() # get file extension fileext = os.path.splitext(files[0])[1][1:].lower() # validate image file if not mimes.has_key(fileext): print "The image file you specified is invalid; images must be in jpg or png format.\n" opts.print_help() sys.exit() else: mimetype = mimes[fileext] # load tags for mp3 file id3 = pyid3lib.tag(files[1]) # open image file tcf = open(files[0], 'rb') # picture type if options.imgtype: picturetype = options.imgtype else: picturetype = 3 # description if options.description: description = options.description else: description = 'None' # loop through all frames i=0 while i < len(id3): # if this is an apic frame, and its the picture type we wanted if id3[i]['frameid'] == 'APIC' and int(id3[i]['picturetype']) == int(picturetype): # if we were told to force, then force if not options.force: print 'An image already exists with type '+str(picturetype)+'. Enable force mode (-f) to overwrite it.' sys.exit() else: print 'An image already exists with type '+str(picturetype)+', but force is enabled, overwriting.' del id3[i] # next frame. i += 1 # create new id3 frame picframe = { 'frameid': 'APIC', 'mimetype': mimetype, 'description': description, 'picturetype': int(picturetype), 'data': tcf.read() } # close image file tcf.close() # add image frame id3.append(picframe) # update tags id3.update() # output print files[0], "added to", files[1], "with type", str(picturetype)