Whiteboard photo snapper

Six people live in my house. We don't have strong technology overlap (some folks in the house only use simple phones and others aren't keen on things like slack or similar). We've addressed this by centralizing around a large whiteboard in our kitchen space. This holds things like grocery lists, house announcements, and similar. I often do grocery shopping on my way home, but rarely remember to snap a photo of the list before leaving for work.

The compromise is a little raspberry pi which periodically sends photos of the whiteboard up to our house website. There were three main aspects of this project: capturing an image, putting it on the website, then setting it up to happen on a recurring basis.

Capturing the photo

For photo snapping, a roommate gave me an old webcam to use. I learned that you can use lsusb to list the USB entries. The output looks like this:

$ lsusb
Bus 001 Device 006: ID 046d:081b Logitech, Inc. Webcam C310
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

You can get more information on a device by specifying the bus and device. The verbose flag dumps out tons of output, but you can grep for width and height.

$ lsusb -s 001:006 -v | egrep "(Width|Height)"
...
        wWidth                           1024
        wHeight                           576
        wWidth                           1184
        wHeight                           656
        wWidth                           1280
        wHeight                           720
        wWidth                           1280
        wHeight                           960
...

This told me the maximum resolution for the webcam was 1280x960.

From here, we needed to snap a photo. I tried commands with vlc, guvcview and ffmpeg.

VLC

VLC had the benefit of popping up a live video feed of the webcam, which allowed me to validate it worked. This command didn't seem to stop on its own (which I believe it should have done with the vlc://quit directive..), which wasn't a good fit for my usecase.

vlc \
  -I dummy \
  v4l2:///dev/video0 \
  --video-filter scene \
  --no-audio \
  --scene-path /tmp/testing-for-video \
  --scene-prefix img_prefix \
  --scene-format png \
  vlc://quit \
  --run-time=1

guvcview

guvcview was good and supported doing the timing work on its own. This would mean I could keep it running as a daemon and have it dump files. Unfortunately, it kept popping up with a GUI frame, even though I didn't want one.

guvcview \
  --resolution 800x600 \
  --image /tmp/testing-for-video/my-test.png \
  --photo_timer 5 \
  --photo_total 1 \
  --gui=none

ffmpeg

ffmpeg seemed to do the simple thing of taking a photo of the webcam and dumping it into the place I asked it to.

ffmpeg -y \
       -f video4linux2 \
       -i /dev/video0 \
       -vframes 1 \
       -vf scale=1280x960 \
       /home/pi/kitchen-webcam-snaps/whiteboard_photo/latest.jpg

Getting the photo to the server

I made a new directory in the webroot for my server. I made a little 'whiteboard uploader' account on it and set up the necessary ssh keypair trusts. Originally, I was looking to save the image on disk and have a periodic rsync to the remote server. Given the lifespan of the SD card in my raspberry pi (notoriously short), we should try to write as little as possible.

To solve this, I mounted my uploader's home folder on the remote server to the local disk. The follow_symlinks portion is important because there is a symlink in that user's home directory to the webroot where the image should live.

sshfs -o follow_symlinks upload-user@pdxgrouphouses.org:/home/upload-user $PWD/kitchen-webcam-snaps

Putting it together

I have a simple crontab entry which runs every 4 hours.

0 */4   *   *  * /home/pi/webcam-snap.sh

This executes the script which will mount the remote folder locally if it's not done, then take a snap of the webcam.

#!/bin/bash

# Mount file system if it's not already mounted
(df | grep pdxgrouphouses.org) || \
sshfs -o follow_symlinks upload-user@pdxgrouphouses.org:/home/upload-user /home/pi/kitchen-webcam-snaps

ffmpeg -y \
       -f video4linux2 \
       -i /dev/video0 \
       -vframes 1 \
       -vf scale=1280x960 \
       /home/pi/kitchen-webcam-snaps/whiteboard_photo/latest.jpg