Projects

Raspberry Pi Network Video Event Recorder

Rob Bell & Mike Lewis

Issue 3, September 2017

This article includes additional downloadable resources.
Please log in to access.

Log in

Using a Raspberry Pi as an event-triggered video recorder for IP camera streams, and the Raspberry Pi camera.

IP surveillance cameras are powerful tools for security and monitoring. They’re easy to install, and can be wired hundreds of metres away, even over WiFi. If you have a large installation, you probably had a large dedicated recording device to take care of the recording functions. But what if you only needed just one camera? We will show you how.

The Raspberry Pi (RPi) is perfectly suited for this application. With it’s combined high quality processor and hardware interfacing via the GPIO, it enables you to record video as well as control recording remotely, via hardware interfacing. Sure, you could use the software that came with your IP camera to do the same, but that’s not terribly efficient for your own computer, especially when it runs slowly as a result, and you’re trying to do other work.

We can use open source software to read the video stream and save it to disk. The best thing is, using the GPIO interface on the RPi, you can trigger recording easily from just about any hardware interface.

THE BROAD OVERVIEW

There are various technologies being used here, and this system is a little more advanced than a basic RPi project. For that reason, there’s some more setup involved. There’s relatively little hardware required to provide a working system. It should probably also be noted that while we’re using RPi here, you could use just about any single-board computer that you can install Ubuntu on. Even an old PC will do the job (but you may need to setup an Arduino or small device to handle hardware triggering).

HOW IT WORKS

There are several technologies being used all together, here. A Raspberry Pi probably isn’t a new concept to you, so we’ll just cover the ones that might not be familiar.

UBUNTU MATE: Ubuntu MATE leverages the power of Ubuntu, which is an open-source Linux distribution, with the lightweight and intuitive MATE desktop. While not specifically designed for RPi, they have a ready-to-roll disk image, so it installs almost as easily as NOOBS does. Once installed it has full support for the RPi camera, GPIO, all within a native Linux environment. It is possible to get our system here running on the default RPi operating system, but this is just as easy to install and includes FFMPEG (more on that below).

NODE.JS: Node.js is a powerful open-source, cross-platform JavaScript run-time environment. It has seen a huge increase in popularity recently, allowing you to run JavaScript server-side, which was traditionally used for web browsers client-side. What’s even better about Node.js is there’s a fully functional library that provides easy access to the GPIO. It also provides a web server engine to serve pages quickly and efficiently.

RTSP: Most IP cameras, regardless of the brand name (or lack thereof), use a fairly standard protocol to transmit their video stream over the network. This protocol is called RTSP, which is the Real Time Streaming Protocol (and yes, as with many acronyms, people will often duplicate the last word and call it the “RTSP Protocol”, but we’ll forgive them for that).

FFMPEG: This is an open source Linux distribution, which is included with Ubuntu MATE, so you don’t even have to install it. It’s the engine room of video handling for this process, and can be used to do all sorts of grunt-work like converting one type of video to another, combining a sequence of images into a video, and more.

Flow Chart

SOFTWARE INSTALLATION

STEP 1: UBUNTU MATE

Head over to Ubuntu Mate and follow the instructions. We're using version 16.04.3 LTS.

NOTE: There are Linux and Windows tutorials provided to create a bootable disk image, on the Ubuntu MATE website. We have created our own for MacOSX, which you can use if you’re using an Apple environment. You can check it out here.

Once you have your bootable SD, put it into your RPi and power up (connecting your monitor, keyboard, mouse, and internet). You won’t need any peripherals later, but this makes life easier for setup.

STEP 2: BOOT THE RPI AND COMPLETE SETUP

Insert SD and power up your RPi with HDMI monitor, keyboard, mouse and Ethernet (if required). Once Ubuntu MATE is loaded, complete the setup [1], and connect it to the internet. If you download the resources for this project to your RPi, it will make copying code files much simpler.

1
Unbuntu

STEP 3: COMMAND LINE

Access terminal so we can install the additional required libraries. You’ll find it in the menu under System Tools -> MATE Terminal.

STEP 4: INSTALL NODE.JS

Update package manager (always a good idea) and install Node.js libraries.

sudo apt-get update
sudo apt-get install -y nodejs
// check everything installed ok:
nodejs -v // we’re using v4.2.6

STEP 5: INSTALL NODE.JS PACKAGE MANAGER

This will allow you to easily install modules and packages to use with Node.js.

sudo apt-get install -y npm
npm -version // we’re using 3.5.2

STEP 6: CREATE THE SIMPLE WEBSERVER APPLICATION

Create a folder called /var/nodeapp/ and navigate to that folder. This will be our work directory.

sudo mkdir /var/nodeapp && cd /var/nodeapp

Create your Node app. The command below prompts you for a number of things, such as the name and version of your application. For now you can simply hit “Return” to accept the defaults. We will use the default entry point of index.js

sudo npm init

Install Express.js which is the web framework for Node.js we’re using.

sudo npm install express --save

This will add the dependency : express into your package.json file and install the required files into the node_modules directory. Check it has completed successfully with the following command:

