-
Notifications
You must be signed in to change notification settings - Fork 1
/
adt
executable file
·114 lines (90 loc) · 4.08 KB
/
adt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#! /usr/bin/env python3
import argparse
import os
import io
import shutil
from PIL import Image
from mutagen.id3 import ID3, TRCK, TDRC, TIT2, TALB, TPE1, TPOS, TCON, TCOM, TPOS, TCOP, COMM, TXXX, APIC
from mutagen.aiff import AIFF
from yaml import load, dump
try:
from yaml import CLoader as Loader, CDumper as Dumper
except ImportError:
from yaml import Loader, Dumper
def get_args():
class ValidateConfigFilename(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
if not values.endswith(".yml") and not values.endswith(".yaml"):
raise ValueError("input must be an .yml or .yaml")
setattr(namespace, self.dest, values)
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('-c', "--config", type=str, required=True, action=ValidateConfigFilename, help='process based on yaml config file')
parser.add_argument('-o', "--output", type=str, default="./", help='location to copy audio files to')
parser.add_argument('-r', "--resize", type=int, help='pixels (width/height) to resize input image before adding to metadata. For CDJ2000NX, the maximum resolution is 800x800. If left blank, original image will be used')
parser.add_argument('-f', "--force", action="store_true", help='forces overwrite of tags')
parser.add_argument('-v', "--verbose", action="store_true", help='print metadata tags (except cover image)')
return parser.parse_args()
def add_tags(audio, info, album_art, force=False):
if audio.tags and not force:
raise ValueError("tags already exist and force option is not set to true")
if audio.tags:
audio.tags = None
audio.add_tags()
audio.tags.add(TRCK(encoding=3, text=info['track']))
audio.tags.add(TDRC(encoding=3, text=info['year']))
audio.tags.add(TIT2(encoding=3, text=info['title']))
audio.tags.add(TALB(encoding=3, text=info['album name']))
audio.tags.add(TPE1(encoding=3, text=info['artist name']))
audio.tags.add(TPOS(encoding=3, text=info['serial number']))
audio.tags.add(TCON(encoding=3, text=info['genre']))
audio.tags.add(TCOM(encoding=3, text=info['composer']))
audio.tags.add(TCOP(encoding=3, text=info['copyright']))
audio.tags.add(TXXX(encoding=3, desc=u'CATALOGNUMBER', text=info['catalog number']))
audio.tags.add(COMM(encoding=3, desc=u'eng', text=info['comment']))
audio.tags.add(APIC(
encoding=3,
mime='image/jpeg',
type=3,
desc=u'Cover',
data=album_art
))
audio.save()
def print_tags(audio):
for key in audio.tags.keys():
if "APIC" in key:
continue
print(key, audio.tags[key])
if __name__ == '__main__':
try:
args = get_args()
except Exception as e:
print(e)
exit()
with open(args.config, 'r') as stream:
config = load(stream, Loader=Loader)
img = Image.open(config["all"]['cover art']).convert('RGB')
if args.resize:
img = img.resize((args.resize, args.resize))
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format='JPEG')
album_art = img_byte_arr.getvalue()
for track_index in config["tracks"]:
info = config["all"].copy()
info["track"] = track_index
track_data = config["tracks"][track_index]
file = track_data.pop('file', None)
info.update(track_data)
os.makedirs(args.output, exist_ok=True)
output_file = f"{info['catalog number']}_{track_index:02}_{info['artist name']}_-_{info['title']}.aiff"
output_file = output_file.replace(" ", "_")
output_file = os.path.join(args.output, output_file)
shutil.copy2(file, output_file)
info = {k: str(v).encode("utf-8").decode('utf-8') for k,v in info.items()}
audio = AIFF(output_file, v2_version=3)
try:
add_tags(audio, info, album_art, force=args.force)
except Exception as e:
print(e)
exit()
if(args.verbose):
print_tags(audio)