Kjetil's Information Center: A Blog About My Projects

FLAC Tagging Helper

Here is a small Python script that helps with tagging FLAC files. It relies on the external "metaflac" tool to do this.

The idea with this script, is to combine it with a album template file that contains all the information that should be tagged for set of files in a specific directory. Since the "--no-utf8-convert" flag is used, the album file should use UTF-8 for any non-ASCII character. Each line represents a tag, and if a line is prefixed with a number and colon, the tag will only be applied for that track number. The script expects to find files that start with the track number and a dash to identify which files to tag in the directory.

Here is an example of a album template file:

ALBUM=Foo
DATE=2001
GENRE=Rock
01:TRACKNUMBER=1
01:ARTIST=Bar
01:TITLE=Baz
02:TRACKNUMBER=2
02:ARTIST=Bar
02:TITLE=Baaaaz
          


Here is the Python script itself:

#!/usr/bin/python

import re
import os

class FLACTagger(object):
    def __init__(self, flac_directory, album_file, cover_image):
        self._flac_directory = flac_directory
        self._album_file = album_file
        self._cover_image = cover_image
        self._global_tags = list()
        self._track_tags = dict()

    def read_album_file(self):
        fh = open(self._album_file, "r")
        for line in fh:
            match = re.match(r"^(\d+):(\w+=.*)$", line)
            if match:
                if not match.group(1) in self._track_tags:
                    self._track_tags[match.group(1)] = list()
                self._track_tags[match.group(1)].append(match.group(2))

            match = re.match(r"^(\w+=.*)$", line)
            if match:
                self._global_tags.append(match.group(1))

        fh.close()

    def make_flactags_files(self):
        for track_no in self._track_tags.keys():
            fh = open("/tmp/%s.flactags" % (track_no), "w")
            for tags in self._global_tags:
                fh.write(tags)
                fh.write("\n")
            for tags in self._track_tags[track_no]:
                fh.write(tags)
                fh.write("\n")
            fh.close()

    def _quote(self, filename):
        return "'" + filename.replace("'", "'\\''") + "'"

    def apply_tags(self):
        for filename in os.listdir(self._flac_directory):
            match = re.match(r"^(\d+) - ", filename)
            full_path = self._quote(self._flac_directory + "/" + filename)
            if match:
                print full_path
                os.system("metaflac --remove-all %s" % (full_path))
                os.system("metaflac --no-utf8-convert --import-tags-from=/tmp/%s.flactags %s" % (match.group(1), full_path))
                os.system("metaflac --import-picture-from=%s %s" % (self._quote(self._cover_image), full_path))



if __name__ == "__main__":
    import sys

    if len(sys.argv) < 4:
        print "Usage: %s <FLAC directory> <album file> <cover image>" % (sys.argv[0])
        sys.exit(1)
    
    if not os.path.isdir(sys.argv[1]):
        print "Error: Invalid file directory"
        sys.exit(1)

    if not os.path.isfile(sys.argv[2]):
        print "Error: Invalid album file"
        sys.exit(1)

    if not os.path.isfile(sys.argv[3]):
        print "Error: Invalid cover image"
        sys.exit(1)

    ftm = FLACTagger(sys.argv[1], sys.argv[2], sys.argv[3])
    ftm.read_album_file()
    ftm.make_flactags_files()
    ftm.apply_tags()
          


Topic: Scripts and Code, by Kjetil @ 01/08-2014, Article Link