commit 6a5feb5d5cbfb543d09a95f5d580255b8f711a65 Author: MaZderMind Date: Thu Mar 6 10:28:56 2014 +0100 restructure diff --git a/2014/.gitignore b/2014/.gitignore new file mode 100644 index 0000000..a2f18c0 --- /dev/null +++ b/2014/.gitignore @@ -0,0 +1,3 @@ +*.mp4 +schedule.de.xml + diff --git a/2014/artwork/abspann.svg b/2014/artwork/abspann.svg new file mode 100644 index 0000000..e80b511 --- /dev/null +++ b/2014/artwork/abspann.svg @@ -0,0 +1,225 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + Berlin19. - 21. März 2014 + FOSSGIS Konferenz2014fossgis.de/konferenz/2014/ + + + + + diff --git a/2014/artwork/by-nc-sa.svg b/2014/artwork/by-nc-sa.svg new file mode 100644 index 0000000..76fe351 --- /dev/null +++ b/2014/artwork/by-nc-sa.svg @@ -0,0 +1,202 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2014/artwork/by-sa.svg b/2014/artwork/by-sa.svg new file mode 100644 index 0000000..f850297 --- /dev/null +++ b/2014/artwork/by-sa.svg @@ -0,0 +1,199 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2014/artwork/cc-zero.svg b/2014/artwork/cc-zero.svg new file mode 100644 index 0000000..195592b --- /dev/null +++ b/2014/artwork/cc-zero.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/2014/artwork/foto-soft.jpg b/2014/artwork/foto-soft.jpg new file mode 100644 index 0000000..0ba8505 Binary files /dev/null and b/2014/artwork/foto-soft.jpg differ diff --git a/2014/artwork/foto.jpg b/2014/artwork/foto.jpg new file mode 100644 index 0000000..dc474a8 Binary files /dev/null and b/2014/artwork/foto.jpg differ diff --git a/2014/artwork/logo-332.png b/2014/artwork/logo-332.png new file mode 100644 index 0000000..de3f43d Binary files /dev/null and b/2014/artwork/logo-332.png differ diff --git a/2014/artwork/logo.png b/2014/artwork/logo.png new file mode 100644 index 0000000..84ea33f Binary files /dev/null and b/2014/artwork/logo.png differ diff --git a/2014/artwork/logo_ohne_rand-332.png b/2014/artwork/logo_ohne_rand-332.png new file mode 100644 index 0000000..4116be2 Binary files /dev/null and b/2014/artwork/logo_ohne_rand-332.png differ diff --git a/2014/artwork/logo_ohne_rand.png b/2014/artwork/logo_ohne_rand.png new file mode 100644 index 0000000..0391370 Binary files /dev/null and b/2014/artwork/logo_ohne_rand.png differ diff --git a/2014/artwork/vorspann.svg b/2014/artwork/vorspann.svg new file mode 100644 index 0000000..70e894d --- /dev/null +++ b/2014/artwork/vorspann.svg @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + Berlin19. - 21. März 2014 + FOSSGIS Konferenz2014 + + + %personnames + %title + + fossgis.de/konferenz/2014/programm/events/%id.de.html + + diff --git a/2014/make.py b/2014/make.py new file mode 100755 index 0000000..7035742 --- /dev/null +++ b/2014/make.py @@ -0,0 +1,269 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- + +import sys +import glob +import os +import re +import shutil +import errno +import unicodedata +import urllib2 +import xml.etree.ElementTree as ET +import textwrap +import tempfile +import threading +import multiprocessing +from threading import Thread, Lock +from Queue import Queue + +# Debug rendert einen Vor- und einen Abspann +fps = 25 +debug = ('--debug' in sys.argv) + +reload(sys) +sys.setdefaultencoding('utf-8') + +# t: current time, b: begInnIng value, c: change In value, d: duration +def easeOutCubic(t, b, c, d): + t=float(t)/d-1 + return c*((t)*t*t + 1) + b + +def ensure_path_exists(path): + try: + os.makedirs(path) + except OSError as exception: + if exception.errno != errno.EEXIST: + raise + +def ensure_files_removed(files): + for f in glob.glob(files): + os.unlink(f) + +def slugify(value): + """ + Normalizes string, converts to lowercase, removes non-alpha characters, + and converts spaces to hyphens. + """ + 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 + + + + +def abspannFrames(): + # 5 Sekunden + + # 2 Sekunden Fadein Text + frame = 0 + frames = 2*fps + for i in range(0, frames): + yield (frame+i, easeOutCubic(i, 0, 1, frames), 0) + + # 2 Sekunde Fadein Lizenz-Logo + frame = frame+i+1 + frames = 2*fps + for i in range(0, frames): + yield (frame+i, 1, float(i)/frames) + + # 1 Sekunde stehen bleiben + frame = frame+i+1 + frames = 1*fps + for i in range(0, frames): + yield (frame+i, 1, 1) + +def vorspannFrames(): + # 7 Sekunden + + # 2 Sekunden Text 1 + frame = 0 + frames = 2*fps + for i in range(0, frames): + yield (frame+i, easeOutCubic(i, 0, 1, frames), easeOutCubic(i, 0, 1, frames), 0) + + # 1 Sekunde Fadeout Text 1 + frame = frame+i+1 + frames = 1*fps + for i in range(0, frames): + yield (frame+i, 1, 1-(float(i)/frames), 0) + + # 2 Sekunden Text 2 + frame = frame+i+1 + frames = 2*fps + for i in range(0, frames): + yield (frame+i, 1, 0, easeOutCubic(i, 0, 1, frames)) + + # 2 Sekunden stehen bleiben + frame = frame+i+1 + frames = 2*fps + for i in range(0, frames): + yield (frame+i, 1, 0, 1) + + + +def abspann(lizenz, workdir='artwork', outdir='..'): + if debug: + print "erzeuge Abspann" + + filename = os.path.join(outdir, 'abspann-{0}.mp4'.format(lizenz)) + + ensure_path_exists(os.path.join(workdir, '.frames')) + + with open(os.path.join(workdir, 'abspann.svg'), 'r') as abspann_file: + abspann = abspann_file.read() + + for (frameNr, opacity, opacityLizenz) in abspannFrames(): + if debug: + print "frameNr {0:2d} => opacity {1:0.2f}, opacityLizenz {2:0.2f}".format(frameNr, opacity, opacityLizenz) + + pairs = \ + ('%opacityLizenz', str(opacityLizenz)), \ + ('%opacity', str(opacity)), \ + ('%lizenz', lizenz), \ + ('%workdir', os.path.realpath(workdir) ) + + with open(os.path.join(workdir, '.gen.svg'), 'w') as gen_file: + gen_abspann = reduce(lambda a, kv: a.replace(*kv), pairs, abspann) + gen_file.write( gen_abspann ) + + os.system('cd {0} && rsvg-convert .gen.svg > .frames/{1:04d}.png'.format(workdir, frameNr)) + + ensure_files_removed(filename) + os.system('cd {0} && avconv -f image2 -i .frames/%04d.png -c:v libx264 -preset veryslow -qp 0 "{1}"'.format(workdir, filename)) + + if debug: + print "aufräumen" + shutil.rmtree(os.path.join(workdir, '.frames')) + ensure_files_removed(os.path.join(workdir, '.gen.svg')) + +def vorspann(id, title, personnames, workdir='artwork', outdir='..'): + if debug: + print u'erzeuge Vorspann für {0:4d} ("{1}")'.format(id, title) + + filename = os.path.join( outdir, u'{0:04d}-{1}.mp4'.format(id, slugify(unicode(title))) ) + + ensure_path_exists(os.path.join(workdir, '.frames')) + + with open(os.path.join(workdir, 'vorspann.svg'), 'r') as vorspann_file: + vorspann = vorspann_file.read() + + # 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 + breaktitle = ''.join(textwrap.wrap(title, 35)) + + for (frameNr, opacityBox, opacity1, opacity2) in vorspannFrames(): + if debug: + print "frameNr {0:2d} => opacityBox {1:0.2f}, opacity1 {2:0.2f}, opacity2 {3:0.2f}".format(frameNr, opacityBox, opacity1, opacity2) + + pairs = \ + ('%opacity1', str(opacity1)), \ + ('%opacity2', str(opacity2)), \ + ('%opacityBox', str(opacityBox)), \ + ('%id', str(id)), \ + ('%title', breaktitle), \ + ('%personnames', personnames), \ + ('%workdir', os.path.realpath(workdir) ) + + with open(os.path.join(workdir, '.gen.svg'), 'w') as gen_file: + gen_vorspann = reduce(lambda a, kv: a.replace(*kv), pairs, vorspann) + gen_file.write( gen_vorspann ) + + os.system('cd {0} && rsvg-convert .gen.svg > .frames/{1:04d}.png'.format(workdir, frameNr)) + + ensure_files_removed(filename) + os.system(u'cd {0} && avconv -f image2 -i .frames/%04d.png -c:v libx264 -preset veryslow -qp 0 "{1}"'.format(workdir, filename) + ('' if debug else '>/dev/null 2>&1')) + + if debug: + print "aufräumen" + shutil.rmtree(os.path.join(workdir, '.frames')) + ensure_files_removed(os.path.join(workdir, '.gen.svg')) + + +def events(): + print "downloading pentabarf schedule" + response = urllib2.urlopen('http://www.fossgis.de/konferenz/2014/programm/schedule.de.xml') + xml = response.read() + schedule = ET.fromstring(xml) + #schedule = ET.parse('schedule.de.xml') + + for day in schedule.iter('day'): + date = day.get('date') + for room in day.iter('room'): + for event in room.iter('event'): + personnames = [] + for person in event.find('persons').iter('person'): + personnames.append(person.text) + + yield ( int(event.get('id')), event.find('title').text, ', '.join(personnames) ) + + + +if debug: + print "!!! DEBUG MODE !!!" + vorspann(667, 'OpenJUMP - Überblick, Neuigkeiten, Zusammenarbeit/Schnittstellen mit proprietärer Software', 'Matthias Scholz') + abspann('by-sa') + sys.exit(0) + + + + +tasks = Queue() + +for (id, title, personnames) in events(): + tasks.put( ('vorspann', id, title, personnames) ) + +tasks.put( ('abspann', 'by-sa') ) +tasks.put( ('abspann', 'by-nc-sa') ) +tasks.put( ('abspann', 'cc-zero') ) + +num_worker_threads = multiprocessing.cpu_count() +print "{0} tasks in queue, starting {1} worker threads".format( tasks.qsize(), num_worker_threads ) + +for _ in range(num_worker_threads): + tasks.put(None) # put sentinel to signal the end + + +printLock = Lock() +def tprint(str): + printLock.acquire() + print threading.current_thread().name+': '+str + printLock.release() + + + +def worker(): + tempdir = os.path.join(tempfile.mkdtemp(), 'artwork') + outdir = os.getcwd() + + tprint("initializing worker in {0}, writing result to {1}".format(tempdir, outdir)) + shutil.copytree('artwork', tempdir) + + while True: + task = tasks.get() + if task == None: + break + + tprint( 'processing {0}'.format(task) ) + fnname = task[0] + fn = globals()[fnname] + opts = task[1:] + (tempdir, outdir) + + fn(*opts) + tprint( 'finished {0}'.format(task) ) + tasks.task_done() + + tprint("cleaning up worker") + shutil.rmtree(tempdir) + tasks.task_done() + + + +for i in range(num_worker_threads): + t = Thread(target=worker) + t.daemon = True + t.start() + +tasks.join() +print "all worker threads ended"