123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- import mutagen
- import mutagen.id3
- import mutagen.mp4
- 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), type(id3_tags)
- 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(path):
- if os.path.isdir(path):
- for dirpath, dirnames, filenames in os.walk(path):
- for filename in filenames:
- symuid(os.path.join(dirpath, filename))
- else:
- try:
- f = mutagen.File(filename=path)
- except Exception:
- raise Exception(path)
- if not f:
- print("{!r}: unsupported filetype, ignored".format(path))
- elif isinstance(f.tags, mutagen.mp4.MP4Tags):
- print("{!r}: mp4 tags not supported, ignored".format(path))
- else:
- get_or_assign_uuid(f.tags)
- def _init_argparser():
- import argparse
- argparser = argparse.ArgumentParser(description=None)
- argparser.add_argument('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))
|