format render_utils

This commit is contained in:
j 2026-01-06 15:17:28 +01:00
commit b30fa00841

View file

@ -3,12 +3,12 @@ import os
import lxml.etree import lxml.etree
from .render_kdenlive melt_xml, get_melt from .render_kdenlive import melt_xml
def parse_lang(lang): def parse_lang(lang):
if lang and "," in lang: if lang and "," in lang:
lang = lang.split(',') lang = lang.split(",")
if isinstance(lang, list): if isinstance(lang, list):
tlang = lang[1:] tlang = lang[1:]
lang = lang[0] lang = lang[0]
@ -18,9 +18,10 @@ def parse_lang(lang):
lang = None lang = None
return lang, tlang return lang, tlang
def random_int(seq, length): def random_int(seq, length):
n = n_ = length - 1 n = n_ = length - 1
#print('len', n) # print('len', n)
if n == 0: if n == 0:
return n return n
r = seq() / 9 * 10 r = seq() / 9 * 10
@ -32,19 +33,22 @@ def random_int(seq, length):
r = int(round(n_ * r / base)) r = int(round(n_ * r / base))
return r return r
def random_choice(seq, items, pop=False): def random_choice(seq, items, pop=False):
n = random_int(seq, len(items)) n = random_int(seq, len(items))
if pop: if pop:
return items.pop(n) return items.pop(n)
return items[n] return items[n]
def chance(seq, chance): def chance(seq, chance):
return (seq() / 10) < chance return (seq() / 10) < chance
def get_clip_by_seqid(clips, seqid): def get_clip_by_seqid(clips, seqid):
selected = None selected = None
for i, clip in enumerate(clips): for i, clip in enumerate(clips):
if clip['seqid'] == seqid: if clip["seqid"] == seqid:
selected = i selected = i
break break
if selected is not None: if selected is not None:
@ -60,7 +64,7 @@ def get_scene_duration(scene):
for key, value in scene.items(): for key, value in scene.items():
for name, clips in value.items(): for name, clips in value.items():
for clip in clips: for clip in clips:
duration += int(clip['duration'] * 24) duration += int(clip["duration"] * 24)
return duration / 24 return duration / 24
@ -68,7 +72,7 @@ def get_offset_duration(prefix):
duration = 0 duration = 0
for root, folders, files in os.walk(prefix): for root, folders, files in os.walk(prefix):
for f in files: for f in files:
if f == 'scene.json': if f == "scene.json":
duration += get_scene_duration(scene) duration += get_scene_duration(scene)
return duration return duration
@ -80,41 +84,45 @@ def get_track_duration(scene, k, n):
for name, clips in value.items(): for name, clips in value.items():
if name == n: if name == n:
for clip in clips: for clip in clips:
duration += int(clip['duration'] * 24) duration += int(clip["duration"] * 24)
return duration / 24 return duration / 24
def get_project_duration(file): def get_project_duration(file):
out = melt_xml(file) out = melt_xml(file)
chain = lxml.etree.fromstring(out).xpath('producer')[0] chain = lxml.etree.fromstring(out).xpath("producer")[0]
duration = int(chain.attrib['out']) + 1 duration = int(chain.attrib["out"]) + 1
return duration return duration
def fix_overlaps(data): def fix_overlaps(data):
previous = None previous = None
for sub in data: for sub in data:
if previous is None: if previous is None:
previous = sub previous = sub
else: else:
if sub['in'] < previous['out']: if sub["in"] < previous["out"]:
previous['out'] = sub['in'] - 0.001 previous["out"] = sub["in"] - 0.001
previous = sub previous = sub
return data return data
def shift_clips(data, offset): def shift_clips(data, offset):
for clip in data: for clip in data:
clip['in'] += offset clip["in"] += offset
clip['out'] += offset clip["out"] += offset
return data return data
def ass_encode(subs, options): def ass_encode(subs, options):
if "lang" in options: if "lang" in options:
langs = options["lang"].split(',') langs = options["lang"].split(",")
else: else:
langs = list(subs[0]["values"]) langs = list(subs[0]["values"])
#print('ass_encode', langs, options) # print('ass_encode', langs, options)
#print(subs) # print(subs)
header = '''[Script Info] header = """[Script Info]
ScriptType: v4.00+ ScriptType: v4.00+
PlayResX: 1920 PlayResX: 1920
PlayResY: 1080 PlayResY: 1080
@ -123,7 +131,7 @@ YCbCr Matrix: None
[V4+ Styles] [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 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 ass = header
offset = options.get("sub_margin", 10) offset = options.get("sub_margin", 10)
spacing = options.get("sub_spacing", 20) spacing = options.get("sub_spacing", 20)
@ -133,27 +141,26 @@ Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour,
if isinstance(options.get("font"), list) and lang in options["font"]: if isinstance(options.get("font"), list) and lang in options["font"]:
font = options["font"][lang] font = options["font"][lang]
else: else:
font = 'SimHei' if lang in ('zh', 'jp') else 'Menlo' font = "SimHei" if lang in ("zh", "jp") else "Menlo"
if isinstance(options.get("font_size"), list) and lang in options["font_size"]: if isinstance(options.get("font_size"), list) and lang in options["font_size"]:
size = options["font_size"][lang] size = options["font_size"][lang]
else: else:
size = 46 if font == 'SimHei' else 42 size = 46 if font == "SimHei" else 42
styles.append( 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' 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 offset += size + spacing
ass += '\n'.join(reversed(styles)) + '\n' ass += "\n".join(reversed(styles)) + "\n"
events = [ events = [
'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text' "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text"
] ]
for sub in subs: for sub in subs:
start = ox.format_timecode(sub['in']).rstrip('0') start = ox.format_timecode(sub["in"]).rstrip("0")
stop = ox.format_timecode(sub['out']).rstrip('0') stop = ox.format_timecode(sub["out"]).rstrip("0")
for lang in reversed(langs): for lang in reversed(langs):
value = sub['values'][lang] value = sub["values"][lang]
event = f'Dialogue: 0,{start},{stop},{lang},,0,0,0,,{value}' event = f"Dialogue: 0,{start},{stop},{lang},,0,0,0,,{value}"
events.append(event) events.append(event)
ass += '\n\n[Events]\n' + '\n'.join(events) + '\n' ass += "\n\n[Events]\n" + "\n".join(events) + "\n"
return ass return ass