cat package.json

You should see output similar to the screenshot:

Screenshot

STEP 7: HELLO WORLD

With your text editor of choice, create a new file index.js (or copy our index.js file from the resources hello_world folder).

sudo nano index.js

Type / copy / paste the following:

const express = require(‘express’);
const app = express();
app.get(‘/’, function (req, res) {
  res.send(‘Hello World!’);
});
app.listen(3000, function () {
  console.log(‘app listening on port 3000!’);
});

This code may look a little strange but it’s the bare-bones of a Node.js web server. It basically loads required dependencies, tells the server to respond with a “hello world” message, and to listen on port 3000.

Now you can start the webserver.

nodejs index.js

The command line should respond with “app listening on port 3000!”, because we told it to. If it doesn’t, work back through the code to check for any errors or missed steps. Otherwise, open a browser to http://localhost:3000/ to see the output [2].

2
Hello World

To stop running the server, go back to the command line and press Control + C.

STEP 8: COPY CODE FILES AND SETUP

To ensure there are no problems with permissions, you should also run the following, replacing Ubuntu with your username:

sudo chown -R ubuntu:ubuntu /var/nodeapp
sudo chmod 755 -R / var/nodeapp

Copy the contents of “EVENT_RECORDER” folder in the resources, to /var/nodeapp - you can overwrite the original index.js and package.json files as you won’t need them any longer. If you list out the contents of /var/nodeapp you should now see something like this:

ubuntu@ubuntu-desktop:/var/nodeapp$ ls -1
/// the above command should list the following
index.js
package.json
recordings
views

Create a symlink with the command:

sudo ln -s /usr/bin/nodejs /usr/sbin/node

To install all the dependency libraries that are listed in the package.json file into a node_modules directory, run:

sudo npm install

STEP 9: SET UP YOUR IP CAMERA

Follow the instructions that come with your camera to ensure RTSP streaming is enabled and running. Ideally, the camera will have a fixed IP address so it won’t change. For our purposes, we’ve used the Jaycar TECHview 1080p IP camera, since we had one already here. Some of these cameras require Windows and plugins to access/control the camera. Once you have the camera working:

// Configure your camera for rtsp streaming 
// our cameras:
// camera1 (TECHView):  
//  rtsp://CAMERA_1_IP_ADDRESS:554/0 
// camera2 (HIKVISION): 
//  rtsp://CAMERA_2_IP_ADDRESS:554/h264.sdp 

Consult your camera’s documentation for the specific query required, as everything after the IP address can send commands to the camera regarding the type of stream, resolution, and various other options.

STEP 10: TEST CAPTURE

On the command line, run the following command:

Note: this is all one line in terminal.

ffmpeg -y -i rtsp://CAMERA_IP_ADDRESS:554/0 -t 00:00:10.00 -vcodec copy -an /var/nodeapp/recordings/test.mp4

In the above code, -t is the duration, this will record for 10 seconds, which you can adjust to see the result too. You can locate the file on your system and open it with VLC player to confirm it’s recording properly.

STEP 11: TEST THE SYSTEM

Now we can check that Node.js can handle this functionality too.

Firstly, edit index.js and update the variable videoInput with your RTSP stream address. Next, we’ll start the server.

cd /var/nodeapp   // ensure you’re in the right directory
nodejs index   // tell node to start the server

If you open the two links below in your web browser, you should see it record. The optional parameter after record allows you to set duration with the request.

http://localhost:3000/record

http://localhost:3000/record/60

We have set up a simple file-listing system, and an in-browser player (using HTML5). Simply navigate to http://localhost:3000 to view a list of the recordings. You can click on any recording to view it in-browser [3].

3
Recordings

There you have it - your system now works!

STEP 12: PERPETUAL OPERATION

There’s a good chance that you don’t want to log on and open terminal, so we’ll set the system up to run by itself. To do this, we will use forever js - https://github.com/foreverjs/forever

sudo npm install forever -g
// the -g parameter allows global access
forever start /var/nodeapp/index.js 

Start this forever script on system startup using Crontab:

// replace ubuntu with your username
sudo crontab -u ubuntu -e
// select a text editor, 2 for nano then add
PATH=/usr/local/bin:/usr/sbin:/usr/bin/
@reboot /usr/local/bin/forever start -c /usr/bin/nodejs /var/nodeapp/index.js

Save and close the file (Control + X, confirm to save). Now your system should run in the background with no terminal windows, and also start automatically if the RPi is restarted.

INTELLIGENT RECORDING DURATION

The recording duration is also intelligent. While the default recording duration is 10 seconds, what happens if the GPIO pin is constantly triggered? If we had simply told the system to record for 10 seconds, there’d be no way to interrupt that process. It would have to finish the first recording before it began to listen to the GPIO again. For this reason, we begin recording for an undefined time, and keep track of the duration. If the GPIO is triggered again, then we extend the recording duration.

