pandora_cdosea/render.py
2017-01-04 18:26:18 +01:00

197 lines
5.3 KiB
Python
Executable file

#!/usr/bin/python3
import os
import json
import subprocess
import string
from pi import random
from keywords import KEYWORDS
import ox
import ox.web.auth
base_url = 'https://cdosea.0x2620.org'
api = None
def get_api():
global api
if not api:
api = ox.API(base_url + '/api/')
api.signin(**ox.web.auth.get('cdosea'))
if os.path.exists('PATHS.json'):
PATHS = json.load(open('PATHS.json'))
else:
PATHS = {}
if os.path.exists('CLIPS.json'):
CLIPS = json.load(open('CLIPS.json'))
else:
CLIPS = {}
def get_path(id):
global PATHS
if id not in PATHS:
get_api()
info = api.findMedia({
'query': {
'conditions': [
{'key': 'id', 'operator': '==', 'value': id}
]
},
'keys': ['id', 'extension'],
'range': [0, 1]
})['data']['items'][0]
path = os.path.join('cache', '%s.%s' % (info['id'], info['extension']))
if not os.path.exists(path):
url = '%s/%s/download/source/' % (base_url, id)
print('get video', url)
PATHS[id] = path
with open('PATHS.json', 'w') as fd:
json.dump(PATHS, fd, indent=4, sort_keys=True)
return PATHS[id]
def get_clips(tag):
global CLIPS
if tag not in CLIPS:
get_api()
clips = api.findAnnotations({
'query': {
'conditions': [
{'key': 'layer', 'operator': '==', 'value': 'keywords'},
{'key': 'value', 'operator': '==', 'value': tag}
],
'operator': '&'
},
'keys': ['id', 'in', 'out'],
'range': [0, 10000]})['data']['items']
for clip in clips:
clip['path'] = get_path(clip['id'].split('/')[0])
clip['duration'] = clip['out'] - clip['in']
clip['tag'] = tag
CLIPS[tag] = list(sorted(clips, key=lambda c: c['id']))
with open('CLIPS.json', 'w') as fd:
json.dump(CLIPS, fd, indent=4, sort_keys=True)
return CLIPS[tag]
def random_choice(seq, items):
n = n_ = len(items) - 1
print('len', n)
if n == 0:
return items[0]
r = seq()
base = 10
while n > 10:
n /= 10
print(r)
r += seq()
base += 10
r = int(n_ * r / base)
print('result', r, items)
return items[r]
def splitint(number, by):
div = int(number/by)
mod = number % by
return [div + 1 if i > (by - 1 - mod) else div for i in range(by)]
def filter_clips(clips, duration, max_duration=0):
# 1 minute
blur = 0.5
low = 1
high = 10
# 2 minute
blur = 1
low = 2
high = 20
buckets = {}
clips_ = []
for tag in clips:
for clip in clips[tag]:
clip['tag'] = tag
clips_.append(clip)
clips_.sort(key=lambda c: c['duration'])
print(clips_)
size = splitint(len(clips_), 10)
p = 0
for i in range(10):
buckets[i+1] = clips_[p:+p+size[i]]
p += size[i]
clips_ = {}
print(buckets[duration])
for clip in buckets[duration]:
if clip['tag'] not in clips_:
clips_[clip['tag']] = []
clips_[clip['tag']].append(clip)
return clips_
def sequence(seq, letter):
tags = KEYWORDS[letter]
clips = {tag: get_clips(tag) for tag in tags}
result = {
'clips': [],
'text': [],
}
duration = 0
MAX_DURATION = 65 * 2
MIN_DURATION = 56 * 2
while duration < MAX_DURATION and not duration >= MIN_DURATION:
# clip duration: 1-10
n = seq()
if n == 0:
n = 10
max_duration = MAX_DURATION - duration
clips_n = filter_clips(clips, n, max_duration)
tags_n = list(sorted(clips_n.keys()))
if not tags_n:
print('NO tags for', letter, n)
tag = random_choice(seq, tags_n)
#if 'tiger' in tags_n:
# tag = 'tiger'
clip = random_choice(seq, clips_n[tag])
duration += clip['duration']
result['clips'].append(clip.copy())
for clip in result['clips']:
if seq() == 0:
clip['black'] = True
position = last_text = 0
while position < duration:
n = seq()
if n == 0:
blank = {'blank': True, 'duration': position - last_text}
result['text'].append(blank)
n = seq()
if n == 0:
n = 10
n = min(n, duration-position)
text = {
'text': random_choice(seq, tags_n),
'duration': n
}
result['text'].append(text)
position += n
last_text = position
else:
position += n
if last_text < duration:
blank = {'blank': True, 'duration': duration - last_text}
result['text'].append(blank)
return result
if __name__ == '__main__':
for n in range(10):
seq = random(n)
#for letter in string.ascii_uppercase:
for letter in ('T', 'W'):
r = sequence(seq, letter)
tjson = 'output/%s%d.json' % (letter, n)
with open(tjson, 'w') as fd:
json.dump(r, fd, indent=4, sort_keys=True)
print(json.dumps(r, indent=4, sort_keys=True))
#print(sum([c['duration'] for c in r['clips']]))
subprocess.call(['./render_mlt.py', tjson])