From ea846d3ea68d09a6f52f04eefd2a2e2f4b1a7b50 Mon Sep 17 00:00:00 2001 From: MaZderMind Date: Sat, 19 Apr 2014 16:40:55 +0200 Subject: [PATCH 1/8] documentation ftw! --- README.md | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..60be011 --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +Frab-Based Pre- and Postroll-Generator +=========================================== + +This is a scripted pre-, postroll and pause-clip generator. It takes a Frab/frab schedule-xml and artwork as svg and generates .dv-clips ready-to-use with the [VOC](https://c3voc.de/wiki/)-CRS (Continuous Recording System) or any other System. It can aĺso be modified to generate Lossless x264 or womething different if reqired. + +Following the requirements of the CRS-Setup it generates one postroll, one pause-sequence and multiple prerolls - one per Talk in your Schedule-xml, but it should be simple to modify this if your Setup needs it. + +Yes! That's what I want! +------------------------ +Okay, let's go. + + - Install python2.7, python-lxml, python-cssutils, inkscape and libav-tools + - Fork this repo on github and clone your personal fork to your local system. + - Copy one of the existing setups (I'd suggest sotmeu14 for a start). + - Open ```artwork/vorspann.svg``` (preroll template) in inkscape and modify it. You can also just create a new one. For the VOC-Setup you should use a Pixel-Resolution of ```1024x576``` (16:9 Aspect Ratio). + - Group things togeter that should be animated together (like subtitle and speaker-text) + - Use Flow-Text (in Inkscape drag an Area of Text instead of just placing a single line). This way the text will automatically wrap inside the specified area if it gets too long. + - Type Placeholder-Texts where the script should substitute content from your schedule-xml. By default the following placeholders are substituted + - ```$id``` - Talk-ID (useful in links to the Frab-Page) + - ```$title``` - Title of the Talk + - ```$subtitle``` - You guessed it... + - ```$personnames``` - Comma-Separated list of Speaker-Names + - Give IDs to the Objects and Groups you want to animate (Inkscape Shift-Ctrl-O) + - Edit your copy of make.py + - set ```scheduleUrl``` to the url of your schedule.xml-file + - modify vorspannFrames (preroll) - see section about the frame-generators below + - search for ```DEBUG MODE``` and comment the sections about abspann (postroll) and pause + - run ```./make.py --debug``` to generate your preroll first preroll + - if it looks good, duplicate vorspann.svg to abspann.svg (postroll) and pause.svg (pause-loop) and modify them according to your needs. You can use different IDs if required + - modify abspannFrames and pauseFrames liek before an test them using ```./make.py --debug``` + - it they look like you'd want them to, run ```make.py```. + - You can use any debianesque linux (can be headless) to generate the videos. More cores help more. + +The Frame-Generators +-------------------- +The animation sequence is controlled by the three frame-generator routines vorspanFrames, abspannFrames and pauseFrames. Each of them yields one tupel per frame. This Frame-Tupel contains one Sub-Tupel per Animated Element, which has one of two forms: + +### CSS-Style-Modifications +```('logo', 'style', 'opacity', 1),``` - locate object with id ```logo``` in the svg, parse its ```style```-attribute as css-inline-string and change the value of the css-property ```opacity``` to 1. The Tupel-Element ```'style'``` is fixed and declares the type of action which is applied to the specified element. All other tupele-mebers can be modified to suit your needs. + +To form an fase-in-opacity-animation, the frame-generator could look like this: + # three seconds of animation + frames = 3*fps + for i in range(0, frames): + yield ( + ('logo', 'style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), + ) + +```easeInCubic``` is an easing-function stolen from the [jquery-easing plugin](http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js) ([easing-cheat-sheet](http://easings.net/). They take 4 parameters: + - t: current time + - b: beginning value + - c: change In value + - d: duration (of time) + +So to fade the logo out, the generator yould look like this: +To form an ease-in-opacity-animation, the frame-generator could look like this: + # three seconds of animation + frames = 3*fps + for i in range(0, frames): + yield ( + ('logo', 'style', 'opacity', "%.4f" % easeInCubic(i, 1, -1, frames)), + ) + +By yielding multiple sub-tuples, you can animate multiple elements at the same time using different easings. Its up to you to find a combination that looks nice with your artwork. + +### XML-Attribute-Modifications +The other form a sub-tuble can have is ```('box', 'attr', 'transform', 'translate(0,0)')``` - locate object with id ```box``` in the svg, and set its ```transform```-attribute to ```translate(0,0)```. This can be used to animate things not specifiable by css - like the spacial translation of an object. A suitable generator, that animates the element ```box``` in an upward movement, could look like this: + # three seconds of animation + frames = 3*fps + for i in range(0, frames): + yield ( + ('box', 'attr', 'transform', 'translate(0,%.4f)' % easeOutQuad(i, 100, -100, frames) ), + ) + + +It works! It doesn't work! +-------------------------- +If it works, push your code to github. This way everybody can see which beautiful animations you created and we can all learn from each other. +If it doesn't work, ask [on IRC](irc://irc.hackint.org/voc), on [the Mailinglist](video@lists.ccc.de) or drop me a [personal mail](github@mazdermind.de) and we'll see that we can solve your problem. +If you think you found a bug, [file an Issue](https://github.com/MaZderMind/c3voc-toolz/issues). Or even better, fix it and [send a Pull-Request](https://github.com/MaZderMind/c3voc-toolz/pulls). From 4e6d5c5eebef94af53d8d7f8bfc8872ae6961b3e Mon Sep 17 00:00:00 2001 From: MaZderMind Date: Sat, 19 Apr 2014 16:41:41 +0200 Subject: [PATCH 2/8] cleanup and merge changes fro mthe eh14 project --- sotmeu14/make.py | 55 ++++++++++++++++-------------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/sotmeu14/make.py b/sotmeu14/make.py index de62807..d897172 100755 --- a/sotmeu14/make.py +++ b/sotmeu14/make.py @@ -8,19 +8,25 @@ import re import math import shutil import errno -import unicodedata import urllib2 -#import xml.etree.ElementTree as etree from lxml import etree +from xml.sax.saxutils import escape as xmlescape import cssutils import logging -import textwrap import tempfile import threading import multiprocessing from threading import Thread, Lock from Queue import Queue +# URL to Schedule-XML +scheduleUrl = 'http://www.fossgis.de/konferenz/2014/programm/schedule.de.xml' + +# For (really) too long titles +titlemap = { + #708: "Neue WEB-Anwendungen des LGRB Baden-Württemberg im Überblick" +} + # Frames per second. Increasing this renders more frames, the avconf-statements would still need modifications fps = 25 @@ -62,27 +68,6 @@ 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(): # 9 Sekunden @@ -199,7 +184,7 @@ def render(infile, outfile, sequence, parameters={}, workdir='artwork'): 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])) + svgstr = svgstr.replace(key, xmlescape(str(parameters[key]))) svg = etree.fromstring(svgstr) @@ -208,7 +193,6 @@ def render(infile, outfile, sequence, parameters={}, workdir='artwork'): 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 @@ -273,7 +257,7 @@ def events(): else: # download the schedule - response = urllib2.urlopen('http://www.fossgis.de/konferenz/2014/programm/schedule.de.xml') + response = urllib2.urlopen(scheduleUrl) # read xml-source xml = response.read() @@ -293,22 +277,22 @@ def events(): 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, ', '.join(personnames) ) + yield ( int(event.get('id')), event.find('title').text, event.find('subtitle').text or '', ', '.join(personnames) ) # debug-mode selected by --debug switch if debug: print "!!! DEBUG MODE !!!" - title = 'OpenJUMP - Überblick, Neuigkeiten, Zusammenarbeit/Schnittstellen mit proprietärer Software' render( 'vorspann.svg', - os.path.join('..', str(667)+".dv"), + '../intro.dv', vorspannFrames, { '$id': 667, - '$title': vorspannTitle(title), - '$personnames': 'Matthias Scholz' + '$title': 'OpenJUMP - Überblick, Neuigkeiten, Zusammenarbeit/Schnittstellen mit proprietärer Software', + '$subtitle': 'Even more news about OpenJUMP', + '$personnames': 'Matthias S.' } ) @@ -330,10 +314,6 @@ if debug: # threaded task queue tasks = Queue() -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, personnames) in events(): if id in titlemap: @@ -346,7 +326,8 @@ for (id, title, personnames) in events(): vorspannFrames, { '$id': id, - '$title': vorspannTitle(title), + '$title': title, + '$subtitle': subtitle, '$personnames': personnames } )) From 186ba55e3030775e53b8dddd3c91a73b37633d2f Mon Sep 17 00:00:00 2001 From: MaZderMind Date: Sat, 19 Apr 2014 16:52:55 +0200 Subject: [PATCH 3/8] use flowtext and let inkscape do the flowing for us --- sotmeu14/artwork/vorspann.svg | 63 ++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/sotmeu14/artwork/vorspann.svg b/sotmeu14/artwork/vorspann.svg index 57df891..0332224 100644 --- a/sotmeu14/artwork/vorspann.svg +++ b/sotmeu14/artwork/vorspann.svg @@ -168,9 +168,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="0.98994949" - inkscape:cx="83.861659" - inkscape:cy="280.49488" + inkscape:zoom="5.6" + inkscape:cx="167.31824" + inkscape:cy="174.4509" inkscape:document-units="px" inkscape:current-layer="box" showgrid="false" @@ -242,12 +242,12 @@ + height="681" + id="image2993" + x="0" + y="471.36218" /> @@ -275,25 +275,36 @@ sodipodi:linespacing="125%" id="text4531" y="881" - x="122" + x="119.29951" style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter4858);font-family:Sans" xml:space="preserve">$personnames - $title - + $title From 9ccdc6c3a85ade8a846b4beac90b824c92d3531b Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 19 Apr 2014 16:54:04 +0200 Subject: [PATCH 4/8] fix code display on github --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 60be011..445decd 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ The animation sequence is controlled by the three frame-generator routines vorsp ```('logo', 'style', 'opacity', 1),``` - locate object with id ```logo``` in the svg, parse its ```style```-attribute as css-inline-string and change the value of the css-property ```opacity``` to 1. The Tupel-Element ```'style'``` is fixed and declares the type of action which is applied to the specified element. All other tupele-mebers can be modified to suit your needs. To form an fase-in-opacity-animation, the frame-generator could look like this: + # three seconds of animation frames = 3*fps for i in range(0, frames): @@ -54,6 +55,7 @@ To form an fase-in-opacity-animation, the frame-generator could look like this: So to fade the logo out, the generator yould look like this: To form an ease-in-opacity-animation, the frame-generator could look like this: + # three seconds of animation frames = 3*fps for i in range(0, frames): @@ -65,6 +67,7 @@ By yielding multiple sub-tuples, you can animate multiple elements at the same t ### XML-Attribute-Modifications The other form a sub-tuble can have is ```('box', 'attr', 'transform', 'translate(0,0)')``` - locate object with id ```box``` in the svg, and set its ```transform```-attribute to ```translate(0,0)```. This can be used to animate things not specifiable by css - like the spacial translation of an object. A suitable generator, that animates the element ```box``` in an upward movement, could look like this: + # three seconds of animation frames = 3*fps for i in range(0, frames): From 8bda01a5ec3795f83c69193ab2be0f0f7c1a2291 Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 19 Apr 2014 16:55:25 +0200 Subject: [PATCH 5/8] fix missing bracket --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 445decd..e31f81a 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ To form an fase-in-opacity-animation, the frame-generator could look like this: ('logo', 'style', 'opacity', "%.4f" % easeInCubic(i, 0, 1, frames)), ) -```easeInCubic``` is an easing-function stolen from the [jquery-easing plugin](http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js) ([easing-cheat-sheet](http://easings.net/). They take 4 parameters: +```easeInCubic``` is an easing-function stolen from the [jquery-easing plugin](http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js) ([easing-cheat-sheet](http://easings.net/)). They take 4 parameters: - t: current time - b: beginning value - c: change In value From 7f758ae74c767456c3fe13b52e8b890d3fe100fa Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 19 Apr 2014 20:43:28 +0200 Subject: [PATCH 6/8] fix text issues --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index e31f81a..5ab8051 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ The animation sequence is controlled by the three frame-generator routines vorsp ### CSS-Style-Modifications ```('logo', 'style', 'opacity', 1),``` - locate object with id ```logo``` in the svg, parse its ```style```-attribute as css-inline-string and change the value of the css-property ```opacity``` to 1. The Tupel-Element ```'style'``` is fixed and declares the type of action which is applied to the specified element. All other tupele-mebers can be modified to suit your needs. -To form an fase-in-opacity-animation, the frame-generator could look like this: +To form an fade-in-opacity-animation, the frame-generator could look like this: # three seconds of animation frames = 3*fps @@ -54,7 +54,6 @@ To form an fase-in-opacity-animation, the frame-generator could look like this: - d: duration (of time) So to fade the logo out, the generator yould look like this: -To form an ease-in-opacity-animation, the frame-generator could look like this: # three seconds of animation frames = 3*fps From c19606f42aa2d08f1853d70bca606f1dc48d002f Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 19 Apr 2014 20:43:55 +0200 Subject: [PATCH 7/8] more typos --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ab8051..0a8f6e3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Frab-Based Pre- and Postroll-Generator =========================================== -This is a scripted pre-, postroll and pause-clip generator. It takes a Frab/frab schedule-xml and artwork as svg and generates .dv-clips ready-to-use with the [VOC](https://c3voc.de/wiki/)-CRS (Continuous Recording System) or any other System. It can aĺso be modified to generate Lossless x264 or womething different if reqired. +This is a scripted pre-, postroll and pause-clip generator. It takes a Frab/frab schedule-xml and artwork as svg and generates .dv-clips ready-to-use with the [VOC](https://c3voc.de/wiki/)-CRS (Continuous Recording System) or any other System. It can aĺso be modified to generate Lossless h264 or something different if reqired. Following the requirements of the CRS-Setup it generates one postroll, one pause-sequence and multiple prerolls - one per Talk in your Schedule-xml, but it should be simple to modify this if your Setup needs it. From dd1b15cf018e59444b4a408a2ca4ff4f46903154 Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 19 Apr 2014 20:44:52 +0200 Subject: [PATCH 8/8] even more text fixes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0a8f6e3..ee9ed34 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ Okay, let's go. - Edit your copy of make.py - set ```scheduleUrl``` to the url of your schedule.xml-file - modify vorspannFrames (preroll) - see section about the frame-generators below - - search for ```DEBUG MODE``` and comment the sections about abspann (postroll) and pause - - run ```./make.py --debug``` to generate your preroll first preroll + - search for ```!!! DEBUG MODE !!!``` and comment the sections about abspann (postroll) and pause + - run ```./make.py --debug``` to generate your first preroll - if it looks good, duplicate vorspann.svg to abspann.svg (postroll) and pause.svg (pause-loop) and modify them according to your needs. You can use different IDs if required - modify abspannFrames and pauseFrames liek before an test them using ```./make.py --debug``` - it they look like you'd want them to, run ```make.py```.