Animating a Git Repository

Montage of Hensen ex Machina, issue 1

To celebrate EPT's first issue, Round Midnight, we made a two minute animation of all 24 pages being drawn:

If the ogg video doesn't play in your browser, you can watch it on YouTube or install an ogg-compatible video player like VLC.

But wait, there's more!

Chapter 2

Montage of Hensen ex Machina, issue 2

Here's the animation for chapter 2, Sweet as Sin:


Here's how we made the animation, in case you'd like to play along at home:

  1. Install Inkscape, ImageMagick, Git, Python, Ffmpeg, and Ffmpeg2theora. On Ubuntu Linux, you can do this via:
    apt-get install inkscape imagemagick git-core python ffmpeg ffmpeg2theora
    If you want to include a soundtrack, you'll also want oggz and vorbis-tools:
    apt-get install oggz-tools vorbis-tools
  2. Make a new directory for your comic and initialize a git repository:
    mkdir ~/ElectricPuppetTheatre
    cd ~/ElectricPuppetTheatre
    git init
    (All of the remaining commands will be run from this directory)
  3. Use Inkscape to generate a template for your comic pages, or download ours. Save it as ~/ElectricPuppetTheatre/Template.svg. If you create your own template, make the width:height ratio 2:3 (e.g. 1200:1800).
  4. Add the template to your git repository:
    git add Template.svg
    git commit Template.svg -m "Template for new pages"
  5. Make a subdirectory for the first issue and initialize the pages from the template:
    mkdir 001
    for i in {01..24}; do
      cp Template.svg 001/"Page-${i}.svg";
  6. Draw each page in Inkscape. Pause periodically to commit your work to the git repository. The first time you commit a page, you will need to add it to the repository:
    git add 001/Page-01.svg
    git commit 001/Page-01.svg -m "Started page 1 of issue 1"
    For subsequent commits, you can skip the add step:
    git commit 001/Page-01.svg -m "Inked first panel"
  7. Now we're ready to animate the repository! First, make a working directory for the rendered images:
    mkdir IssueMovie
  8. Use our script to render a montage of the pages for each commit in the archive:
    chmod "a+x"
    Here's what the script is doing behind the scenes:
    • Find all of the commits that touch this issue with git log.
    • Find the pages touched by a particular commit with git show.
    • Extract each page version from the repository with git cat-file blob.
    • Render each page to a 160x240 pixel PNG with inkscape.
    • Render each set of pages as an 8x3 grid with the montage tool from ImageMagick.
    (This step took about 40 minutes to render 656 commits on 32-bit Ubuntu 10.04 on a 2GHz T7300).
  9. Move to the working directory for the final rendering steps:
    cd IssueMovie
  10. Use ImageMagick to convert the PNG (lossless) frames to JPEGs, setting quality to 100% to avoid lossy compression:
    for i in frame*.png ; do 
      convert -quality 100 $i `basename $i png`jpg; 
  11. Use ffmpeg2theora to combine the frames into an ogg video:

    ffmpeg2theora -F 6 -v 10 -i frame%04d.jpg -o MOS.ogv
    -v 10 gives the highest image quality, which is necessary to keep the pencils from blurring and to avoid artifacts on flat images, and -F sets the frame rate.

    For Round Midnight, we had 656 frames, for a length of 1 minute 49 seconds at 6 frames per second. Combining this with a slightly longer audio track gives the nice effect of holding for a few seconds on the final image; we used a 2 minute 14 second mix of Sara and Louis jamming on the Electric Puppet Waltz, converting it to ogg audio with vorbis-tools:

    oggenc -n MOI.oga GuitarWaltz.wav
    and then combining (muxing) the audio and video streams with oggz-tools:
    oggz merge -o ept1.ogv MOS.ogv MOI.oga

Bonus: Animating for YouTube

The instructions above work for making an animation in the open, patent-safe OGG format. Unfortunately, there are many places that OGG won't play. Mark Pilgrim's Dive Into HTML5 had an excellent discussion of the hairy details of distributing video on the web, the short version of which is:

