Pale blue cloud  

   

   

Computer stuff

Webcam streaming with Raspberry Pi

Details

Here is a set of instructions for the installation and configuration of a Raspberry Pi to provide streaming video from a webcam. I set this up in preparation for my Nestcam project which hopefully appears on these pages in the following months.

To capture video and snapshots from a webcam and stream them through a webserver I use Motion: "Motion is a program that monitors the video signal from cameras. It is able to detect if a significant part of the picture has changed; in other words, it can detect motion." Website here. I have also tried the combination ffserver and ffmpeg/avconv, but initially the webcam would throw errors like the one below, which caused avconv to crash. This was probably due to the USB stream containing errors and it disappeared after I updated the system

[video4linux2 @ 0x8cb6c0] The v4l2 frame is 8316 bytes, but 153600 bytes are expected

Motion can be setup in such a way that it only captures images and/or video when something moves in the camera's field of vision. This is ideal for observation purposes because it limits the required bandwidth and the number of images produced.

To watch the stream in other browsers than Firefox you'll need to install a Java applet. At least, that's what the Motion website lets us believe: "The webserver generates a stream in "multipart jpeg" format (mjpeg). You cannot watch the stream with most browsers. Only certain versions of Netscape works. Mozilla and Firefox brosers can view the mjpeg stream but you often have to refresh the page once to get the streaming going. Internet Explorer cannot show the mjpeg stream. For public viewing this is not very useful. There exists a java applet called Cambozola which enabled any Java capable browser to show the stream. To enable the feature to a broad audience you should use this applet or similar.".

 

Update below.

Special measure are required to include <applet> and <iframe> tags in a Joomla (1.5) article: the article must be written in the Administrator backend and the author's editor must be set to 'none', otherwise the applet tags are removed. Background here.

As mentioned above, Firefox can display the webcam stream directly, either by using an <image src="http://host:port"/> or by creating an HTML page and embedding the image in that, then load that page in, for example, an IFRAME element in your site:

<html>
<body>
<img src="http://host:port"/>
</body>
</html>

Chrome (Windows) will display the first image, when using the IFRAME method, but it won't reload the stream.

IE 9 can't deal with either method, apparently.

By the way, the colour balance of the webcam pictures is off because I modified the cam for 'night vision'.

Getting started

  1. Download and install a Raspberry Pi image or buy a pre-loaded SD card. I started off with 2012-07-15-wheezy-raspbian.
  2. Start the RPi and configure it to your liking using raspi-config.
  3. Update raspi-config: select update from the raspi-config menu.
  4. Update all installed packages: execute sudo apt-get update.
  5. Change the default password for user pi with passwd pi.
  6. Correctly setup ssh because raspi-config doesn't do it: when starting ssh from the commandline there's an error 'could not load host key'. Here's a HOWTO.
  7. Use sudo apt-get install to install the following packages:
    sysv-rc-conf (for managing services, not needed for streaming)
    camorama (just to see if my webcam works, using a gui program, not needed for streaming)
    lsof (for convenience sake, not needed for the webcam)
    mplayer
    ffmpeg
    motion
    feh (simple image viewer)
    screen (utility for starting multiple virtual terminal processes in a single physical terminal)
  8. We're going to be access from the internet, so setup iptables to limit access to the bare essential. Here are some instructions to get started.
  9. Create a directory /home/pi/.motion.
  10. In this directory, create the configuration file motion.conf for motion. When started with this configuration file, the webcam creates JPG images and AVI video, and start a web server on port 8080.
    My motion.conf looks like this:
    daemon=on
    norm=3
    input=8
    auto_brightness=on
    framerate=2
    height=240width=320
    jpeg_filename=motion/%Y%m%d/%v-%H%M%S-%q
    noise_tune=on
    output_all=off
    output_motion=off
    output_normal=on
    quality=75
    snapshot_interval=300
    target_dir=(hidden)
    text_left=(c) Nestcam
    text_right=%d %b %Y\n%k:%M:%S
    threshold=500
    v4l2_palette=6
    videodevice=/dev/video0
    webcam_localhost=off
    webcam_maxrate=2

    webcam_port=8080
    wecam_quality=85
  11. Start motion by typing motion at the prompt (logged in as the user pi). You should see the following:
    pi@raspberrypi ~ $ motion
    [0] Processing thread 0 - config file /home/pi/.motion/motion.conf
    [0] Motion 3.2.12 Started
    [0] Motion going to daemon mode
  12. Fire up a browser and point it to the IP address of the RPi, port 8080 (e.g. 192.168.10.10:8080) and you should see the images of the webcam. In my case, the RPi's default browser, Midori, did not recognize the JPG image from the webcam as an image - it showed binary gibberish. Using Firefox/Chrome from other computers in the network was fine though.
  13. Setup the internal network to forward requests on a specific external port to the Raspberry Pi's webcam port.

