This blog has been archived.
Visit my home page at

storyboard reached 0.1

For quite some time I've been working on a Python project called storyboard, and today I finally released the 0.1 stable (or you can think of it as 1.0).

As described on the index page,

storyboard is a FFmpeg-based customizable video storyboard generator with metadata reporting directly embedded in the generated images. Reported metadata fields include, but are not limited to, title, filename, file size, SHA-1 digest, container format, duration, pixel dimension, display aspect ratio (DAR), scan type (progressive, interlaced, or telecined), frame rate, and per-stream metadata (type, codec, profile, dimensions, bitrate, etc.).

And the motivation was

storyboard was inspired by the storyboards I frequently encounter on video-sharing Internet forums, mostly generated by proprietary video players. Those storyboards often come with video/file metadata bundled, which I see as a great all-in-one solution for video sharing, saving one the labor of typing multiple console commands, copying and pasting output, and worrying about the forum’s crappy formatting. However, I, for one, dislike proprietary players. Also, those storyboards are usually ugly and uninformative, using stupid fonts and lacking crucial information that hackers look for (e.g., hash). Therefore, I developed this customizable storyboard generator for hackers.

The project itself isn't very important, and I don't see any possibility of it gaining recognition; but its educational value to me was pretty huge. This is the first full package I ever developed, in the sense that it's complete with documentation, test suites, continuous integration and tested portability, as well as distributed to a package index (PyPI in this case). Here's what I observed and learned:

  1. It's just really different from casual hacking, where I would try to achieve what I need in the shortest amount of programmer time possible, drop hard-coded values (even OAuth tokens) in scripts, leave things undocumented, etc. I'm a perfectionist so my casual code is usually not so bad, but storyboard is just different — to ensure quality of API and CLI, I wrote more documentation than actual code. Through this project I realized how hard real-world coding (or idealized real-world coding) is: the initial 10% is excitement, and the rest is just chores (compare that to casual hacking, where at least 30% is excitement).

  2. Write once, debug everywhere. Not really, but ensuring portability is really difficult. Trying to debug something on a platform which I can't lay my hands upon is insanely frustrating. This afternoon I spent a long time trying to pin down a weird hanging bug on AppVeyor; the complete process is documented in this squashed commit. In the end the bug wasn't in my program, but in that specific version of FFmpeg (which I wouldn't believe since FFmpeg is really stable from my experience), or that specific version of FFmpeg combined with AppVeyor, or that specific version of FFmpeg combined with AppVeyor combined with Azure, or... who knows. The only thing I could say is it was not in my program, because I could reproduce the infinite loop in ffprobe even before I launched my program... Anyway, in this case I can lay my hands on the platform, just indirectly and painful. What about real world development where developers need to handle bug reports from users who could have broken everything? I don't want to imagine.

  3. The project was a clear manifestation of Hofstadter's law:

    It always takes longer than you expect, even when you take into account Hofstadter's Law.

    Enough said; so true. In fact, towards the end of the development cycle I got pretty bogged down1 and stopped for a while to work on renovating this blog (60% excitement!). Meanwhile, I was too busy with other parts of life, so I rushed towards the stable 0.1 release in the past two days, dropping several ideas I wanted to implement (for completeness). Although I "rushed", it still took at least four times as long as I expected.

Anyway, here it is, the 0.1 release. The badges certainly weren't bad:

storyboard's got quite a few badges of honor

storyboard's got quite a few badges of honor

I created an asciinema recording to commemorate the release (the original asciicast is here):2

And, just to demonstrate storyboard, I re-screen-recorded the asciinema screencast with QuickTime, saved to an MOV file, and ran it through my metadata and storyboard:

> metadata
File size:              60418244 (57.7MiB)
Container format:       QuickTime movie
Duration:               00:06:36.30
Pixel dimensions:       672x846
Display aspect ratio:   112:141
Scan type:              Progressive scan
Frame rate:             60 fps
    #0: Video, H.264 (Main Profile level 3.2), 672x846 (DAR 112:141), 60 fps, 1213 kb/s

> storyboard
Crunching metadata...
Trying to determine scan type...
Inspecting frame 40/40...
Generating main storyboard...
Extracting frame 16/16...
Generating thumbnail 16/16...
Tiling thumbnails...
Generating metadata sheet...
Computing SHA-1 digest...
57.7MiB 0:00:00 [ 571MiB/s] [=================================================================================>] 100%
Generating promotional banner...
Assembling pieces...

storyboard saved to: /tmp/storyboard-se3fbiif.jpg

Here's the actual image:

storyboard of (1964x2694), generated with the default settings by storyboard 0.1

storyboard of (1964x2694), generated with the default settings by storyboard 0.1

Credit to lolcat for making my storyboard colorful.

  1. I was implementing stuff that I wouldn't ever need myself — for completeness, and that was not rewarding in the slightest.↩︎

  2. The screencast's color scheme is actually off in some places, since in my iTerm2 bold font is displayed as bold, not bright.↩︎