import re import os import lxml.etree from .render_kdenlive import melt_xml def parse_lang(lang): if lang and "," in lang: lang = lang.split(',') if isinstance(lang, list): tlang = lang[1:] lang = lang[0] else: tlang = None if lang == "en": lang = None return lang, tlang def random_int(seq, length): n = n_ = length - 1 #print('len', n) if n == 0: return n r = seq() / 9 * 10 base = 10 while n > 10: n /= 10 r += seq() / 9 * 10 base += 10 r = int(round(n_ * r / base)) return r def random_choice(seq, items, pop=False): n = random_int(seq, len(items)) if pop: return items.pop(n) return items[n] def chance(seq, chance): return (seq() / 10) < chance def get_clip_by_seqid(clips, seqid): selected = None for i, clip in enumerate(clips): if clip['seqid'] == seqid: selected = i break if selected is not None: return clips.pop(i) return None def get_scene_duration(scene): if isinstance(scene, str): with open(scene) as fd: scene = json.load(fd) duration = 0 for key, value in scene.items(): for name, clips in value.items(): for clip in clips: duration += int(clip['duration'] * 24) return duration / 24 def get_offset_duration(prefix): duration = 0 for root, folders, files in os.walk(prefix): for f in files: if f == 'scene.json': duration += get_scene_duration(scene) return duration def get_track_duration(scene, k, n): duration = 0 for key, value in scene.items(): if key == k: for name, clips in value.items(): if name == n: for clip in clips: duration += int(clip['duration'] * 24) return duration / 24 def get_project_duration(file): out = melt_xml(file) chain = lxml.etree.fromstring(out).xpath('producer')[0] duration = int(chain.attrib['out']) + 1 return duration def fix_overlaps(data): previous = None for sub in data: if previous is None: previous = sub else: if sub['in'] < previous['out']: previous['out'] = sub['in'] - 0.001 previous = sub return data def shift_clips(data, offset): for clip in data: clip['in'] += offset clip['out'] += offset return data def ass_encode(subs, options): if "lang" in options: langs = options["lang"].split(',') else: langs = list(subs[0]["values"]) #print('ass_encode', langs, options) #print(subs) header = '''[Script Info] ScriptType: v4.00+ PlayResX: 1920 PlayResY: 1080 ScaledBorderAndShadow: yes YCbCr Matrix: None [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding ''' ass = header offset = options.get("sub_margin", 10) spacing = options.get("sub_spacing", 20) height = 42 styles = [] for lang in reversed(langs): if isinstance(options.get("font"), list) and lang in options["font"]: font = options["font"][lang] else: font = 'SimHei' if lang in ('zh', 'jp') else 'Menlo' if isinstance(options.get("font_size"), list) and lang in options["font_size"]: size = options["font_size"][lang] else: size = 46 if font == 'SimHei' else 42 styles.append( f'Style: {lang},{font},{size},&Hffffff,&Hffffff,&H0,&H0,0,0,0,0,100,100,0,0,1,1,0,2,10,10,{offset},1' ) offset += size + spacing ass += '\n'.join(reversed(styles)) + '\n' events = [ 'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text' ] for sub in subs: start = ox.format_timecode(sub['in']).rstrip('0') stop = ox.format_timecode(sub['out']).rstrip('0') for lang in reversed(langs): value = sub['values'][lang] event = f'Dialogue: 0,{start},{stop},{lang},,0,0,0,,{value}' events.append(event) ass += '\n\n[Events]\n' + '\n'.join(events) + '\n' return ass