diff options
author | Zhiming Wang <zmwangx@gmail.com> | 2015-05-09 00:34:08 -0700 |
---|---|---|
committer | Zhiming Wang <zmwangx@gmail.com> | 2015-05-09 00:34:08 -0700 |
commit | 38f5c298302264edad7cdedff805ada67d6b0140 (patch) | |
tree | d73e123fb2197efda832f06e54777e382b2d87c5 | |
parent | 31246ba82cf7234a75505346520bf6c9653eec67 (diff) | |
download | my_new_personal_website-38f5c298302264edad7cdedff805ada67d6b0140.tar.xz my_new_personal_website-38f5c298302264edad7cdedff805ada67d6b0140.zip |
20150509 storyboard reached 0.1
Also fixed the bugs in pyblog introduced in the last revision and
tweaked the theme a bit.
Diffstat (limited to '')
-rwxr-xr-x | pyblog | 10 | ||||
-rw-r--r-- | source/blog/2015-05-09-storyboard-reached-01.md | 80 | ||||
-rw-r--r-- | source/css/theme.css | 4 |
3 files changed, 87 insertions, 7 deletions
@@ -310,9 +310,9 @@ def generate_index_and_feed(): feed.title = ET.fromstring("<title>%s</title>" % feed.title_text) # update time will be set after everthing finishes - for name in os.listdir(POSTSDIR): + for name in os.listdir(os.path.join(BUILDDIR, "blog")): if re.match(r"^[0-9]{4}-[0-9]{2}-[0-9]{2}.*\.html", name): - htmlpath = os.path.join(POSTSDIR, name) + htmlpath = os.path.join(BUILDDIR, "blog", name) entry = AtomEntry() with open(htmlpath, encoding="utf-8") as htmlfile: soup = bs4.BeautifulSoup(htmlfile.read()) @@ -501,7 +501,7 @@ def new_post(title): display_date = "%s %d, %d" % (date.strftime("%B"), date.day, date.year) title_sanitized = sanitize(title) filename = "%s-%s.md" % (filename_date, title_sanitized) - fullpath = os.path.join(postdir, filename) + fullpath = os.path.join(POSTSDIR, filename) if not os.path.isdir(POSTSDIR): if os.path.exists(POSTSDIR): os.remove(POSTSDIR) @@ -726,10 +726,6 @@ def gen_deploy(args): touch(latest_post) sys.stderr.write("\n") - # TODO: remove temporary code - print("deploying...") - return 0 - generate_blog(fresh=True) deploy(None) diff --git a/source/blog/2015-05-09-storyboard-reached-01.md b/source/blog/2015-05-09-storyboard-reached-01.md new file mode 100644 index 00000000..8e33d97e --- /dev/null +++ b/source/blog/2015-05-09-storyboard-reached-01.md @@ -0,0 +1,80 @@ +--- +title: "<code>storyboard</code> reached 0.1" +date: 2015-05-09T00:32:28-07:00 +date-display: May 9, 2015 +--- +For quite some time I've been working on a Python project called [`storyboard`](https://github.com/zmwangx/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](https://storyboard.readthedocs.org/en/0.1/index.html), + +> `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](https://pypi.python.org/pypi/storyboard) 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](https://github.com/zmwangx/storyboard/commit/e8a28e5a92f744157fedd03893fa8fe5a5e7d445). 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 down[^bogged-down] 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. + +[^bogged-down]: I was implementing stuff that I wouldn't ever need myself — for completeness, and that was not rewarding in the slightest. + +Anyway, here it is, the [0.1](https://github.com/zmwangx/storyboard/releases/tag/0.1) [release](https://pypi.python.org/pypi/storyboard/0.1). The badges certainly weren't bad: + +![`storyboard`'s got quite a few badges of honor](https://i.imgur.com/miOoX5Y.png) + +I created [an asciinema recording](https://asciinema.org/a/19782) to commemorate the release:[^solarized-dark] + +[^solarized-dark]: The screencast's color scheme is actually off in some places, since in my iTerm2 bold font is displayed as bold, not bright. + +<div style="width: 672px; margin: auto;"> +<script type="text/javascript" src="https://asciinema.org/a/19782.js" id="asciicast-19782" async></script> +</div> + +And, just to demonstrate `storyboard`, I re-screen-recorded the asciinema screencast with QuickTime, saved to [an MOV file](https://dl.bintray.com/zmwangx/generic/storyboard-0.1-walkthrough.mov), and ran it through my `metadata` and `storyboard`: + +``` +> metadata storyboard-0.1-walkthrough.mov +Filename: storyboard-0.1-walkthrough.mov +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 +Streams: + #0: Video, H.264 (Main Profile level 3.2), 672x846 (DAR 112:141), 60 fps, 1213 kb/s + +> storyboard storyboard-0.1-walkthrough.mov +Processing storyboard-0.1-walkthrough.mov +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 ``storyboard-0.1-walkthrough.mov`` (1964x2694), generated with the default settings by `storyboard 0.1`](https://i.imgur.com/c3E3M8R.jpg) + +Credit to `lolcat` for making my storyboard colorful. diff --git a/source/css/theme.css b/source/css/theme.css index 969e73c2..d7983bef 100644 --- a/source/css/theme.css +++ b/source/css/theme.css @@ -89,6 +89,10 @@ img { font-size: 10pt; } +.figure .caption code { + font-size: 9.5pt; +} + a { color: #333; } |