From 89dad20377ad40cb901bec1cd37d3db7ebc26331 Mon Sep 17 00:00:00 2001 From: Gael Le Mignot Date: Thu, 28 Apr 2022 11:09:44 +0200 Subject: [PATCH] Fixed parsing of 6.24.0 files --- telemeta/util/kdenlive/session.py | 97 ++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 34 deletions(-) diff --git a/telemeta/util/kdenlive/session.py b/telemeta/util/kdenlive/session.py index d9ed7eb0..a10a0f10 100644 --- a/telemeta/util/kdenlive/session.py +++ b/telemeta/util/kdenlive/session.py @@ -35,21 +35,23 @@ import time from telemeta.util.xmltodict2 import * +import json -def parse_timestamp(value): +def parse_timecode(value, fps): """ - Parse a timestamp, either new HH:MM:SS.mmm format or old seconds format + Parse a timestamp, either new HH:MM:SS.mmm format or old frames format """ if ':' in value: if '.' in value: - value = value.split('.')[0] + value, decimal = value.split('.') comps = value.split(':') comps = [ int(c) for c in comps ] res = 0 for comp in comps: res = res * 60 + comp + res += float(decimal) / 10**len(decimal) else: - res = int(value) + res = float(value) / fps return res @@ -80,18 +82,21 @@ class KDEnLiveSession(object): def entries_sorted(self): return sorted(self.entries(), key=lambda k: int(k['in']), reverse=False) - def entries_video_seconds(self): + def get_fps(self): profile = self.profile() fps = float(profile['frame_rate_num'])/float(profile['frame_rate_den']) - #fps= 25 + return fps + + def entries_video_seconds(self): + fps = self.get_fps() res = [] start = 0 entries = self.video_entries() for entry in entries: id = entry['producer'].split('_')[0] - t_in = parse_timestamp(entry['in'])/fps - t_out = parse_timestamp(entry['out'])/fps + t_in = parse_timecode(entry['in'], fps) + t_out = parse_timecode(entry['out'], fps) t_len = t_out - t_in end = start + t_len res.append({ 'id': str(id), 't': start, 'in': t_in, 'out': t_out }) @@ -132,17 +137,40 @@ class KDEnLiveSession(object): offset: general origin offset """ - - abs_time = 0 markers = [] - i = 0 entries = self.entries_video_seconds() title = '' + fps = self.get_fps() + + def add_marker(rel_time, comment): + """ + Add a marker to the list from it's id, timestamp and comment + """ + marker = {} + marker['time'] = rel_time + marker['session_timecode'] = time.strftime('%H:%M:%S', time.gmtime(rel_time)) + if ":" in comment: + pre, post = comment.split(':', 1) + if pre.isdigit(): + comment = post + marker['comment'] = comment + markers.append(marker) + + def get_reltime(entry_id, marker_time): + """ + Get the relative time of a marker linked to an entry + """ + rel_time = 0 + + for entry in entries: + if entry['in'] <= marker_time <= entry['out'] and entry_id == entry['id']: + rel_time = entry['t'] + (marker_time - entry['in']) + offset + return rel_time for attr in self.session['children']: if 'playlist' in attr['name'] and 'children' in attr: + # Old v 6.4 file format, markers in playlist for att in attr['children']: - marker = {} if 'name' in att['attributes']: name = att['attributes']['name'] if 'docmetadata.meta.attr.title.markup' in name: @@ -150,28 +178,29 @@ class KDEnLiveSession(object): if 'marker' in name: name = name.encode('utf8') marker_time = float(name.split(':')[-1].replace(',','.').replace(' ', '')) - id = str(name.split(':')[-2].split('.')[-1]) - rel_time = 0 - - for entry in entries: - if entry['in'] <= marker_time <= entry['out'] and id == entry['id']: - if i == 0 and from_first_marker: - abs_time = entry['t'] - rel_time = entry['t'] + (marker_time - entry['in']) - abs_time + offset - break - else: - continue - - marker['time'] = rel_time - marker['session_timecode'] = time.strftime('%H:%M:%S', time.gmtime(rel_time)) + entry_id = str(name.split(':')[-2].split('.')[-1]) comment = self.fix_text(att['cdata']) - if ":" in comment: - pre, post = comment.split(':', 1) - if pre.isdigit(): - comment = post - marker['comment'] = comment - markers.append(marker) - - i += 1 + rel_time = get_reltime(entry_id, marker_time) + if rel_time is not None: + add_marker(rel_time, comment) + elif 'producer' in attr['name'] and 'children' in attr: + # New v 6.24 file format, markers in producers + if "id" in attr['attributes']: + entry_id = attr['attributes']['id'] + for att in attr['children']: + name = att['attributes']['name'] + if 'markers' in name: + items = json.loads(self.fix_text(att['cdata'])) + for marker in items: + marker_time = float(marker['pos'] / fps) + rel_time = get_reltime(entry_id, marker_time) + if rel_time is not None: + add_marker(rel_time, marker['comment']) + + + if markers and from_first_marker: + delta = min([ marker['time'] for marker in markers ]) + for marker in markers: + marker['time'] -= delta return title, markers -- 2.39.5