import json import os import re from collections import defaultdict from django.core.management.base import BaseCommand from django.conf import settings import item.models import itemlist.models def resolve_roman(s): extra = re.compile('^\d+(.*?)$').findall(s) if extra: extra = extra[0].lower() new = { 'i': '1', 'ii': '2', 'iii': '3', 'iv': '4', 'v': '5', 'vi': '6', 'vii': 7, 'viii': '8', 'ix': '9', 'x': '10' }.get(extra, extra) return s.replace(extra, new) return s class Command(BaseCommand): help = 'generate symlinks to clips and clips.json' def add_arguments(self, parser): parser.add_argument('--prefix', action='store', dest='prefix', default="/srv/t_for_time", help='prefix to build clips in') def handle(self, **options): prefix = options['prefix'] clips = [] for i in item.models.Item.objects.filter(sort__type='original'): qs = item.models.Item.objects.filter(data__title=i.data['title']).exclude(id=i.id) if qs.count() >= 1: clip = {} durations = [] for e in item.models.Item.objects.filter(data__title=i.data['title']): if 'type' not in e.data: print("ignoring invalid video %s (no type)" % e) continue if not e.files.filter(selected=True).exists(): continue source = e.files.filter(selected=True)[0].data.path ext = os.path.splitext(source)[1] type_ = e.data['type'][0].lower() target = os.path.join(prefix, type_, i.data['title'] + ext) os.makedirs(os.path.dirname(target), exist_ok=True) if os.path.islink(target): os.unlink(target) os.symlink(source, target) clip[type_] = target durations.append(e.files.filter(selected=True)[0].duration) clip["duration"] = min(durations) if not clip["duration"]: print('!!', durations, clip) continue clip['tags'] = i.data.get('tags', []) clip['editingtags'] = i.data.get('editingtags', []) name = os.path.basename(clip['original']) seqid = re.sub("Hotel Aporia_(\d+)", "S\\1_", name) seqid = re.sub("Night March_(\d+)", "S\\1_", seqid) seqid = re.sub("_(\d+)H_(\d+)", "_S\\1\\2_", seqid) seqid = seqid.split('_')[:2] seqid = [b[1:] if b[0] in ('B', 'S') else '0' for b in seqid] seqid[1] = resolve_roman(seqid[1]) seqid[1] = ''.join([b for b in seqid[1] if b.isdigit()]) if not seqid[1]: seqid[1] = '0' try: clip['seqid'] = int(''.join(['%06d' % int(b) for b in seqid])) except: print(name, seqid, 'failed') raise if "original" in clip and "foreground" in clip and "background" in clip: clips.append(clip) elif "original" in clip and "animation" in clip: clips.append(clip) else: print("ignoring incomplete video", i) with open(os.path.join(prefix, 'clips.json'), 'w') as fd: json.dump(clips, fd, indent=2, ensure_ascii=False) print("using", len(clips), "clips") voice_over = defaultdict(dict) for vo in item.models.Item.objects.filter( data__type__contains="Voice Over", ): fragment_id = int(vo.get('title').split('_')[0]) source = vo.files.filter(selected=True)[0] batch = vo.get('batch')[0].replace('Text-', '') src = source.data.path target = os.path.join(prefix, 'voice_over', batch, '%s.wav' % fragment_id) os.makedirs(os.path.dirname(target), exist_ok=True) if os.path.islink(target): os.unlink(target) os.symlink(src, target) subs = [] for sub in vo.annotations.filter(layer="subtitles").exclude(value="").order_by("start"): sdata = sub.json(keys=['in', 'out', 'value']) sdata['value'] = sdata['value'].replace('
', '
').replace('
\n', '\n').replace('
', '\n') subs.append(sdata) voice_over[fragment_id][batch] = { "src": target, "duration": source.duration, "subs": subs } with open(os.path.join(prefix, 'voice_over.json'), 'w') as fd: json.dump(voice_over, fd, indent=2, ensure_ascii=False)