Linux webcam timelapse

KewBridge-20191110-121501

This weekend I decided to set up an unused webcam to capture a timelapse of London. There were several things to consider:

  • Where to connect the camera
  • Software to capture photos
  • Accessing and presenting the photos

I connected the camera to a different machine (not the server) that I would be willing to keep switched on. I used guvcview to connect to the camera and check the configuration. Next, I installed and set up motion and set it to take a snapshot every 300 seconds and also stream a live feed to a locally accessible website. This all worked successfully.

My webcam of choice was the Logitech C920, which has a 3:2 2304×1636 sensor, however it is limited to [email protected] for video, and can only manage two photos per second at the full sensor resolution. Since I configured the webcam to take photos every five minutes I hoped to use the full sensor resolution, however, due to motion’s main use case being for detecting motion (hence the name) this was impossible. Also, motion had a very high load on the machine and caused the fan to be noticeably louder, and I was not willing to have so much noise in the room this machine is in.

So I turned instead to a combination of ffmpeg and cron to capture photos. ffmpeg supports input from video devices on linux, so this was a viable alternative. After spending a significant amount of time messing with the configuration options for my specific webcam, I managed to retrieve full-sensor images.

My webcam configuration command:

v4l2-ctl -c brightness=128 
\ -c contrast=128 
\ -c saturation=150 
\ -c sharpness=190 
\ -c backlight_compensation=1 
\ -c exposure_auto_priority=1 
\ -c focus_absolute=0 
\ -c focus_auto=0 
\ -c led1_mode=0

And my ffmpeg command:

ffmpeg -f video4linux2 # V4L2 interface
\ -input_format yuyv422 # raw video input (to access full sensor)
\ -framerate 2 # limit framerate to 2, otherwise V4L2 automatically selects 1080p instead
\ -video_size 2304x1536 -s 2304x1536 # set the desired capture size
\ -i /dev/video0 # my input device
\ -frames 1 # how many frames to take
\ -vf drawtext="fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf:text='%{localtime\:%Y-%m-%d %T}':x=20:y=20:fontcolor=white" # date + time watermark on the photo
\ /var/www/html/motion/KewBridge-$(date +%Y%m%d-%H%M%S).jpg

So putting this into cron, it looks like this (escape % symbol):

@reboot v4l2-ctl -c brightness=128 -c contrast=128 -c saturation=150 -c sharpness=190 -c backlight_compensation=1 -c exposure_auto_priority=1 -c focus_absolute=0 -c focus_auto=0 -c led1_mode=0
*/5 * * * * ffmpeg -f video4linux2 -input_format yuyv422 -framerate 2 -video_size 2304x1536 -s 2304x1536 -i /dev/video0 -frames 1 -vf drawtext="fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf:text='\%{localtime\:\%Y-\%m-\%d \%T}':x=20:y=20:fontcolor=white"  /var/www/html/motion/KewBridge-$(date +\%Y\%m\%d-\%H\%M\%S).jpg

Using ffmpeg allows me to access the camera when it’s not taking a photo, cpu load on my machine is significantly reduced and I still capture the same number of images.

To access and present these photos, I use apache2 in combination with this lovely apache2 directory listing theme. In fact, these images are public, and you can view them on my website here. (sorry for non-https, but it’s because the machine is on port 8080)

Best of luck in your timelapse adventures! Any questions or clarifications please feel free to comment below.

Leave a Reply

Your email address will not be published. Required fields are marked *