Quick and Dirty Raspberry Pi Spy Cam
BOARDS
Quick and Dirty Raspberry Pi Spy Cam
2016-09-27
By
Gogi Club

It has been a long time since we played with our Rpi. In the meantime we have got a Rpi2, Rpi3 and even manage to get a Rpi Zero, together with a camera module. We have some plans for these little guys, specially within the frame of the MIA project. But first we have to get started with all toys. So... Let's build the simplest spy camera ever.
As we have just said this is probably the simplest way to build a Spy camera. Our intention is to improve this build and, of course, let you know about the progress. For this first iteration we're going to use the following:

  • A Rpi2 + a Wireless dongle... or, alternatively a Rpi3. I have tried both
  • A camera module. A USB external webcam will also work, but that will have some drawbacks and also they waste a lot of space
  • A external battery pack
  • Some tape :)

DISCLAIMER
The author of this post is not responsible of any damage that may be caused out of the content of this post.

    Be careful to avoid hurting yourself and to avoid damaging your equipment

    Do not touch your board or the header pins when the board is power up. You may cause a short cut that may damage your board.

    Be careful when tighten screws. You may break the PCB if you tight them too hard.

    Avoid applying force to cables attached to connectors on the board, you may damage the connector (specially the Power microUSB on the RPI)

The Hardware Build

There are many different options out there to attach the camera. Be free to buy whatever you like. As we said, this is the simplest build possible so we will be using just one M2 screw and 3 nuts. This allows us to attach the camera directly to the Rpi and also save some space.

This is how it looks like:

Camera attached to a RPi2 using an M2 screen and some nuts

You will need a bit of tape to hold the camera's flat cable close to the board. It can be easily stuck to the USB connectors with that little piece of tape.

We fixed the flat camera cable with some tape
Then, you just need to plug in the USB wifi dongle, choose a USB battery and figure out a way to attach it to the board, so you have a single block you can easily move around.

The final build is pretty bulky but portable. We will work this out in future post. For the time being it is enough to test the concept.

Final build using a Fish Eye lens to capture everything!

Software Installation

For the SW I used the latest Raspbian version. It comes with everything needed to use the camera out of the box. We just need to do a couple of very minor changes to get the Spy Cam up and running.

First, we have to enable the camera. Usually you do this updating and upgrading Raspbian and, after that, using the raspi-config tool or the graphical version accessible from the desktop menu. That will indeed work.

However, the only thing that has to be done is to change the string start_x=0 in the /boot/config.txt file to start_x=1 and make sure that the GPU memory is at least 128Mb (that is the default value, and usually it is just after the start_x value).

So:

$ cd /boot
$ sudo cp config.txt config.txt.ORIG
$ sudo sed -i 's/start_x=0/start_x=1' config.txt
$ tail config.txt
# Additional overlays and parameters are documented /boot/overlays/README

# Enable audio (loads snd_bcm2835)
dtparam=audio=on
start_x=1
gpu_mem=128

That's it for the camera.

Now we have to configure the wireless access. For doing that we need to let the Rpi know the AP and password for our wifi.

$ cd /etc/wpa_supplicant
$ sudo cp wpa_supplicant wpa_supplicant.ORIG
$ sudo vim wpa_supplicant

After editing, the file should look like:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=GB

network={
        ssid="YOUR_WIFI_ESSID"
        psk="YOUR_WIFI_PASSWORD"
        key_mgmt=WPA-PSK
}

This is the typical configuration for a WPA2 network... That is the minimum security you should enable in your wifi network.

We are almost done with the configuration.

Streaming Video

The final piece is to set the Rpi to stream the video when it boots up, but First we need to figure out how to stream the video from the Rpi and render it in a different computer. There are many options for doing this, but we went, for the time being, with the gstreamer solution.

So, to stream the RPi camera to a computer with IP RENDER_IP we have to use the following command:

raspivid -n -t 0 -rot 270 -w 1280 -h 720 -fps 30 -b 6000000 -o - | gst-launch-1.0 -e -vvvv fdsrc ! h264parse ! rtph264pay pt=96 config-interval=5 ! udpsink host=RENDER_IP port=5000
Video transmission pipeline from the Rpi

The first part of the command runs the raspivid tool that activates the camera. This tool allows us to control different camera parameters as well as getting a RAW H264 stream from the camera. That is very nice because we do not need to waste CPU cycles encoding the camera images... we can just send out the stream from the camera using almost no CPU.

In this case, we are rotating the image, setting resolution to 1280x720, fixing the frame rate to 30 fps and limiting the bandwidth to 600Kbps. The -t 0 flag tell the application to not timeout and the -n disables the preview... we will not have a display any way.

The raspivid tool, dumps the camera stream to stdout... yes. So, in order to feed this stream into gstreamer we have to use a fdsrc component... a file descriptor source that, by default, takes data from stdin. That is pretty convenient. Then we have to pass the steam through a h264parse (this is needed by gstreamer to figure out the stream characteristics and properly configure the pipeline).

After that, we build our RTP packet and send it out, using the UDP protocol towards the RENDER_IP computer and to the port 5000 (you can use any other port you want).

Now we just need to add this line at the very end of /etc/rc.local, and the Rpi will start streaming to the configured IP every time it boots up.

Watching the Stream

Now we have to be able to watch the stream somewhere else. For doing that we will use gstreamer again. A command like this:

gst-launch-1.0 -e -v udpsrc port=5000 ! application/x-rtp, payload=96 ! rtpjitterbuffer ! rtph264depay ! avdec_h264 ! fpsdisplaysink sync=false text-overlay=false
Reception Pipeline. Run it in the computer with the RENDER_IP

Again, the pipeline is pretty straightforward. Get data from a UDP port, pass it through a rtpjitterbuffer to compensate latency/jitter, decode the RTP stream, then decode the H264 video stream (note that we didn't encode it on the transmission pipeline on the Rpi :o), and send it to a sink component for final rendering in the screen. You can use other displaysink if you do not want to monitor the frames per seconds.

If you have searched the net for examples on how to stream using gstreamer, you may have seen many examples using the gdppay and gdpdepay. These components are used for interchanging capabilities between transmitter and emitter. However, you can interchange the stream capabilities by other means.

For H264 streams, we are very lucky, and we can use some default capabilities that work in all cases. That is why we do not have to use gdppay/gdpdepay and why we do not have to copy over the capabilities by hand.

In our command above, you can see the capabilities just after the udpsrc component:

 application/x-rtp, payload=96 

In case you want to use other codecs you may need to get the proper capabilities and enter them by hand (or use other means lie gdppay/depay). In order to get the capabilities pass the -v flag to gst-launch-1.0 in your transmission stream. Then in the output look for the application/x-rtp string, and paste it in the receiver pipeline. That's it.

Conclusions

I think this is, by far, the easiest way to build a spy cam with a Rpi. However, as you may had noticed from the pictures, it is pretty bulky. I'll try to improve the build in the future and also enable additional capabilities... there are quite some potential in here with the hardware accelerated camera.

Stay tuned!