I finished my PiCam project, and after it was live for a few days, I was bothered by what a pain it is to view images and video. This little system already has a lot going on, so I wanted to create a simple, nearly static website to view images and video. I decided to go with mustache templates because they make creating static sites easy. I also decided I should use one of the languages already installed, so I had my choice of C, C++, Ruby, Python, or Perl. Nothing beats Perl when it comes to creating something quick, so it was my choice. I decided to go against my own experience, and common wisdom, and use the system Perl. I was able to install a couple libraries I needed via apt, but there we some I was going to have to install via CPAN. And, again, went against my own experience and decided to use the already installed cpan executable. I ran into an issue I never had, though:
cpan failing with 'Cannot allocate memory'
I found that this is a common problem on low powered systems thanks to an answer on stackoverflow. The answer recommended installing cpanm, which is what I would usually just do in the first place. You can do that (admittedly unsafely) with:
curl -L https://cpanmin.us | perl - --sudo App::cpanminus
cpanm --sudo Template::Mustache
Once you fire that off, just go eat a sandwich. There's really no point in waiting. After cpanm was installed, I was able to install all my dependencies in a single go.
Once I had all my dependencies, I started writing the code that would scan the directory containing the images and video. I needed to match images and video of the same event and pull a bunch of details out of the file names so I could take actions in the web templates using them. The primary work is done in a single loop that looks through each file in the motion capture directory, uses a regular expression to pull the file name apart, and organizes everything in a hash for later use:
my %motion_capture;
my $capture_path = path($capture_dir);
my $split_re = qr/^((?:.*?\/)+)(\d+)-(\d+)(?:-\d+)?\.(\w+)$/;
foreach my $occurrence ($capture_path->children) {
# skip directories and dot files
next if !-f $occurrence || $occurrence =~ /^\./;
my ($dir_path, $capture_num, $timestamp, $extension) = ($occurrence =~ $split_re);
if ($extension eq 'jpg') {
$motion_capture{$capture_num}{image}{file} = $occurrence;
$motion_capture{$capture_num}{image}{timestamp} = $timestamp;
} else {
$motion_capture{$capture_num}{video}{file} = $occurrence;
$motion_capture{$capture_num}{video}{timestamp} = $timestamp;
}
}
I created a very simple HTML only site that leans on the power of the HTML5 video element to make magic. The highlighted motion detection image is used as the poster for the video, and the video itself is setup to use the built in controls:
<video controls width="640" height="480" type="video/mp4" poster="{{pic}}" src="{{vid}}"></video>
This gave me exactly what I needed to interact with all the videos I am capturing.
I tried this on a couple browsers, but for some reason it would only work on Chrome. This didn't make any sense because all that's there is HTML, well HTML and video. When I set up Motion, I accepted the configured default of mkv for video. This video format does not have good, cross-browser support. Mozilla web docs had me covered, as always, with an excellent summary of media format support across browsers. I decided to switch to mpeg4 because it has excellent cross browser support, including mobile browsers.
Finally, I needed to find a lightweight web server. The lighttpd project seems to fit the bill, so I gave it a shot. I've never used this server before, but setup was standard. I installed via apt, made a few changes to the config (/etc/lighttpd/lighttpd.conf), dropped my generated HTML in the base directory (/var/www/html), and restarted the server (sudo systemctl restart lighttpd.service). It has handled my requests flawlessly and isn't eating nearly any system resources:
pi@picam:~/picam_site $ ps aux --sort -rss
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
...
www-data 2711 0.0 1.2 9376 4600 ? Ss Sep27 0:34 /usr/sbin/lighttpd -D -f /etc/light
The Raspberry Pi Zero W that it is running on has 512 MB of RAM, so that's a whopping 6MB of RAM for lighttpd. Seems pretty light to me.