pandora_cut/pandora_cut.py

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