Worlds Shittiest NVR pt. 3.

Our wonderful NVR is now basically a circular buffer in RAM, but we’d like to do a few things if motion (or other things) occur.

Many cameras support notification by email when things happen; while getting an email is nice enough, it’s not really what we want. Instead, we’ll (ab)use the mechanism as a way for the camera to notify our “NVR”.

First, we need a “fake” SMTP server, so that the camera will think that it is talking to a real one and attempt to send an actual email. When we receive the request to send the email we’ll simply do something else. An idea would be to move the temporary file on the RAM drive to permanent storage, but first, we’ll see if we can do the fake SMTP server in a few lines of code.

Start by downloading and installing node.js. Node.js allows us to run javascript code, and to tap into a vast library of modules that we can use via npm (used to stand for “Node Package Manager).

Assuming you’ve got node installed, we’ll open a command prompt and test that node is properly installed by entering this command:

node -v

You should now see the version number of node in the console window. If this worked, we can move on.

Let’s make a folder for our fake SMTP server first; Let’s pretend you’ve made a folder called c:\shittynvr. In the command prompt cd to that directory, and we’re ready to enter a few more commands.

We’re not going to write an entire fake SMTP server from scratch, instead, we’ll be using a library for node. The library is called simplesmtp. It is deprecated and has been superseded by something better, but it’ll work just fine for our purpose.

To get simplesmtp, we’ll enter this command in the prompt:

npm intall simplesmtp

You should see the console download some stuff and spew out some warnings and messages, we’ll ignore those for now.

We now have node.js and the simplesmtp library, and we’re now ready to create our “event server”.

Create a text file called “smtp.js”, add this code to the file, and save it.

