15 October 2006

Making a Time-Lapse Movie

Our webcam now has a time-lapse movie for today and yesterday. Or rather it will have one for yesterday after it’s been running for more than one day. This was achieved by saving off a copy of every webcam image into a directory for the day and then processing them with some free tools. In this post I walk through the process we use to make this happen.

First, my Gawker image fetch project grew a new -d directory option to save JPEG files into a directory. We have to save the images if we expect to make a movie out of them at some point. It should be noted this requires a bit of disk space. With a new image every 30 seconds, a day of images occupies nearly 150 megabytes of disk.

Now that we have the images, we want to turn them into a movie. For this we start with netpbm.
Using jpegtopnm we convert the series of JPEG images into a series of raster images that the next software can deal with.

Next in line is mjpegtools. It has a tool ppmtoy4m that takes the series of raster images and renders it into a “Y4M” video file. The Y4M format adds useful information to traditional YUV video data, such as the size of the image and the framerate. It’s worth noting that this Y4M data is mainly raw video frames, which results in a fairly large file if we write it to disk.

Lastly, we want to use x264 to convert the Y4M data into a highly-compressed movie that your can view with your web browser. The only problem is that x264 treats it’s input as raw YUV data by default and has no switch to make use of Y4M data, it only uses Y4M data if the input file is named something.y4m.

But we don’t want to save a very large Y4M file to our disk every 10 minutes when we’re generating the movie, only to throw the file away when we’re done. We want to just send it the input directly. All the other tools allow us to pipeline the commands together so as one command processes some data it passes it’s output straight on to the next command. So now it was time to fix x264 to let us pipeline the way we want:

I sent this message to the x264-devel list this morning.

This patch adds the long option “--y4m-input” which sets b_y4m. It
also avoids any evaluation that might result in setting both b_avis
and b_y4m.

In order to politely handle pipelines from mjpegtools and other y4m
sources, b_y4m must be set even if the filename is ”-”. Sadly, that filename
does not end in ”.y4m”.

The patch is available here.

In the longer term it would be useful to offer options for all
accepted input and output types on stdin and stdout to avoid having to
create (rather sizable) temp file everywhere.

So with that fix in place now we can send a series of JPEG files through the pipe of jpegtopnm, ppmtoy4m, x264 and wind up with a time-lapse movie you can watch.

Update: The files are now also mangled by the qt-faststart program (part of ffmpeg) which will let QuickTime (and possibly other players) start playback immediately before the whole file is loaded. I’ll try to get this change committed to svn soon.

No comments: