171 lines
5.1 KiB
Python
Executable File
171 lines
5.1 KiB
Python
Executable File
#!/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
|