There is no single combination of containers and codecs that works in all HTML5 browsers.
More importantly, it is impossible to support all platforms without using patent-encumbered formats. Rather than deal with this directly, we will punt the problem to Google by uploading our video to YouTube which supports uploads in the patent-safe WebM format.

Here are the things we need to know about YouTube:

Got that? Okay, here we go:

  1. Prepare your frames by following steps 1-10 of the OGG instructions above.
  2. Pad out the video portion to match the audio portion using additional "frames" symlinked to the last real frame. Our last frame was frame0656.jpg. We added a "closing credit" to this in inkscape, giving frame0657, then added 142 symlinked copies (23 seconds at 6 fps):
    for i in {658..800}; do ln --symbolic frame0657.jpg "frame0${i}.jpg"; done
  3. Use Ffmpeg to generate a WebM video, using our previous OGG audio track:
    ffmpeg -qscale 1 -r 6 -b 9600 -i frame%04d.jpg -vcodec libvpx -i MOI.oga ept1.webm

Ffmpeg has WebM support starting with version 0.6. If your system copy is older than this (as was the case for us on Ubuntu 10.04) you can compile a single-user bleeding-edge copy without overwriting the system copy. Here's how:

  1. Make sure you have the GNU toolchain:
    sudo apt-get install build-essential
  2. Make a build directory:
    mkdir ffmpegwebm
    cd ffmpegwebm
    mkdir local
  3. Download and compile the latest V8 code, targeting our build directory:
    git clone
    cd libvpx
    ./configure --prefix=../local/
    make && make install
    cd ..
  4. Download and compile the latest Ffmpeg code, enabling the WebM codecs:
    git clone git://
    cd ffmpeg
    ./configure --prefix=../local/ --enable-libvorbis --enable-libvpx --enable-gpl \
    --extra-cflags=-I../local/include/ --extra-libs=-L../local/lib/
    make && make install
    cd ../..
    (The --extra config flags tell autotools to look for the V8 headers and libraries in our local build directory)
  5. To reference the local build, step 3 above is now:
    ffmpegwebm/local/bin/ffmpeg -qscale 1 -r 6 -b 9600 \
    -i frame%04d.jpg -vcodec libvpx -i MOI.oga ept1.webm

"Generic" animation with Gource

EPT source repository

Gource is a nifty tool for animating repositories that track files that are less obviously visual (i.e., anything other than comics). Rather than rendering the files directly, it animates the file system tree with contributors flitting hither and thither through the code as they hack on it.

We used gource to animate a merge of the full comic repository (currently tracking 6 of the 12 chapters of Hensen ex Machina) with the repository that manages our website:

If you'd like to try gource yourself, it's super easy. On Ubuntu Linux it's as simple as:

apt-get install gource
cd ~/my/favorite/repository/
gource ./

The above example will display the gource animation in an interactive window (which allows you to move the camera, inspect user and file details, etc.) To save the animation as a movie, use the -o option to generate a PPM stream and pipe it through Ffmpeg. Here's how we generated our animation:

# Create a temporary repository merging the comics with the website
cd ~/
mkdir temp
cd temp
git clone ~/ElectricPuppetTheatre/
git remote add website ~/
git pull website master
# Generate the animation
gource  -i 0 -s .01 --hide usernames,date --default-user-image \
htdocs/css/hand1.png --key -o - ./ | ffmpeg -y -r 60 -f image2pipe \
-vcodec ppm -i - -vcodec libvpx -b 10000K gource.webm
# And mux in an appropriately sized ditty courtesy of Janice, Pria, and Sara
#  (the crunchy metal tone is a Mitchell acoustic guitar with a new set of
#   Dunlop strings filtered through the "Tight Rock" preset in Rakarrack)
ffmpeg -i gource.webm -vcodec copy -i MetalDitty.oga gource2.webm
For more details on making this sort of video, see the Gource wiki.

Questions, comments, corrections? Please send any and all feedback to markv [at]