render fixes, encode vides in render command
This commit is contained in:
parent
e84ea31147
commit
5075394318
4 changed files with 35 additions and 7 deletions
|
@ -19,10 +19,12 @@ class Command(BaseCommand):
|
||||||
clips = []
|
clips = []
|
||||||
for i in item.models.Item.objects.filter(data__type__contains="Original"):
|
for i in item.models.Item.objects.filter(data__type__contains="Original"):
|
||||||
qs = item.models.Item.objects.filter(data__title=i.data['title']).exclude(id=i.id)
|
qs = item.models.Item.objects.filter(data__title=i.data['title']).exclude(id=i.id)
|
||||||
if qs.count() == 2:
|
if qs.count() >= 2:
|
||||||
clip = {}
|
clip = {}
|
||||||
durations = []
|
durations = []
|
||||||
for e in item.models.Item.objects.filter(data__title=i.data['title']):
|
for e in item.models.Item.objects.filter(data__title=i.data['title']):
|
||||||
|
if 'type' not in e.data:
|
||||||
|
print("ignoring invalid video", e)
|
||||||
source = e.files.all()[0].data.path
|
source = e.files.all()[0].data.path
|
||||||
ext = os.path.splitext(source)[1]
|
ext = os.path.splitext(source)[1]
|
||||||
type_ = e.data['type'][0].lower()
|
type_ = e.data['type'][0].lower()
|
||||||
|
@ -35,7 +37,10 @@ class Command(BaseCommand):
|
||||||
durations.append(e.files.all()[0].duration)
|
durations.append(e.files.all()[0].duration)
|
||||||
clip["duration"] = min(durations)
|
clip["duration"] = min(durations)
|
||||||
clip['tags'] = i.data.get('tags', [])
|
clip['tags'] = i.data.get('tags', [])
|
||||||
|
if "original" in clip and "foreground" in clip and "background" in clip:
|
||||||
clips.append(clip)
|
clips.append(clip)
|
||||||
|
else:
|
||||||
|
print("ignoring incomplete video", i)
|
||||||
|
|
||||||
with open(os.path.join(prefix, 'clips.json'), 'w') as fd:
|
with open(os.path.join(prefix, 'clips.json'), 'w') as fd:
|
||||||
json.dump(clips, fd, indent=2, ensure_ascii=False)
|
json.dump(clips, fd, indent=2, ensure_ascii=False)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -14,6 +15,7 @@ class Command(BaseCommand):
|
||||||
parser.add_argument('--prefix', action='store', dest='prefix', default="/srv/t_for_time", help='prefix to build clips in')
|
parser.add_argument('--prefix', action='store', dest='prefix', default="/srv/t_for_time", help='prefix to build clips in')
|
||||||
parser.add_argument('--duration', action='store', dest='duration', default="150", help='target duration in seconds')
|
parser.add_argument('--duration', action='store', dest='duration', default="150", help='target duration in seconds')
|
||||||
parser.add_argument('--offset', action='store', dest='offset', default="1024", help='inital offset in pi')
|
parser.add_argument('--offset', action='store', dest='offset', default="1024", help='inital offset in pi')
|
||||||
|
parser.add_argument('--no-video', action='store_true', dest='no_video', default=False, help='don\'t render video')
|
||||||
|
|
||||||
def handle(self, **options):
|
def handle(self, **options):
|
||||||
prefix = options['prefix']
|
prefix = options['prefix']
|
||||||
|
@ -23,7 +25,15 @@ class Command(BaseCommand):
|
||||||
with open(os.path.join(prefix, "clips.json")) as fd:
|
with open(os.path.join(prefix, "clips.json")) as fd:
|
||||||
clips = json.load(fd)
|
clips = json.load(fd)
|
||||||
scene = compose(clips, target=target, base=base)
|
scene = compose(clips, target=target, base=base)
|
||||||
render(prefix, scene, 'scene-%s-' % base)
|
timelines = render(prefix, scene, 'scene-%s-' % base)
|
||||||
with open(os.path.join(prefix, 'scene-%s.json' % base), 'w') as fd:
|
with open(os.path.join(prefix, 'scene-%s.json' % base), 'w') as fd:
|
||||||
json.dump(scene, fd, indent=2, ensure_ascii=False)
|
json.dump(scene, fd, indent=2, ensure_ascii=False)
|
||||||
|
if not options['no_video']:
|
||||||
|
for timeline in timelines:
|
||||||
|
cmd = [
|
||||||
|
'xvfb-run', '-a',
|
||||||
|
'melt', timeline,
|
||||||
|
'-consumer', 'avformat:%s' % timeline.replace('.kdenlive', '.mp4')
|
||||||
|
]
|
||||||
|
subprocess.call(cmd)
|
||||||
|
|
||||||
|
|
14
render.py
14
render.py
|
@ -14,7 +14,9 @@ def random_choice(seq, items, pop=False):
|
||||||
n = n_ = len(items) - 1
|
n = n_ = len(items) - 1
|
||||||
#print('len', n)
|
#print('len', n)
|
||||||
if n == 0:
|
if n == 0:
|
||||||
return items[0]
|
if pop:
|
||||||
|
return items.pop(n)
|
||||||
|
return items[n]
|
||||||
r = seq()
|
r = seq()
|
||||||
base = 10
|
base = 10
|
||||||
while n > 10:
|
while n > 10:
|
||||||
|
@ -50,9 +52,12 @@ def compose(clips, target=150, base=1024):
|
||||||
'A4': [],
|
'A4': [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
all_clips = clips.copy()
|
||||||
seq = random(base)
|
seq = random(base)
|
||||||
while target - length > 10 and clips:
|
while target - length > 10 and clips:
|
||||||
clip = random_choice(seq, clips, True)
|
clip = random_choice(seq, clips, True)
|
||||||
|
if not clips:
|
||||||
|
clips = [c for c in all_clips if c != clip]
|
||||||
if length + clip['duration'] > target:
|
if length + clip['duration'] > target:
|
||||||
break
|
break
|
||||||
length += clip['duration']
|
length += clip['duration']
|
||||||
|
@ -112,6 +117,7 @@ def compose(clips, target=150, base=1024):
|
||||||
|
|
||||||
def render(root, scene, prefix=''):
|
def render(root, scene, prefix=''):
|
||||||
fps = 24
|
fps = 24
|
||||||
|
files = []
|
||||||
for timeline, data in scene.items():
|
for timeline, data in scene.items():
|
||||||
print(timeline)
|
print(timeline)
|
||||||
project = KDEnliveProject(root)
|
project = KDEnliveProject(root)
|
||||||
|
@ -121,6 +127,8 @@ def render(root, scene, prefix=''):
|
||||||
print(track)
|
print(track)
|
||||||
for clip in clips:
|
for clip in clips:
|
||||||
project.append_clip(track, clip)
|
project.append_clip(track, clip)
|
||||||
|
path = os.path.join(root, prefix + "%s.kdenlive" % timeline)
|
||||||
with open(os.path.join(root, prefix + "%s.kdenlive" % timeline), 'w') as fd:
|
with open(path, 'w') as fd:
|
||||||
fd.write(project.to_xml())
|
fd.write(project.to_xml())
|
||||||
|
files.append(path)
|
||||||
|
return files
|
||||||
|
|
|
@ -5,6 +5,7 @@ import lxml.etree
|
||||||
import uuid
|
import uuid
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
_CACHE = {}
|
||||||
_IDS = defaultdict(int)
|
_IDS = defaultdict(int)
|
||||||
|
|
||||||
def get_propery(element, name):
|
def get_propery(element, name):
|
||||||
|
@ -12,6 +13,7 @@ def get_propery(element, name):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class KDEnliveProject:
|
class KDEnliveProject:
|
||||||
|
|
||||||
def to_xml(self):
|
def to_xml(self):
|
||||||
|
@ -316,7 +318,10 @@ class KDEnliveProject:
|
||||||
return prefix + self.get_counter(prefix)
|
return prefix + self.get_counter(prefix)
|
||||||
|
|
||||||
def get_chain(self, file, kdenlive_id=None):
|
def get_chain(self, file, kdenlive_id=None):
|
||||||
out = subprocess.check_output(['melt', file, '-consumer', 'xml'])
|
if file in _CACHE:
|
||||||
|
out = _CACHE[file]
|
||||||
|
else:
|
||||||
|
out = _CACHE[file] = subprocess.check_output(['melt', file, '-consumer', 'xml'])
|
||||||
chain = lxml.etree.fromstring(out).xpath('producer')[0]
|
chain = lxml.etree.fromstring(out).xpath('producer')[0]
|
||||||
chain.tag = 'chain'
|
chain.tag = 'chain'
|
||||||
chain.attrib['id'] = self.get_id('chain')
|
chain.attrib['id'] = self.get_id('chain')
|
||||||
|
|
Loading…
Reference in a new issue