diff --git a/forumoe19/__init__.py b/forumoe19/__init__.py
new file mode 100644
index 0000000..b85bffc
--- /dev/null
+++ b/forumoe19/__init__.py
@@ -0,0 +1,154 @@
+#!/usr/bin/python
+
+from renderlib import *
+from easing import *
+
+# URL to Schedule-XML
+scheduleUrl = 'https://gist.githubusercontent.com/danimo/3cf27a2198da2fbc7c1fb138c13506ce/raw/forumoe19-schedule.xml'
+
+personmap = {
+1: 'Margit Stumpp (Fraktion B. 90/Die Grünen)',
+2: 'Marja-Liisa Völlers (SPD-Fraktion)',
+3: 'Dr. Jens Brandenburg (FDP-Fraktion)',
+}
+
+taglinemap = {
+1: "Bildungspolitische Sprecherin",
+2: "Expertin für frühk., schul. und berufl. Bildung",
+3: "Sprecher für Studium und Bildung",
+4: "mediale.pfade",
+}
+
+
+def bounce(i, min, max, frames):
+ if i == frames - 1:
+ return 0
+
+ if i <= frames/2:
+ return easeInOutQuad(i, min, max, frames/2)
+ else:
+ return max - easeInOutQuad(i - frames/2, min, max, frames/2)
+
+def introFrames(parameters):
+ # 1 Sekunde Text Fadein
+ frames = 1*fps
+ for i in range(0, frames):
+ yield (
+ ('text', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)),
+ )
+
+ # 4 Sekunden stehen lassen
+ frames = 4*fps
+ for i in range(0, frames):
+ yield ()
+
+def outroFrames(p):
+ # 5 Sekunden stehen bleiben
+ frames = 5*fps
+ for i in range(0, frames):
+ yield []
+
+def bbFrames(parameters):
+ # 1 Sekunde Text Fadein
+ frames = 1*fps
+ for i in range(0, frames):
+ yield (
+ ('bg', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)),
+ ('text', 'style', 'opacity', "%.4f" % easeLinear(i, 0, 1, frames)),
+ )
+
+ # 3 Sekunden stehen lassen
+ frames = 3*fps
+ for i in range(0, frames):
+ yield ()
+
+ frames = 1*fps
+ for i in range(0, frames):
+ yield (
+ ('bg', 'style', 'opacity', "%.4f" % easeLinear(i, 1, -1, frames)),
+ ('text', 'style', 'opacity', "%.4f" % easeLinear(i, 1, -1, frames)),
+ )
+
+
+
+def debug():
+# render(
+# 'intro.svg',
+# '../intro.ts',
+# introFrames,
+# {
+# '$ID': 4711,
+# '$TITLE': "Long Long Long title is LONG",
+# '$SUBTITLE': 'Long Long Long Long subtitle is LONGER',
+# '$SPEAKER': 'Long Name of Dr. Dr. Prof. Dr. Long Long'
+# }
+# )
+
+ render(
+ 'insert.svg',
+ '../insert.mkv',
+ bbFrames,
+ {
+ '$PERSON': "Prof. Bernhard Birnbaum",
+ '$TAGLINE': "Leiter des rennomierten Birnbaum-Instituts",
+ }
+ )
+
+# render(
+# 'pause.svg',
+# '../pause.ts',
+# pauseFrames
+# )
+#
+# render(
+# 'outro.svg',
+# '../outro.ts',
+# outroFrames
+# )
+
+def tasks(queue, args, idlist, skiplist):
+ # iterate over all events extracted from the schedule xml-export
+ for event in events(scheduleUrl):
+ if event['room'] not in ('ecdf'):
+ print("skipping room %s (%s [%s])" % (event['room'], event['title'], event['id']))
+ continue
+ if not (idlist==[]):
+ if 000000 in idlist:
+ print("skipping id (%s [%s])" % (event['title'], event['id']))
+ continue
+ if int(event['id']) not in idlist:
+ print("skipping id (%s [%s])" % (event['title'], event['id']))
+ continue
+
+ # generate a task description and put it into the queue
+ queue.put(Rendertask(
+ infile = 'intro.svg',
+ outfile = str(event['id'])+".ts",
+ sequence = introFrames,
+ parameters = {
+ '$ID': event['id'],
+ '$TITLE': event['title'],
+ '$SUBTITLE': event['subtitle'],
+ '$SPEAKER': event['personnames']
+ }
+ ))
+
+ # place a task for the outro into the queue
+ if not "out" in skiplist:
+ queue.put(Rendertask(
+ infile = 'outro.svg',
+ outfile = 'outro.ts',
+ sequence = outroFrames
+ ))
+
+ for person in persons(scheduleUrl, personmap, taglinemap):
+ queue.put(Rendertask(
+ infile = 'insert.svg',
+ outfile = "insert_{}.mkv".format(person['person'].replace("/", "_")),
+ sequence = bbFrames,
+ parameters = {
+ '$PERSON': person['person'],
+ '$TAGLINE': person['tagline'],
+ }
+ ))
+
diff --git a/forumoe19/artwork/5_Intro-Video.png b/forumoe19/artwork/5_Intro-Video.png
new file mode 100644
index 0000000..c7e2925
Binary files /dev/null and b/forumoe19/artwork/5_Intro-Video.png differ
diff --git a/forumoe19/artwork/CC-Zero-badge.svg b/forumoe19/artwork/CC-Zero-badge.svg
new file mode 100644
index 0000000..122529e
--- /dev/null
+++ b/forumoe19/artwork/CC-Zero-badge.svg
@@ -0,0 +1,12 @@
+
+
diff --git a/forumoe19/artwork/Logo_Bündnis_Freie_Bildung_hochkant.png b/forumoe19/artwork/Logo_Bündnis_Freie_Bildung_hochkant.png
new file mode 100644
index 0000000..f5febb2
Binary files /dev/null and b/forumoe19/artwork/Logo_Bündnis_Freie_Bildung_hochkant.png differ
diff --git a/forumoe19/artwork/insert.png b/forumoe19/artwork/insert.png
new file mode 100644
index 0000000..4dd7c16
Binary files /dev/null and b/forumoe19/artwork/insert.png differ
diff --git a/forumoe19/artwork/insert.svg b/forumoe19/artwork/insert.svg
new file mode 100644
index 0000000..c2106fb
--- /dev/null
+++ b/forumoe19/artwork/insert.svg
@@ -0,0 +1,97 @@
+
+
+
+
diff --git a/forumoe19/artwork/intro.svg b/forumoe19/artwork/intro.svg
new file mode 100644
index 0000000..bab0025
--- /dev/null
+++ b/forumoe19/artwork/intro.svg
@@ -0,0 +1,588 @@
+
+
+
+
diff --git a/forumoe19/artwork/logo-okfn.png b/forumoe19/artwork/logo-okfn.png
new file mode 100644
index 0000000..1abf6f4
Binary files /dev/null and b/forumoe19/artwork/logo-okfn.png differ
diff --git a/forumoe19/artwork/outro.svg b/forumoe19/artwork/outro.svg
new file mode 100644
index 0000000..a4353e3
--- /dev/null
+++ b/forumoe19/artwork/outro.svg
@@ -0,0 +1,583 @@
+
+
+
+
diff --git a/forumoe19/artwork/pause.svg b/forumoe19/artwork/pause.svg
new file mode 100644
index 0000000..e69de29
diff --git a/forumoe19/artwork/wmde.png b/forumoe19/artwork/wmde.png
new file mode 100644
index 0000000..5394326
Binary files /dev/null and b/forumoe19/artwork/wmde.png differ
diff --git a/renderlib.py b/renderlib.py
index 36ff9b4..21b7173 100644
--- a/renderlib.py
+++ b/renderlib.py
@@ -162,7 +162,7 @@ def rendertask(task):
# write the generated svg-text into the output-file
fp.write(etree.tostring(svg, encoding='unicode'))
- if task.outfile.endswith('.ts') or task.outfile.endswith('.mov'):
+ if task.outfile.endswith('.ts') or task.outfile.endswith('.mov') or task.outfile.endswith('.mkv'):
width = 1920
height = 1080
else:
@@ -216,6 +216,8 @@ def rendertask(task):
elif task.outfile.endswith('.mov'):
cmd = 'cd {0} && '.format(task.workdir)
cmd += 'ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -f image2 -i .frames/%04d.png -r 25 -shortest -c:v qtrle -f mov "{0}"'.format(task.outfile)
+ elif task.outfile.endswith('.mkv'):
+ cmd = 'cd {0} && ffmpeg -ar 48000 -ac 2 -f s16le -i /dev/zero -f image2 -i .frames/%04d.png -aspect 16:9 -c copy -shortest "{1}"'.format(task.workdir, task.outfile)
else:
cmd = 'cd {0} && ffmpeg -ar 48000 -ac 2 -f s16le -i /dev/zero -f image2 -i .frames/%04d.png -target pal-dv -aspect 16:9 -shortest "{1}"'.format(task.workdir, task.outfile)
@@ -238,7 +240,7 @@ def rendertask(task):
# Download the Events-Schedule and parse all Events out of it. Yield a tupel for each Event
-def events(scheduleUrl, titlemap={}):
+def downloadSchedule(scheduleUrl):
print("downloading schedule")
# download the schedule
@@ -249,8 +251,41 @@ def events(scheduleUrl, titlemap={}):
# parse into ElementTree
parser = etree.XMLParser(huge_tree=True)
- schedule = etree.fromstring(xml, parser)
+ return etree.fromstring(xml, parser)
+def persons(scheduleUrl, personmap={}, taglinemap={}):
+ schedule = downloadSchedule(scheduleUrl)
+ # 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
+ persons_seen = []
+ if event.find('persons') is not None:
+ for person in event.find('persons').iter('person'):
+ id = int(person.get("id"))
+ person = re.sub(r'\s+', ' ', person.text).strip()
+ match = re.search(r'\((.*?)\)', person)
+ tagline = ''
+ if not match is None:
+ tagline = match.group(1)
+ person = person.split(" (")[0]
+ if id in taglinemap:
+ tagline = taglinemap[id]
+ if id in personmap:
+ person = personmap[id]
+ if not id in persons_seen:
+ persons_seen.append(id)
+ yield {
+ 'id': id,
+ 'person': person,
+ 'tagline': tagline
+ }
+
+def events(scheduleUrl, titlemap={}):
+ schedule = downloadSchedule(scheduleUrl)
# iterate all days
for day in schedule.iter('day'):
# iterate all rooms
@@ -277,7 +312,6 @@ def events(scheduleUrl, titlemap={}):
subtitle = re.sub(r'\s+', ' ', event.find('subtitle').text).strip()
else:
subtitle = ''
-
# yield a tupel with the event-id, event-title and person-names
yield {
'id': id,
@@ -287,7 +321,7 @@ def events(scheduleUrl, titlemap={}):
'personnames': ', '.join(personnames),
'room': room.attrib['name'],
'track': event.find('track').text,
- 'url': event.find('url').text
+ #'url': event.find('url').text
}