Effectively, if you have an entry that’s being monitored with a doorway sensor beam, you can trigger recording each time someone walks through. But if you have someone walking through every five seconds, for instance, the system will simply record continuously until there is a 10-second break in people walking through the door. Of course, this default duration can be set to whatever duration you like: one minute, one day, one week.

This intelligent recording applies to web browser requests and GPIO hardware-initiated recording as well.

GETTING FANCY - HARDWARE INTERFACING

This is where the fun really begins. There are many instances where you would want to trigger recording via hardware; perhaps a motion sensor, an entry sensor, or a “panic button”. Even for something you may have set up, such as an automatic pet feeder to check “did the cat come and get its food this morning?”. More importantly, you can interface it with something such as our Alarmduino project, to record for a duration when the alarm is triggered, or even just when someone has armed/disarmed the system, so you have a video record of events.

Fortunately with the inclusion of GPIO, this is a relatively simple solution to implement. We will create an example below and we’re going to use a simple push-button switch to trigger recording.

IMPORTANT NOTE: Hardware interfacing with other devices should be approached with caution. If you're triggering from a relay output of some description, then this is usually a safe method as no voltages are involved other than your own. However if you sent 12V to your Raspberry Pi, as done from some alarm systems, you could damage your Raspberry Pi. Be careful to ensure high voltages aren't being sent to your hardware unintentionally.

THE BUILD

Since you may be interfacing your own hardware, this build is considered as more of a test circuit to ensure everything’s running as intended. Due to its basic nature, we won’t describe the build itself. If you’re tackling this project, we’re confident you can follow the diagram easily.

Parts Required: Jaycar Altronics
1 x Raspberry Pi 3 XC9000 Z6302B
1 x Tactile Switch SP0609 S1120
1 x 330Ω Resistor RR0560 R7040

In addition to the parts list, you’ll require suitable jumper wires and breadboard/prototyping equipment.

Breadboard

Our code is already configured for the GPIO triggering. When you push the button, recording will start. But it’s important to note, you can use this code to trigger from any 5V logic signal.

On line 16 of index.js you’ll find:

var pin = 7;

You can change this to whatever number you prefer. We are keeping things simple with only one GPIO interfacing pin, but you could easily expand this to multiple pins (and even record different cameras based on the pin that's triggered).

From line 121 you’ll find our GPIO callback function. You can modify this in all sorts of ways, but here we’re basically just telling the system to listen to the GPIO pin, and whenever anything changes, perform some functions. In this case, we trigger “startVideoCapture()” function. It would be possible to expand on this to send an email, turn on a light, or all sorts of other functions.

gpio.on(‘change’, function(channel, value) {
  if ( value === true ) {
    console.log(‘Triggered’);
    startVideoCapture();
  }
});
gpio.setup(pin, gpio.DIR_IN, gpio.EDGE_BOTH);

REMOTE OPERATION

While we’ve already provided the callback URLs for triggering recording, we’ve created a very simple interface. It’s HTML5 using offline storage to remember the server IP address, so you don’t have to retype it each time you set it up.

Once this system is running, you can effectively use it as a panic button, or simply a convenient way to record, using your IP camera. It’s VERY simple. It includes a slider to set the recording duration and a big record button! [4]

4
Remote Operation

The HTML package is included in the online resources, as a live load, and a download so you can modify it. The code will work on any smartphone, tablet, or modern web browser.

It wouldn't take much work to provide the list of recordings, and the ability to view videos in-browser. However this functionality is already provided by the Node.JS web server directly, so we would somewhat be doubling up.

WHERE TO FROM HERE?

LIVE STREAM MONITORING: It is possible to view the live stream from the IP camera directly through a VLC player, which is included with Ubuntu MATE. We had mixed success with this though. When reading the stream at full HD resolutions, it would quickly overload the processor. It seemed to work fine at a lower resolution (such as 720p, perhaps smaller), without interfering with the DVR functionality. The playback capabilities will depend on the resolution, video format, and network speeds.

HARD DISK SPACE: Inevitably, you’ll run out of hard disk space. While it’s possible to record to any connected storage device with a minor configuration change, it will probably EVENTUALLY run out of space. It wouldn’t take too much to create a scheduled process in Ubuntu, which cleared out the oldest files to maintain free disk space.

MULTI-CHANNEL RECORDING: As long as your IP camera provides video in a standard stream that can be interpreted (such as native MPEG4), and the processor usage is rather low (we saw it sit below 10% with a single, 1080p full HD stream), you could easily add multiple channel functions. It’s important to consider that you don’t want to overload the processor, and you need to retain headroom in the processor for smooth operation. If you’re recording 1080p we wouldn’t suggest more than perhaps four streams concurrently; however, if you’re using smaller resolutions this would be less of a problem.

VIDEO TRANSCODING: Further to our previous notes on live streaming burden on the Raspberry Pi hardware, some IP cameras may actually require video transcoding to store it in a suitable format. This is processor-intensive and may rapidly overwhelm your RPi.

DASHCAM: We’re currently experimenting with a dashcam-type setup with accelerometer and small screen, using the RPi camera. We could bundle it all into a neat 3D-printed case! Keep an eye out for more on this one, in future issues.