const smtp = require ( "simplesmtp");
smtp.createSimpleServer({SMTPBanner:"My NVR"}, function(req){
  // we can do other stuff here!!!

console.log ( "ready" );

We can now start our SMTP server, by typing

node smtp.js

Windows may ask you if you want to allow the server to open a port, if you want your camera to send events to your PC, you’ll need to approve. If you are using a different firewall of some sort, you’ll need to allow incoming traffic on port 6789.

We should now be ready to receive events via SMTP.

The server will run as long as you keep the console window open, or until you hit CTRL+C to stop it and return to the prompt.

The next step is to set up the camera to send emails when things happen. When you enter the SMTP setup for your camera, you’ll need to enter the IP address of your PC and specify the port 6789. How you set up your camera to send events via email varies with manufacturers, so consult your manual.

Here’s an example of the output I get when I use a Hikvision camera. I’ve set it up so that it sends emails when someone tries to access the camera with the wrong credentials:

output Next time, we’ll look at moving files from temporary RAM storage to disk.


Worlds Shittiest NVR pt. 2.

In pt. 1 we set up FFmpeg to suck video out of your affordable Hikvision camera. I hope your significant other was more impressed with this feat than mine was.

The issue we have with this writing constantly to the drive is that most of the time, nothing happens, so why even commit it to disk? It obviously depends on the application, but if you’re sure your wonderful VMS will not be stolen or suffer an outage at the time of a (real) incident, you can simply keep things in RAM.

So, how do we get FFmpeg to store in RAM? Well … Enter the wonderful world of the RAM disk.

ImDisk Virtual Disk Driver, is a tool that allows us to set up a RAM drive. Once you’ve downloaded the tool, you can create a disk using this command:

imdisk -a -s 512M -m X: -p "/fs:ntfs /q /y"

Do you remember how I said that I had an x: drive? Total lie. It was a RAM drive the whole time!

The command shown creates a 512-megabyte NTFS drive backed by RAM. This means that if the computer shuts down (before committing to physical HDD) the data is gone. On the other hand, it’s insanely fast and it does not screw up your HDD.

When we restart FFmpeg, it will now think that it is writing to an HDD, but in reality, it’s just sticking it into RAM. To the OS the RAM disk is a legit harddrive so we can read/write/copy/move files to and fro the disk.

In part 3, we’ll set up node.js to respond to events.

Oh, and here’s a handy guide to imdisk.

Worlds Shittiest NVR pt. 1

In this tutorial, we’ll examine what it takes to create a very shitty NVR on a Windows machine. The UI will be very difficult to use, but it will support as many cameras as you’d like, for as long as you like.

The first thing we need to do is to download FFmpeg.

Do you have it installed?

OK, then we can move on.

Create a directory on a disk that has a few gigabytes to spare. On my system, I’ve decided that the x: drive is going to hold my video. So, I’ve created a folder called “diynvr” on that driver.

Note the IP address of your camera, the make and model too, and use google to find the RTSP address of the camera streams. Many manufacturers (wisely) use a common format for all their cameras. Others do not. Use Google (or Bing if you’re crazy).


Hanwha (SUNAPI):

Some random Hikvision camera:

Now we’re almost ready for the worlds shittiest NVR.

The first thing we’ll do is to open a command prompt (I warned you that this was shitty). We’ll then CD into the directory where you’ve placed the FFmpeg files (just to make it a bit easier to type out the commands).

And now – with a single line, we can make a very, very shitty NVR (we’ll make it marginally better at a later time, but it will still be shit).

ffmpeg -i rtsp://[...your rtsp url from google goes here...] -c:v copy -f segment -segment_time 10 -segment_wrap 10 x:/diynvr/%d.mp4

So, what is going on here?

We tell FFmpeg to pull video from the address, that’s this part

-i rtsp://[...your rtsp url from google goes here...]

we then tell FFmpeg to no do anything with the video format (i.e. keep it H.264, don’t mess with it):

-c:v copy

FFmpeg should save the data in segments, with a duration of 10 seconds, and wrap around after 10 segments (100 seconds in all)

-f segment -segment_time 10 -segment_wrap 10

It should be fairly obvious how you change the segment duration and number of segments in the database so that you can do something a little more useful than having just 100 seconds of video.

And finally, store the files in mp4 containers at this location:


the %d part, means that the filename will be the digits of the segment as filename, so we’ll get files named 0.mp4, 1.mp4 … up to and including 9.mp4.

So, now we have a little circular buffer with 100 seconds of video. If anyone breaks into my house, I just need to scour through the files to find the swine. I can open the files using any video player that can play mp4 files. I use VLC, but you might prefer something else. Each file is 10 seconds long, and with thumbnails, in Explorer, you have a nice little overview of the entire “database”.

In the next part we will improve on these two things:

  • Everything gets stored
  • Constant writing to HDD

Oh, and if your camera is password protected (it should be), you can pass in the credentials in the rtsp url like so:

rtsp://[username]:[password]@[ the relevant url for your camera]


Adding a Button to the Interface

If you are hosting the Auga control in your own applications, you can easily add a custom button.

You will need a PNG file with 3 states; normal, hover and pressed (no support for disabled buttons at this point).

Auga exposes a function called “CreateElement” and “SetElementPixelPos”. Use these two functions to create and position your new button. Then subscribe to ElementClicked to be notified when the user presses the button.

Fairly simple I should think.

Does MJPEG Provide a Predictable Image Size?

The answer is no. We learned this the hard way when a client called and told us the software crashed when they turned the light on! Our support team had a hard time convincing R&D that this was what the client was experiencing. A couple of developers went to the site, and sure enough, the app crashed predictably when they turned their lights on. It turned out that a reception buffer was too small, and that the image size grew considerably when the lights came on – making the image a lot more complex than when peering into a dark room. Embarrassed and humbled, we delivered a new version in a few days.

I created 4 JPEG images in Photoshop. Same resolution and same quality setting, but the sizes range from 16.2kb to 389kb. Naturally, this is a synthetic test, but it demonstrates the concept quite clearly. The white frame is the smallest, at just 16.2 kb (the images are further compressed by the blog engine, so to replicate you will need to do the experiment yourself), the dark phone is simply the regular phone with synthetically depressed light, yet the dark image is 50% smaller (compressed) than the normal one, and the noisy image is a whopping 389kb.

Going into entropy theory is beyond the scope of this blog, but let me just say that in GSM for example we don’t even attempt to compress the noise. We simply re-generate noise on the receiving end, shaping the noise with a filter.

As a result of a discussion on LinkedIn, which sparked this post, I’ve added some further observations. Two routes are taken; the image is darkened, and noise is added. One path simply compresses the image as-is, while the other multiplies the pixel values (horizontal path). The image sizes are noted. On the as-is frame, we multiply the pixel values by the same factor and compare the differences to the original.

3D Eyecandy

Ocularis does 3D

Ocularis has some hidden “gems”; One is the layout command called “box”, swing by and find the docs for LoadLayoutFromString. Somewhere in there, you will find a description of the experimental feature called “box:”

string layout =
vport: 0, 0.000, 0.000, 0.500, 0.500
vport: 1, 0.500, 0.000, 1.000, 0.500
vport: 2, 0.000, 0.500, 0.500, 1.000
vport: 3, 0.500, 0.500, 1.000, 1.000
salvo: 0,0,0,NetDVMS://UserName:Password@[Axis 223M] Camera 1
salvo: 1,0,0,NetDVMS://UserName:Password@[Axis 214] Camera 1
salvo: 2,0,0,NetDVMS://UserName:Password@[Axis 215] Camera 1
salvo: 3,0,0,NetDVMS://UserName:Password@[Axis 231] Camera 1


You need 4 viewports and a salvo for each ( the term salvo is prob. misleading, but you get the idea ), and the end result is pretty cool. This could be used at trade-shows or for in-store displays I believe.

3D using the BOX command

Joomla Theme pt. 3

The layout of a Joomla theme is really more about CSS than anything else. An example is menus – they are usually a bunch of <ul>’s, so to make them look cool you need to know how to change the layout of a <ul> (there are hundreds of CSS tutorials around the net). Other modules are dumped as a <table>; an example could be the newsflash module.

In my setup, the newsflash module is linked to the top position. So to draw the newsflash, the php will contain something like this

<jdoc:include type=”modules” name=”top” />

this will result in this output

<table class="contentpaneopen">
    <td valign="top" >Joomla! 1.5 - 'Experience the Freedom'!....</td>
    <td valign="top" ></td>

It would seem logical that we just create some CSS for table.contentpaneopen – however – ALL the tables are of this class, and obviously, we need the newsflash to look completely different. The solution is to wrap the top position in a <div>

<div id=”newsflash”><jdoc:include type=”modules” name=”top” /></div>

in the CSS, we can then address the newsflash with this selector

div#newsflash table.contentpaneopen
background: fuchsia;

the individual <td>’s are addressed like so

div#newsflash table.contentpaneopen td
background: #456;

This was a pretty brief intro to the Joomla way of thinking. Now go play 🙂