Audio sample from Take Time, off The Books’ album, The Lemon of Pink, used with permission. Thanks Nick and Paul!
This is one I’ve been wanting to do for a while. My last two time-lapses were both stationary (Pine St and Lombard St), so I was ready to go mobile. And what better subject than San Francisco’s famed cable cars.
Every day I see the cable cars as I cross Powell to and from work. But I don’t ride them very often, because, well, they’re pretty pricey to ride. $5 without transfers. They are really more like amusement park rides masquerading as public transit.
In that spirit, I rode the full length of the California line from Van Ness to Market and back again to make this video. It was a lot of fun.
Most people know Lombard Street as the “the crookedest street in the world”, but it’s also a major thoroughfare for US-101 traffic going to and from the Golden Gate Bridge. Given that I started my California life in the North Bay, Lombard has always felt like the gateway to San Francisco for me. Whenever I return from a trip up north, it’s not until I’m driving along Lombard that I feel like I’m home.
I’ve always thought the view looking west down Lombard from Larkin was particularly expansive. It’s up on the side of Russian Hill, so one can see from Van Ness all the way to Richardson Ave unobstructed. The other night I decided to head out there with my tripod and try my hand at another time-lapse video. I started around 10 o’clock and took pictures until my camera battery died an hour and a half later.
When I got back home and stitched the images into a video, I discovered an unintentional artifact. Because I’d zoomed the camera all the way in on Lombard, its attempt at nighttime auto-focusing caused slight fluctuations in the focal length (I assume) creating an odd pulsating effect in the video. Not what I had expected, but a happy accident, as it mated especially well with the beat-heavy techno track Stephanie created for me using Looptastic on her iPhone.
As much as I use and enjoy services like YouTube, Vimeo, and Flickr, I’ve never been a big fan of entrusting my content to large, centralized, corporate services. Yes they’re here today, yes they seem stable and secure, but will they always be around? Even while they are still in business, I’ve never liked the idea that the content I create effectively lives on their site, so they end up profiting from my page views. And frankly, centralization like that is counter to the distributed architecture at the core of the internet.
That said, this is as much to aid my memory for any future web video projects as it is to assist anyone else in a similar endeavor. It condenses about 18 hours of experimentation, research, and testing into a set of simple, easy to follow steps.
Step 1: Make some video
The easiest way to do this is with a point-and-shoot digital camera. I admit that I know absolutely nothing about video-editing, and even less about doing so on Ubuntu. That is fodder for a future post, I suppose. But honestly, we’re talking about short videos for the web. Who cares about editing?
Since the audio quality from most point-and-shoot cameras is rather poor, most people tend to replace it with music if it’s not critical to the content of the video. I also know very little about audio editing, but I can coax Audacity into cutting an audio track down to the length of the video, and adding a fade-in and a fade-out. Once I’ve got a wav or mp3 that I want to use, here’s the command to merge the audio and the video:
Until all browsers support the new HTML5 <video> element, Flash Video (.flv) is the de facto standard for streaming video on the web. At this point it helps to know what dimensions to encode the video to. I discovered that both the width and height need to be multiples of 2, as this helps with the data compression. On my blog, video with a 4:3 aspect ratio (like TV) translates to pixel dimensions of 380×284. Here is the FFmpeg command to convert an mp4 video to a reasonably compressed flv video:
Several sources recommended the JW FLV Media Player, which looks a little homely at first, but turns out to be infinitely configurable, as well as skinnable. I wanted my video player to resemble the Vimeo-style controls as much as possible (overlayed, display on hover, etc) and sure enough they had a skin, Bekle, that looked just like it.
Minimally, the player requires that I host a single file, player.swf, and optionally a second swf file for the skin. The look and feel of the player can then be modified by many configuration options set via flashvars. One of the flashvars worth mentioning, config, makes it possible to bundle up a series of common flashvars settings into a simple XML format, so I don’t have to repeat settings that I plan to implement site-wide (like colors, the skin URL, etc).
The documentation recommends using v1.5 of the swfobject.js library to embed the Flash Video on the page, but I found that to be overkill for my purposes. I write most of my posts in straight HTML, so I’d prefer to limit the content of my posts to HTML, rather than mess with inline JavaScript. That and WordPress tends to choke on inline JavaScript in posts.
The real benefit of swfobject is its battle-tested cross-browser compatibility. By foregoing that route, I had to figure out what combination of <object>, <embed>, and <param> tags was the most compatible across the latest versions of the big 3: Firefox 3, Safari 4, and Internet Explorer 8. As it turns out Firefox and Safari were the most forgiving, and managed to load and play every combination of tags I threw at them. IE would only load the video if it had a param tag of type “movie”. Ohhhhk.
As an aside: after letting IE6 lie fallow for 5 years, and then reawakening after of furious advances made by Mozilla, Apple, Opera, Adobe, and now Google, Microsoft has yet to support the object tag standard as defined in the HTML 4.01 spec from 1999. Embarrassing.
Anyway, I’m not about to stoop to support IE’s backwardness in every post that I embed video, so I wrote a quick WordPress plugin that would inject the necessary movie param tag into the object tag for any IE user-agents.
<?php
/*
Plugin Name: Add movie param to object tags for IE
Description: This plugin gets the data attribute from an <code><object></code> tag and adds it in as a <code><param name="movie" value="[data]"/></code> for Internet Explorers
Author: Justin Watt
Version: 1
Author URI: http://justinsomnia.org
*/
add_filter("the_content", "add_movie_param_to_object_tags_for_ie");
function add_movie_param_to_object_tags_for_ie($content)
{
if (isset($_SERVER['HTTP_USER_AGENT']) && (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false)) {
return preg_replace("#(<object\s+[^>]*?data\s*=\s*('|\"))([^'\"]+)(.*?)(</object>)#si", "$1$3$4<param name=\"movie\" value=\"$3\"/>$5", $content);
} else {
return $content;
}
}
Essentially there are two ways to make a time-lapse video, regardless of the tool. I chose FFmpeg because it was easy to use, and available on Ubuntu.
From Video
With the first, you take an existing video, recorded at 25 (or 30) frames per second, and strip out all the frames except for one every second. This gives you an effective speedup of 25x. For example, by extracting one frame per second from a 60 minute video, you can drop the length to a much more watchable, entertaining, and web-friendly 2.4 minutes (not to mention a smaller, easier to download file size).
Here’s a bash script (timelapsify.sh) that uses FFmpeg to convert a normal video into a time-lapse video. It takes an input video filename and an output video filename as command line arguments:
The other way is to set up your camera so that it takes a photo every 1 or 2 seconds. Many of the popular Canon Powershot cameras can be customized with a non-destructive, non-permanent firmware enhancement called CHDK which you can use to run a custom intervalometer (like this one). Or your camera may offer this functionality natively.
Keep in mind that 2 minutes of video represents 3000 distinct photos at 25 frames/second. Your battery or your memory card may run out before you get that far, so if possible, plug your camera in and set it to its lowest resolution setting.
One FFmpeg-specific caveat: in order to assemble photos into a video, you need to name them sequentially, starting from 1. So I wrote a simple little command line PHP script to rename the series of image filenames that my camera produced (IMG_3550.JPG, IMG_3551.JPG, IMG_3552.JPG) into something a little more FFmpeg-friendly (frame_1.jpg, frame_2.jpg, frame_3.jpg):
And here’s the FFmpeg command to assemble all those renamed “frame” jpgs into an actual mp4, H.264-encoded video (very much like timelapsify.sh above):
The 41 second time-lapse is made up of 1,001 photos taken out our window over the course of an hour and 40 minutes. I set the camera to take a photo every 2 seconds (which increased to every 6 seconds as the sun set), and it did so until the battery died.
For more information on how I made this, check out: