|
@@ -0,0 +1,58 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
+
|
|
|
+import mutagen
|
|
|
+import mutagen.id3
|
|
|
+import os
|
|
|
+import subprocess
|
|
|
+
|
|
|
+# http://id3.org/id3v2.4.0-frames#4.1.
|
|
|
+TRACK_UUID_ID3_OWNER_ID = 'symuid'
|
|
|
+
|
|
|
+# TODO http://mutagen.readthedocs.io/en/latest/api/mp4.html
|
|
|
+
|
|
|
+def generate_uuid():
|
|
|
+ return subprocess.check_output(['uuid', '-v', '4', '-F', 'BIN']).strip()
|
|
|
+
|
|
|
+def get_uuid(id3_tags):
|
|
|
+ assert isinstance(id3_tags, mutagen.id3.ID3)
|
|
|
+ ufids = id3_tags.getall('UFID')
|
|
|
+ for ufid in ufids:
|
|
|
+ if ufid.owner == TRACK_UUID_ID3_OWNER_ID:
|
|
|
+ return ufid.data
|
|
|
+ return None
|
|
|
+
|
|
|
+def get_or_assign_uuid(id3_tags):
|
|
|
+ uuid = get_uuid(id3_tags)
|
|
|
+ if uuid is None:
|
|
|
+ # mutagen.id3._specs.EncodedTextSpec.write encodes 'owner'
|
|
|
+ id3_tags.add(mutagen.id3.UFID(
|
|
|
+ owner=TRACK_UUID_ID3_OWNER_ID,
|
|
|
+ data=generate_uuid(),
|
|
|
+ ))
|
|
|
+ id3_tags.save()
|
|
|
+ id3_tags.load(filename=id3_tags.filename)
|
|
|
+ uuid = get_uuid(id3_tags)
|
|
|
+ print("{!r}: assigned uuid {!r}".format(id3_tags.filename, uuid))
|
|
|
+ assert uuid is not None
|
|
|
+ return uuid
|
|
|
+
|
|
|
+def symuid(track_path):
|
|
|
+ f = mutagen.File(filename=track_path)
|
|
|
+ print(get_or_assign_uuid(f.tags))
|
|
|
+
|
|
|
+def _init_argparser():
|
|
|
+ import argparse
|
|
|
+ argparser = argparse.ArgumentParser(description=None)
|
|
|
+ argparser.add_argument('track_path')
|
|
|
+ return argparser
|
|
|
+
|
|
|
+def main(argv):
|
|
|
+ argparser = _init_argparser()
|
|
|
+ args = argparser.parse_args(argv[1:])
|
|
|
+ symuid(**vars(args))
|
|
|
+ return 0
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ import sys
|
|
|
+ sys.exit(main(sys.argv))
|