Wednesday, February 17, 2010

Perl script for creating time lapse videos from a GoPro HD camera

A few months ago, I bought a GoPro HD helmet cam. It takes 1080p video at 30fps, and is basically bomb proof. Video is not the only thing this little beast does, however. It has a mode to take continuous still pictures at given intervals ( 2,5,30,60 seconds ). Because it has a rather nice glass, wide angle lens, you can capture a lot in a single shot. This camera basically does all the hard work for you, so all you have to do is stitch the pictures back together. If you remember correctly (and you probably don't, because let's face it, who reads this blog?), I did a post on how to use ffmpeg to do stuff. In there I showed how you could use ffmpeg to create time lapse videos from stills. Basically you just do the following:

ffmpeg -r 15 -b 1800 -i IMG_%04d.JPG movie.avi

Anyway, this works for the GoPro as well (except the regex for the image name), but you get a cropped square picture, and pretty poor compression. So how do we fix that? Like so:

ffmpeg %d.JPG -r 12 -croptop 180 -cropbottom 180 -s hd720 -vcodec ffv1 movie.avi

Again, the name regex is incorrect in this case, but I'm just using this for demostration. So, this solves the problem of formatting the video to your liking, but there are two other issues that need to be accounted for:

1. When taking more >1000 images the GoPro makes a new folder and starts the image count over again. So your images end up in folders like 100MEDIA, 101MEDIA, so on and so forth.

2. You now have images with the same name in multiple folders.

The problem with this is the way ffmpeg handles the input of still images. It would be nice if you could just input *.jpg, but you can't. Because you have to have your images named sequentially, you can't delete pictures out of the sequence either.

Because of these problems, I wrote a perl script that grabs all the images in any of the MEDIA folders, resizes and renames them, by modified time, and then puts then in a single folder. It then creates the movie for you. Here is the script:


#!/usr/bin/perl -w

@files = <*MEDIA/*.JPG>;

@sorted = sort{ -M $b <=> -M $a } @files;

mkdir( "resize" );
for($i = 0; $i <= $#sorted; $i++)
{
$j = $i+1;
`convert -resize 2048 $sorted[$i] resize/$j.JPG`
}

`ffmpeg -y -i resize/%d.JPG -r 12 -croptop 180 -cropbottom 180 -s hd720 -vcodec ffv1 movie.avi`;


To make this script run on Windows:

1. Install Perl from ActiveState - ActivePerl
2. Install ImageMagick - Windows Bins
3. Save the above script into a file called "makeMovie.pl"
4. Copy all the MEDIA folders from your GoPro to a folder on your machine once you've captured your images
5. From the command line, switch into the folder with your MEDIA folders and copy the perl script into the folder
6. Run the perl script

To run this on Linux (Ubuntu):

1. Install imagemagick - sudo apt-get install imagemagick
2. Copy the above script into a file called "makeMovie.pl"
3. From the command line chomod the file - chmod +x makeMovie.pl
4. Copy your MEDIA folders from your GoPro to a folder
5. Copy your perl script into the same folder as the MEDIA folders
6. Run the perl script

Here's a few examples of what you get:



And one from skiing: