From 5103e8f81b97852beb4be344f729f0549828ece8 Mon Sep 17 00:00:00 2001 From: j Date: Thu, 16 Nov 2023 09:08:03 +0100 Subject: [PATCH] update subtitles --- management/commands/update_subtitles.py | 20 +++++++ render.py | 70 ++++++++++++++++++++++--- 2 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 management/commands/update_subtitles.py diff --git a/management/commands/update_subtitles.py b/management/commands/update_subtitles.py new file mode 100644 index 0000000..2ca2511 --- /dev/null +++ b/management/commands/update_subtitles.py @@ -0,0 +1,20 @@ +import json +import os +import subprocess + +from django.core.management.base import BaseCommand +from django.conf import settings + +from ...render import update_subtitles + + +class Command(BaseCommand): + help = 'genrate kdenlive porject and render' + + def add_arguments(self, parser): + parser.add_argument('--prefix', action='store', dest='prefix', default="/srv/t_for_time", help='prefix to build clips in') + parser.add_argument('--duration', action='store', dest='duration', default="3600", help='target duration of all fragments in seconds') + parser.add_argument('--offset', action='store', dest='offset', default="1024", help='inital offset in pi') + + def handle(self, **options): + update_subtitles(options) diff --git a/render.py b/render.py index bdaaf2c..d7c60bd 100644 --- a/render.py +++ b/render.py @@ -2,10 +2,11 @@ from collections import defaultdict import json import os +import re +import shutil import subprocess import sys import time -import shutil from pathlib import Path import ox @@ -46,6 +47,23 @@ def get_clip_by_seqid(clips, seqid): return clips.pop(i) return None + +def write_if_new(path, data, mode=''): + read_mode = 'r' + mode + write_mode = 'w' + mode + if os.path.exists(path): + with open(path, read_mode) as fd: + old = fd.read() + else: + old = "" + is_new = data != old + if path.endswith(".kdenlive"): + is_new = re.sub('\{.{36}\}', '', data) != re.sub('\{.{36}\}', '', old) + if is_new: + with open(path, write_mode) as fd: + fd.write(data) + + def compose(clips, target=150, base=1024, voice_over=None): length = 0 scene = { @@ -282,8 +300,9 @@ def render(root, scene, prefix=''): scene_duration = int(get_scene_duration(scene) * 24) for timeline, data in scene.items(): if timeline == "subtitles": - with open(os.path.join(root, prefix + "front.srt"), "wb") as fd: - fd.write(ox.srt.encode(data)) + path = os.path.join(root, prefix + "front.srt") + srt = ox.srt.encode(data) + write_if_new(path, srt, 'b') continue #print(timeline) project = KDEnliveProject(root) @@ -304,8 +323,8 @@ def render(root, scene, prefix=''): project.append_clip(track, {'blank': True, "duration": delta/24}) break path = os.path.join(root, prefix + "%s.kdenlive" % timeline) - with open(path, 'w') as fd: - fd.write(project.to_xml()) + project_xml = project.to_xml() + write_if_new(path, project_xml) files.append(path) return files @@ -410,8 +429,8 @@ def render_all(options): timelines = render(prefix, scene, fragment_prefix[len(prefix) + 1:] + '/') - with open(os.path.join(fragment_prefix, 'scene.json'), 'w') as fd: - json.dump(scene, fd, indent=2, ensure_ascii=False) + scene_json = json.dumps(scene, indent=2, ensure_ascii=False) + write_if_new(os.path.join(fragment_prefix, 'scene.json'), scene_json) if not options['no_video']: for timeline in timelines: @@ -517,3 +536,40 @@ def render_all(options): print(json.dumps(dict(stats), sort_keys=True, indent=2)) with open(_cache, "w") as fd: json.dump(_CACHE, fd) + + +def update_subtitles(options): + import item.models + + prefix = Path(options['prefix']) + duration = int(options['duration']) + base = int(options['offset']) + + _cache = os.path.join(prefix, "cache.json") + if os.path.exists(_cache): + with open(_cache) as fd: + _CACHE.update(json.load(fd)) + + base_prefix = prefix / 'render' / str(base) + for folder in os.listdir(base_prefix): + folder = base_prefix / folder + with open(folder / "scene.json") as fd: + scene = json.load(fd) + offset = 0 + subs = [] + for clip in scene['audio-center']['A1']: + if not clip.get("blank"): + batch, fragment_id = clip['src'].replace('.wav', '').split('/')[-2:] + vo = item.models.Item.objects.filter(data__icontains='2-Whispered', data__title__startswith=fragment_id + '_').first() + if vo: + 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') + sdata["in"] += offset + sdata["out"] += offset + subs.append(sdata) + offset += clip['duration'] + path = folder / "front.srt" + srt = ox.srt.encode(subs) + write_if_new(str(path), srt, 'b') +