From 715e892475de7d963cd0df6908cf35da819d905d Mon Sep 17 00:00:00 2001 From: MaZderMind Date: Fri, 18 Apr 2014 20:56:24 +0200 Subject: [PATCH] eh14 pre/postroll --- eh14/artwork/abspann.svg | 1001 +++++++++++++++++++++++++++ eh14/artwork/overlay-1024x576.png | Bin 0 -> 13232 bytes eh14/artwork/overlay-720x576.png | Bin 0 -> 10181 bytes eh14/artwork/overlay.svg | 492 ++++++++++++++ eh14/artwork/pause.svg | 1017 ++++++++++++++++++++++++++++ eh14/artwork/vorspann.svg | 1048 +++++++++++++++++++++++++++++ eh14/make.py | 447 ++++++++++++ 7 files changed, 4005 insertions(+) create mode 100644 eh14/artwork/abspann.svg create mode 100644 eh14/artwork/overlay-1024x576.png create mode 100644 eh14/artwork/overlay-720x576.png create mode 100644 eh14/artwork/overlay.svg create mode 100644 eh14/artwork/pause.svg create mode 100644 eh14/artwork/vorspann.svg create mode 100755 eh14/make.py diff --git a/eh14/artwork/abspann.svg b/eh14/artwork/abspann.svg new file mode 100644 index 0000000..c4f8cb7 --- /dev/null +++ b/eh14/artwork/abspann.svg @@ -0,0 +1,1001 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ddddd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eh14/artwork/overlay-1024x576.png b/eh14/artwork/overlay-1024x576.png new file mode 100644 index 0000000000000000000000000000000000000000..db6a944d099fc04a98c57a6446d370ccd0a99734 GIT binary patch literal 13232 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 bBT%Grm-kUv)pj#ez5}>5@|V(|Z#?`z`caa> literal 0 HcmV?d00001 diff --git a/eh14/artwork/overlay-720x576.png b/eh14/artwork/overlay-720x576.png new file mode 100644 index 0000000000000000000000000000000000000000..99d862bc8f0a5e68fc0518ab6280b7f351ac595e GIT binary patch literal 10181 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 o{u_b+M&Q2@_;M1& literal 0 HcmV?d00001 diff --git a/eh14/artwork/overlay.svg b/eh14/artwork/overlay.svg new file mode 100644 index 0000000..fbb69b9 --- /dev/null +++ b/eh14/artwork/overlay.svg @@ -0,0 +1,492 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eh14/artwork/pause.svg b/eh14/artwork/pause.svg new file mode 100644 index 0000000..de93a29 --- /dev/null +++ b/eh14/artwork/pause.svg @@ -0,0 +1,1017 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ddddd Gleich geht's weiter... + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eh14/artwork/vorspann.svg b/eh14/artwork/vorspann.svg new file mode 100644 index 0000000..fdba27f --- /dev/null +++ b/eh14/artwork/vorspann.svg @@ -0,0 +1,1048 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ddddd $title + + $personnames $subtitle + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eh14/make.py b/eh14/make.py new file mode 100755 index 0000000..4d4bf22 --- /dev/null +++ b/eh14/make.py @@ -0,0 +1,447 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +import sys +import glob +import os +import re +import math +import shutil +import errno +import unicodedata +import urllib2 +#import xml.etree.ElementTree as etree +from lxml import etree +import cssutils +import logging +import textwrap +import tempfile +import threading +import multiprocessing +from threading import Thread, Lock +from Queue import Queue + +# Frames per second. Increasing this renders more frames, the avconf-statements would still need modifications +fps = 25 + +# using --debug skips the threading, the network fetching of the schedule and +# just renders one type of video +debug = ('--debug' in sys.argv) + +# using --offline only skips the network fetching and use a local schedule.de.xml +offline = ('--offline' in sys.argv) + +# set charset of output-terminal +reload(sys) +sys.setdefaultencoding('utf-8') + +# t: current time, b: begInnIng value, c: change In value, d: duration +# copied from jqueryui +def easeOutCubic(t, b, c, d): + t=float(t)/d-1 + return c*((t)*t*t + 1) + b + +def easeInCubic(t, b, c, d): + t=float(t)/d + return c*(t)*t*t + b; + +def easeOutQuad(t, b, c, d): + t=float(t)/d + return -c *(t)*(t-2) + b; + +# try to create all folders needed and skip, they already exist +def ensurePathExists(path): + try: + os.makedirs(path) + except OSError as exception: + if exception.errno != errno.EEXIST: + raise + +# remove the files matched by the pattern +def ensureFilesRemoved(pattern): + for f in glob.glob(pattern): + os.unlink(f) + +# Normalizes string, converts to lowercase, removes non-alpha characters, + #and converts spaces to hyphens. +def slugify(value): + value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore') + value = unicode(re.sub('[^\w\s-]', '', value).strip().lower()) + value = unicode(re.sub('[-\s]+', '-', value)) + return value + +# create a filename from the events' id and a slugified version of the title +def vorspannFilename(id, title): + return u'{0:04d}-{1}.dv'.format(id, slugify(unicode(title))) + +# svg does not have a method for automatic line breaking, that rsvg is capable of +# so we do it in python as good as we can +def vorspannTitle(title): + return ''.join(textwrap.wrap(title, 50)) + +def vorspannUrl(id): + return 'fossgis.de/konferenz/2014/programm/events/'+str(id)+'.de.html' + + +def abspannFrames(): + # 5 Sekunden + + # 2 Sekunden Fadein Lizenz + frames = 2*fps + for i in range(0, frames): + yield ( + ('lizenz','style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ) + + # 3 Sekunden stehenlassen + frames = 3*fps + for i in range(0, frames): + yield ( + ('lizenz','style', 'opacity', 1), + ) + + +def vorspannFrames(): + # 5 Sekunden + + # 1 Sekunde Title Fadein + frames = 1*fps + for i in range(0, frames): + yield ( + ('title', 'style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ('text', 'style', 'opacity', 0), + ('lizenz','style', 'opacity', 0), + ) + + # 2 Sekunde Text Fadein + frames = 2*fps + for i in range(0, frames): + yield ( + ('title', 'style', 'opacity', 1), + ('text', 'style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ('lizenz','style', 'opacity', 0), + ) + + # 1 Sekunde Lizenz Fadein + frames = 1*fps + for i in range(0, frames): + yield ( + ('title', 'style', 'opacity', 1), + ('text', 'style', 'opacity', 1), + ('lizenz','style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ) + + # 1 Sekunde stehen bleiben + frames = 1*fps + for i in range(0, frames): + yield ( + ('title', 'style', 'opacity', 1), + ('text', 'style', 'opacity', 1), + ('lizenz','style', 'opacity', 1), + ) + +def pauseFrames(): + # 7 Sekunden + + # 3 Sekunde Text FadeIn + frames = 3*fps + for i in range(0, frames): + yield ( + ('text','style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ) + + # 3 Sekunde Text FadeOut + frames = 3*fps + for i in range(0, frames): + yield ( + ('text','style', 'opacity', "%.4f" % easeInCubic(i, 1, -1, frames)), + ) + + # 1 Sekunde stehen lassen + frames = 1*fps + for i in range(0, frames): + yield ( + ('text','style', 'opacity', 0), + ) + +cssutils.ser.prefs.lineSeparator = ' ' +cssutils.log.setLevel(logging.ERROR) + +def render(infile, outfile, sequence, parameters={}, workdir='artwork'): + # in debug mode we have no thread-worker which prints its progress + if debug: + print "generating {0} from {1}".format(outfile, infile) + + # make sure a .frames-directory exists in out workdir + ensurePathExists(os.path.join(workdir, '.frames')) + + # open and parse the input file + with open(os.path.join(workdir, infile), 'r') as fp: + svgstr = fp.read() + for key in parameters.keys(): + svgstr = svgstr.replace(key, str(parameters[key])) + + svg = etree.fromstring(svgstr) + + # find all images and force them to absolute file-urls + namespaces = {'xlink': 'http://www.w3.org/1999/xlink', 'svg': 'http://www.w3.org/2000/svg'} + for el in svg.findall(".//svg:image[@xlink:href]", namespaces=namespaces): + el.attrib['{http://www.w3.org/1999/xlink}href'] = 'file:///' + os.path.realpath(workdir) + '/' + el.attrib['{http://www.w3.org/1999/xlink}href'] + + + # frame-number counter + frameNr = 0 + + # iterate through the animation seqence frame by frame + # frame is a ... tbd + for frame in sequence(): + # print a line for each and every frame generated + if debug: + print "frameNr {0:2d} => {1}".format(frameNr, frame) + + # open the output-file (named ".gen.svg" in the workdir) + with open(os.path.join(workdir, '.gen.svg'), 'w') as fp: + # apply the replace-pairs to the input text, by finding the specified xml-elements by thier id and modify thier css-parameter the correct value + for replaceinfo in frame: + (id, type, key, value) = replaceinfo + + for el in svg.findall(".//*[@id='"+id.replace("'", "\\'")+"']"): + if type == 'style': + style = cssutils.parseStyle( el.attrib['style'] if 'style' in el.attrib else '' ) + style[key] = unicode(value) + el.attrib['style'] = style.cssText + + elif type == 'attr': + el.attrib[key] = value + + # write the generated svg-text into the output-file + fp.write( etree.tostring(svg) ) + + # invoke inkscape to convert the generated svg-file into a png inside the .frames-directory + os.system('cd {0} && inkscape --export-png=.frames/{1:04d}.png .gen.svg >/dev/null 2>&1'.format(workdir, frameNr)) + + # incrwement frame-number + frameNr += 1 + + # remove the dv we are about to (re-)generate + ensureFilesRemoved(os.path.join(workdir, outfile)) + + # invoke avconv aka ffmpeg and renerate a lossles-dv from the frames + # if we're not in debug-mode, suppress all output + os.system('cd {0} && avconv -ar 48000 -ac 2 -f s16le -i /dev/zero -f image2 -i .frames/%04d.png -target pal-dv -aspect 16:9 -shortest "{1}"'.format(workdir, outfile) + ('' if debug else '>/dev/null 2>&1')) + + # as before, in non-debug-mode the thread-worker does all progress messages + if debug: + print "cleanup" + + # remove the .frames-dir with all frames in it + shutil.rmtree(os.path.join(workdir, '.frames')) + + # remove the generated svg + ensureFilesRemoved(os.path.join(workdir, '.gen.svg')) + + + +# Download the Events-Schedule and parse all Events out of it. Yield a tupel for each Event +def events(): + print "downloading pentabarf schedule" + + # use --offline to skip networking + if offline: + # parse the offline-version + schedule = etree.parse('schedule.de.xml').getroot() + + else: + # download the schedule + response = urllib2.urlopen('http://www.fossgis.de/konferenz/2014/programm/schedule.de.xml') + + # read xml-source + xml = response.read() + + # parse into ElementTree + schedule = etree.fromstring(xml) + + # iterate all days + for day in schedule.iter('day'): + # iterate all rooms + for room in day.iter('room'): + # iterate events on that day in this room + for event in room.iter('event'): + # aggregate names of the persons holding this talk + personnames = [] + for person in event.find('persons').iter('person'): + personnames.append(person.text) + + # yield a tupel with the event-id, event-title and person-names + yield ( int(event.get('id')), event.find('title').text, event.find('subtitle').text, ', '.join(personnames) ) + + +# debug-mode selected by --debug switch +if debug: + print "!!! DEBUG MODE !!!" + title = 'Sleep? Ain\'t nobody got time for that!' + subtitle = 'Physiologie von Schlaf und Wachzustand' + + render( + 'vorspann.svg', + os.path.join('..', str(5725)+".dv"), + vorspannFrames, + { + '$id': 5725, + '$title': title, + '$subtitle': subtitle, + '$personnames': 'Christina' + } + ) + + # render( + # 'abspann.svg', + # '../outro.dv', + # abspannFrames + # ) + + render('pause.svg', + '../pause.dv', + pauseFrames + ) + + sys.exit(0) + + + +# threaded task queue +tasks = Queue() + + +# for too long titles ;) +titlemap = { + #708: "Neue WEB-Anwendungen des LGRB Baden-Württemberg im Überblick" +} + +# iterate over all events extracted from the schedule xml-export +for (id, title, subtitle, personnames) in events(): + if id in titlemap: + title = titlemap[id] + + # generate a task description and put them into the queue + tasks.put(( + 'vorspann.svg', + str(id)+".dv", + vorspannFrames, + { + '$id': id, + '$title': title, + '$subtitle': subtitle, + '$personnames': personnames + } + )) + +# place a task for the outro into the queue +tasks.put(( + 'abspann.svg', + 'outro.dv', + abspannFrames +)) + +# place the pause-sequence into the queue +tasks.put(( + 'pause.svg', + 'pause.dv', + pauseFrames +)) + +# one working thread per cpu +num_worker_threads = multiprocessing.cpu_count() +print "{0} tasks in queue, starting {1} worker threads".format(tasks.qsize(), num_worker_threads) + +# put a sentinel for each thread into the queue to signal the end +for _ in range(num_worker_threads): + tasks.put(None) + +# this lock ensures, that only one thread at a time is writing to stdout +# and avoids output from multiple threads intermixing +printLock = Lock() +def tprint(str): + # aquire lock + printLock.acquire() + + # print thread-name and message + print threading.current_thread().name+': '+str + + # release lock + printLock.release() + + +# thread worker +def worker(): + # generate a tempdir for this worker-thread and use the artwork-subdir as temporary folder + tempdir = tempfile.mkdtemp() + workdir = os.path.join(tempdir, 'artwork') + + # save the current working dir as output-dir + outdir = os.getcwd() + + # print a message that we're about to initialize our environment + tprint("initializing worker in {0}, writing result to {1}".format(tempdir, outdir)) + + # copy the artwork-dir into the tempdir + shutil.copytree('artwork', workdir) + + # loop until all tasks are done (when the thread fetches a sentinal from the queue) + while True: + # fetch a task from the queue + task = tasks.get() + + # if it is a stop-sentinal break out of the loop + if task == None: + break + + # print that we're about to render a task + tprint('rendering {0}'.format(task[1])) + + # render options + opts = ( + # argument 0 is the input file. prepend the workdir + os.path.join(workdir, task[0]), + + # argument 1 is the output file. prepend the outdir + os.path.join(outdir, task[1]), + + # argument 2 is the frame generator, nothing to do here + task[2], + + # argument 3 are the extra parameters + task[3] if len(task) > 3 else {}, + + # argument 4 is the workdir path + workdir + ) + + # render with these arguments + render(*opts) + + # print that we're finished + tprint('finished {0}, {1} tasks left'.format(task[1], max(0, tasks.qsize() - num_worker_threads))) + + # mark the task as finished + tasks.task_done() + + # all tasks from the queue done, clean up + tprint("cleaning up worker") + + # remove the tempdir + shutil.rmtree(tempdir) + + # mark the sentinal as done + tasks.task_done() + + +# generate and start the threads +for i in range(num_worker_threads): + t = Thread(target=worker) + t.daemon = True + t.start() + +# wait until they finished doing the work +tasks.join() +print "all worker threads ended"