Countless times I have bought a CD and ripped it to my music collection only to find that it has no meta data. No artist, no album and worst off all no album art (I like my album art alright). There are countless tools out there that could do this for me but I wanted one that I had made because why not?
The following code is my solution to tagging album art. It takes a directory as a required arguments and then a bunch of other arguments to deal with things such as release date, genre and most importantly album art.
#!/usr/bin/env python import os, glob, eyed3, optparse parser = optparse.OptionParser(usage="python %prog [options]", version="%pro 1.0") parser.add_option("-A", "--artist", dest="artist", default=None, help="Adds the artist tag to all songs") parser.add_option("-a", "--album", dest="album", default=None, help="Adds the album tag to all songs") parser.add_option("-i", "--image", dest="image", default=None, help="Adds an image to all songs") parser.add_option("-t", "--title", dest="title", default=False, action="store_true", help="Add the title tag and use the filename") parser.add_option("-g", "--genre", dest="genre", default=None, help="Add genres to all songs. Takes a comma seperated list as argument") parser.add_option("-r", "--release", dest="release", default=None, type="int", help="Add the release date tag to all songs e.g. 1998") parser.add_option("-d", "--directory", dest="directory", default=None, help="Directory that target songs are stored in") (options, args) = parser.parse_args() if options.directory is None: raise ValueError("No directory was given! Try again with the '-d' option.") if os.path.isdir(options.directory): raise IOError("'%s' does not exist." %(options.directory)) songs = glob.glob(options.directory + "*.mp3") print("[*] Tagging %d songs" %(len(songs))) for song in songs: audio = eyed3.load(song) if options.artist is not None: audio.tag.artist = unicode(options.artist) if options.album is not None: audio.tag.album = unicode(options.album) if options.image is not None: if not os.path.isfile(options.image): raise IOError("'%s' does not exist" %(options.image)) image = open(options.image, "rb").read() if options.image.endswith("jpg"): audio.tag.images.set(3, image, "image/jpeg", u"") elif options.image.endswith("png"): audio.tag.images.set(3, image, "image/png", u"") else: raise IOError("Image extension not supported.") if options.title is not None: name = song.split("/")[-1] audio.tag.title = unicode(name) if options.genre is not None: audio.tag.genre = unicode(options.genre) if options.release is not None: if len(options.release) != 4: raise ValueError("Release date must be a 4 digit integer e.g. 1998") else: audio.tag.year = unicode(str(options.release)) audio.tag.save() name = song.split("/")[-1] print("[+] Successfully tagged '%s'" %(name))
The backbone of this program is the optparse module. Using this you can specify a whole host of options from the command line with the only required argument being the directory of the songs.
- The artist option adds the artist tag to the song
- The album tag adds the album tag to the song
- The image option adds the specified image although it only supports jpeg and png images as of yet
- The title tag is a true/false option and adds the title tag based on the filename. The filename is capatalized first.
- The genre option can take a comma separated list meaning multiple genres can be added for an album
- The release date takes a integers as an argument e.g. 1997
- The directory argument is the only required argument and points the script to the MP3 files.
Once all the data is collected from the command line, the program iterates over the given directory using the glob module, creating a list of files. Then, using the eyed3 module, the program adds tags to each song, saving after each one.
There is not much in the way of error handling. The only checks that happen are on the command line elements. The inputs are checked to make sure they are correct e.g. the image file exists or the release sat is a 4 digit number etc. If the program for some reason cannot tag the MP3 file and error will be raised and the program will exit (although this hasn’t happened to me yet 🙂 )