#!/usr/bin/env python from __future__ import division import json import os from optparse import OptionParser from urlparse import urlparse import sys import ox base = os.path.abspath(os.path.dirname(__file__)) formats = ['fcp', 'fcpx', 'kdenlive', 'm3u', 'pitivi'] formats = ['fcp', 'm3u'] usage = "usage: %prog [options] edit_url > result.xml" parser = OptionParser(usage=usage) parser.add_option('-b', '--base', dest='base', help='base path', default=base, type='string') parser.add_option('-c', '--cache', dest='cache', help='cache api requests', default='', type='string') parser.add_option('-f', '--format', dest='format', help='output format: %s' % (', '.join(formats)), default='fcp', type='string') parser.add_option('-p', '--prores', dest='prores', help='use prores proxies', action="store_true") (opts, args) = parser.parse_args() if not args: parser.print_help() sys.exit(1) if opts.format not in formats: sys.stderr.write('Format "%s" unsupported, please provide supported format: %s\n' % (opts.format, ', '.join(formats))) sys.exit(1) elif opts.format == 'fcp': from edl.fcp import Project elif opts.format == 'fcpx': from edl.fcpx import Project elif opts.format == 'm3u': from edl.m3u import Project elif opts.format == 'pitivi': from edl.pitivi import Project elif opts.format == 'kdenlive': from edl.pitivi import Project u = urlparse(args[0]) base_url = '%s://%s/' % (u.scheme, u.netloc) api = ox.API('%sapi/'%base_url) edit_id = args[0].split('/')[-1].replace('_', ' ') prores = opts.prores prores_prefix = 'prores' base = opts.base if not base.endswith('/'): base += '/' edit = None files = {} if opts.cache: files_json = os.path.join(opts.cache, 'files.json') edit_json = os.path.join(opts.cache, 'edit.json') if os.path.exists(edit_json): with open(edit_json) as fd: edit = json.load(fd) if os.path.exists(files_json): with open(files_json) as fd: files = json.load(fd) if not edit: edit = api.getEdit(id=edit_id)['data'] if opts.cache: with open(edit_json, 'w') as fd: json.dump(edit, fd, indent=2) update = False for c in edit['clips']: item = c['item'] if 'item' in c else c['annotatoin'].split('/')[0] if item not in files: r = api.findMedia({ 'query': { 'conditions': [{ 'key': 'id', 'value': item, 'operator': '==' }], 'operator': '&' }, 'keys': [ 'id', "selected", "type", "duration", 'instances', 'path', 'resolution', 'samplerate', 'channels' ], 'range': [0, 100] }) item_files = r['data']['items'] item_files = filter(lambda f: f['type'] == 'video' and f['selected'], item_files) for f in item_files: f['path'] = f['instances'][0]['path'] del f['instances'] files[item] = item_files update = True if update and opts.cache: with open(files_json, 'w') as fd: json.dump(files, fd, indent=2) clips = [] for clip in edit['clips']: item = clip['item'] if 'item' in clip else clip['annotation'].split('/')[0] position = 0 for part, f in enumerate(files[item]): if clip['in'] < position + f['duration']: clip_in = clip['in'] - position clip_out = clip['out'] - position c = clip.copy() c['in'] = clip_in c['out'] = clip_out if c['out'] > f['duration']: more_clips = True position += f['duration'] clip['in'] = position c['out'] = f['duration'] else: more_clips = False c['duration'] = c['out'] - c['in'] c['oshash'] = f['id'] path = f['path'] name = os.path.dirname(path).split('/')[-1] ext = path.split('.')[-1] if prores: #fixme, custom hack # FCP fails to open video with 'invalid video' # error if file has more than one , (comma) in name if name.startswith('001'): name = name.replace(',', '') ext = 'mov' path = os.path.join(prores_prefix, '%s.%s' % (name, ext)) def format_time(t): t = ox.format_duration(t * 1000) if t.endswith('.000'): t = t[:-4] return t c['url'] = '%s%s/editor/%s,%s' % ( base_url, item, format_time(c['in']), format_time(c['out']) ) c['path'] = path c['width'] = f['resolution'][0] c['file_duration'] = f['duration'] c['height'] = f['resolution'][1] c['samplerate'] = f['samplerate'] c['channels'] = f.get('channels', 2) clips.append(c) if not more_clips: break else: position += f['duration'] edit = Project(clips, base) edit.width = 1280 edit.height = 720 print edit