Hardening the Pi

If you enable access to the evil interwebs to your webcam stream, you may want to harden your Raspberry Pi against uninvited visitors. Even with its small form factor, it's still a full-fledged computer that can be compromised and used as an attic vector for your internal network.

To limit access there are a couple of things you can, or should, do:

  • disable unused services (e.g. Apache, MySQL)
  • change the password of the 'pi' account (see above)
  • enable ssh and set it up for passwordless authentication
  • run motion as a service, under an account with few priviliges and no shell or home directory
  • configure a local firewall using iptables, information about this can be found in the Debian Wiki

Run motion as a service when the Raspberry Pi starts up

It's no use having to ssh into the RPi and start motion manually every time after the power was removed. So we want to start motion automatically at boot time, and run it as a daemon. As luck has it, a dedicated account 'motion' is already present in the system: my guess is that apt-get took care of that. So what we do is change the location of the configuration file from one assocated with user 'pi' to one associated with the default application installation.

  1. Make a backup of the system-wide original motion.conf file:
    sudo cp -p /etc/motion/motion.conf /etc/motion/motion.conf.org
  2. Copy the motion.conf from 'pi' user to the default location:
    sudo cp /home/pi/.motion/motion.conf /etc/motion/motion.conf
    sudo chown root.motion /etc/motion/motion.conf
  3. As root edit /etc/motion/motion.conf and change the value of target_dir to a location where user 'motion' is allowed to write its JPGs and AVIs. For example, an external USB drive or a custom directory under the /var. Do not write them in /tmp or any of the other directories that are in the tmpfs filesystem because the RPi needs them itself. I use /var/local/motion-output. You may also opt to change some other parameters, for example frame_rate and webcam_maxrate, depending on how many clients you intend to serve with the webserver.
    cd /var/local
    sudo mkdir motion-output
    chown root.motion motion-output
    sudo chmod 775 motion-output
  4. As root edit /etc/default/motion with your favourite text editor, so that it reads:
    # set to 'yes' to enable the motion daemon
    start_motion_daemon=yes
  5. Start the script that lets you control services startup by init: sudo sysv-rc-conf
  6. Check that motion is started automatically by init: in the row for motion there should be an 'X' in the columns named 2, 3, 4 and 5. If there isn't then put an X in there using the space bar.
  7. If you have motion running under the 'pi' user then kill it now.
  8. Start the motion service:
    pi@raspberrypi ~ $ sudo /etc/init.d/motion start
    [ ok ] Starting motion detection daemon: motion.
  9. Check that it's running under the right ownership:
    pi@raspberrypi ~ $ ps aux | grep motion
    motion    1921  0.4  4.2  39748  7916 ?        Sl   12:25   0:00 /usr/bin/motion
  10. Check that the webserver interface is up:
    pi@raspberrypi ~ $ sudo netstat -apt
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 *:http-alt              *:*                     LISTEN      1921/motion
    [...]
  11. Fire up a browser and point it to the IP address of the RPi, port 8080 (e.g. 192.168.10.10:8080) and hopefully now you should see the images of the webcam. If not then the first step in troubleshooting is checking the system log /var/log/messages for obvious error messages.

Update

I was not very satisfied with any of streaming software I tried: motion, ffserver/ffmpeg, mjpeg-streamer. Streaming was slow and often interrupted. By chance I discovered that the stream was much better when there was a higher load on the system. For example, by running top with a high refresh rate. Quite strange.

A friendly contributer on the Raspberri Pi forum  suggested to do a complete update and upgrade of the RPi, like this:

sudo apt-get update
sudo apt-get upgrade
sudo reboot

After the update, which was considerable, the output of uname -a read as follows:

Linux raspberrypi 3.2.27+ #102 PREEMPT Sat Sep 1 01:00:50 BST 2012 armv6l GNU/Linux

Even better than a new kernel is the fact that streaming with motion and mjpg-streamer (both with and without the help of Cambozola) is much better!

Another attractive streaming application is mjpg-streamer. I had to compile it from source because there was no suitable package available, but this was not hard. I have not yet made up my mind which package it's going to be eventually, but motion has going for it that it can 'activate on motion', thus only creating output footage when somthing significant happens.

   
© Palebluedot