#!/usr/bin/python3 import os import json import math import ox import ox.web.auth base_url = 'https://0xdb.org' credentials = ox.web.auth.get('0xdb.org') prefix = '/Cinema' if os.path.exists('files.json'): files = json.load(open('files.json')) else: files = {} def get_info(api, oshash): if oshash not in files: r = api.findMedia({ 'query': { 'conditions': [{'key': 'oshash', 'value': oshash}] }, 'keys': ['id', 'instances', 'resolution'] })['data'] if not r['items'][0]['instances']: print(r) raise Exception('item without instance') files[oshash] = { 'path': os.path.join(prefix, r['items'][0]['instances'][0]['path']), 'resolution': r['items'][0]['resolution'] } return files[oshash] def normalize(name): return name.replace(':', '_').replace('/', '_') def sort_clips(edit, sort): clips = edit['clips'] reverse = sort.startswith('-') last = '' if reverse else 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' sort = sort.lstrip('-') if sort == 'manual': s = clips if reverse: s = reversed(s) elif sort in [ 'id', 'index', 'in', 'out', 'duration', 'title', 'director', 'year', 'videoRatio' ]: s = sorted(clips, key=lambda c: (str(c.get(sort, last)), c['title'], c['in'], c['out'])) if reverse: s = reversed(s) else: ids = api.sortClips({ 'edit': edit['id'], 'sort': [{'key': sort, 'operator': '-' if reverse else '+'}] })['data']['clips'] print(set(c['id'] for c in clips) - set(ids)) print(set(ids) - set(c['id'] for c in clips)) s = sorted(clips, key=lambda c: ids.index(c['id']) if c['id'] in ids else -1) return s if __name__ == '__main__': import sys edit_id = sys.argv[1] if len(sys.argv) > 2: sort_by = sys.argv[2] else: sort_by = 'year' api = ox.API(base_url + '/api/') api.signin(**credentials) edit = api.getEdit(id=edit_id)['data'] videos = [] subtitles = [] position = 0 for clip in sort_clips(edit, sort_by): clip_subtitles = [] for sub in clip['layers']['subtitles']: subtitles.append({ 'in': position, 'out': position + (sub['out'] - sub['in']), 'value': sub['value'].replace('
', '\n').replace('
', '\n').replace('\n\n', '\n'), }) clip_subtitles.append(sub['value'].replace('
', '\n').replace('
', '\n').replace('\n\n', '\n')) part_pos = 0 for i, duration in enumerate(clip['durations']): if part_pos + duration < clip['in']: part_pos += duration elif part_pos <= clip['in']: stream_in = clip['in'] - part_pos stream_out = min(clip['out'] - part_pos, duration) stream_in = math.ceil(stream_in / (1/25)) * 1/25 stream_out = math.ceil(stream_out / (1/25)) * 1/25 part_pos += duration info = get_info(api, clip['streams'][i]) videos.append({ 'oshash': clip['streams'][i], 'path': os.path.join(prefix, info['path']), 'resolution': info['resolution'], 'in': stream_in, 'out': stream_out, 'subtitles': '\n'.join(clip_subtitles) }) elif clip['out'] > part_pos: stream_in = part_pos stream_out = min(clip['out'] - part_pos, duration) stream_in = math.ceil(stream_in / (1/25)) * 1/25 stream_out = math.ceil(stream_out / (1/25)) * 1/25 part_pos += duration info = get_info(api, clip['streams'][i]) videos.append({ 'oshash': clip['streams'][i], 'path': info['path'], 'resolution': info['resolution'], 'in': stream_in, 'out': stream_out, 'subtitles': '\n'.join(clip_subtitles) }) position += clip['duration'] position = math.ceil(position / (1/25)) * 1/25 name = normalize(edit_id) if sort_by != 'year': name += '_' + sort_by with open('%s.srt' % name, 'wb') as fd: fd.write(ox.srt.encode(subtitles)) with open('%s.json' % name, 'w') as fd: json.dump(videos, fd, indent=4, ensure_ascii=False) with open('files.json', 'w') as fd: json.dump(files, fd, indent=4, ensure_ascii=False)