This project describes my process of building a home security camera system using Dahua PoE cameras and ZoneMinder. Overall the system is functional, but Zoneminder leaves a bit to be desired. I will revisit this project in the future.

The Beginnings of a Camera System

The real OG camera system was installed by my dad a decade ago using analog ‘960H’ cameras (which are grossly misleading in their advertising since they market the horizontal resolution instead of the usual vertical resolution, they are actually 480x960 at best). The system used a Chinese DVR which was limited to 8 cameras, and one after another they failed due mostly to poor quality cabling. The image quality was also awful. So, a new setup was desirable. We don’t live in a very dangerous area, but we like to look at the cameras to check on things when we go on vacation, and they can also be useful to keep track of deliveries and who’s home or away.

For the ‘New’ first camera system, I wanted to go all IP based, with plenty of room to upgrade in the future, and complete local control. I wanted to be free of any cloud services. I didn’t mind paying for licensed software when it’s the best option, but I’d prefer an open source solution and absolutely require Linux or BSD for servers. I already had a PoE managed network switch (Mikrotik CRS328-24P-4S+RM), so the next choice was the cameras.

Based on the camera review of intermit.tech, I looked at Dahua, one of the two major Chinese camera OEMs (the other is Hikvision). I decided to try the DH-IPC-HDW2431TP (4MP/1440P ‘Lite’ series) and DH-IPC-HDW5831RP-ZE (8MP/4K ‘Pro’ series, the one he calls the ‘old champ’ in a few videos). The Pro series cameras have a better build quality, higher resolution, and a varifocal lens that can be considerably sharper in certain scenarios. The Lite series cost 1/3 the price with a fixed focus lens, so you have to design around the focal range of the lens. I ran an Ethernet cable to my first location and setup the Pro for a week, followed by the Lite, and compared the two. Based on this test, I decided that the Lite series was perfectly adequate for most of the views I wanted to capture. Most of the camera locations I wanted were near entry doors, so the fixed focus lens was a good match for close range imaging above each door. I then bought a 5-pack of the Lite cameras to build out the whole system (7 cameras in hand now).

Short Review of the Dahua Cameras

I highly recommend you review intermit.tech’s IP Camera series (Blog Link)(YouTube Link). He’s done a good job at showing the features and visual comparisons of each camera. The right camera for you is very subjective. In my case, I was on a fairly low budget, and not trying to spot a license plate or face at the end of my driveway, especially not at night.

In my case, here are my observations which may be useful to you:

  • The software security of the cameras impressed me, given the my very low expectations based on the reputation of cheap IoT devices. When first connecting to the camera, it made me choose a new password, offered me the choice to enable or disable cloud services, and hasn’t made any attempt to call home as verified by my router. This is a professional product, albeit from China, and it’s software design shows some care has been given to security.
  • The Web UI is a bit basic, but it’s functional to navitage and configure the camera. The cameras support both h.264 and h.265, although I operate them in h.264 mode to remove the need to transcode the recordings to view them (since no web browser other than Safari natively supports h.265 as of the writing of this).
  • The Lite cameras support a main stream of up to 2560x1440x30fps (1440p) and a single sub stream of up to 704x480x30fps (D1). You can independently select the resolution, framerate, encoding mode (constant/variable bit rate), maximum bit rate, i-frame interval, and codec (h.264 or h.265) for each stream.
  • The Pro cameras support three streams. The main stream supports up to 3840x2160x15fps (4K), and the two sub streams support up to 704x480x15fps (D1) for sub stream 1 and 1920x1080x15fps (1080p) for sub stream 2. All 3 streams can be enabled at once, and again have independent configuration of all parameters
  • The cameras show up in ONVIF Device Manager, as they should, being advertised as ONVIF compliant. I don’t use an ONVIF compliant NVR, so I can’t test intgration with other hardware, but ONVIF Device Manager can help you identify the streams if you need help with that.

When wiring the cameras, I bought Ubiquiti Toughcable, which has a black polyethylene (PE) jacket instead of the usual PVC, so it does not degrade in sunlight. It seems like they have discontinued this cable, but any outdoor rated cable, preferrably non gel filled, will work for outdoor wiring. I had to run some cameras 50’ or more outdoors along a brick ledge between the first and second floor of the house, but for short runs of a few feet an indoor rated cable should be fine.

The Great NVR Test Campaign

I initially tried a number of open source NVRs in a virtual machine on my personal workstation using Virtualbox. The goal of these tests was to estimate the CPU and RAM requirements for a single camera (by limiting the VM to one core or less on my Ryzen Threadripper 1950X), test scalability with the 2 cameras I had installed at the time, and evaluate the installation process, maintenance, UI, and apps.

The tests included the long-running open source project ZoneMinder, Motion, and Shinobi. ZoneMinder was functional but required a lot of menus to setup, but offered a ton of configuration of exactly how to extract the video (using ffmpeg internally) and manage the streams. Motion seemed to lack the comprehensive system feature set I wanted, and more focused on being lightweight. At the time of this review (2020), Shinobi’s setup did not function correctly in my Ubuntu virtual machine and overall it was a very painful process. Considering the recent age of the project it’s possible the developer has improved it.

I also tried trial versions of a few commercial products including Xenoma and Blue Iris, but was dissatisfied with both. Xenoma licensing does not allow running personal licenses in a virtual machine, which would drastically raise the price for me running virtual machines at home. Blue Iris only supports Windows, and I’d like to avoid a Windows virtual machine just for this. My goal was to run this software in a LXC container on Ubuntu (18.04 Bionic Beaver), with the host running a ZFS pool for storage. At this point in the project, the NVR was expected to run on the existing storage server, which was not very powerful and the low overhead LXC container was preferrable over a paravirtualized Linux or hardware virtualized Windows virtual machine. My knowledge of virtual machines was also poor going in to this project.

The Choice of Zoneminder

Zoneminder is very functional and reliable, as you would expect from a nearly 20 year project still in active development. However, it’s design age is showing. When the project was started, it was expected that analog cameras would be connected to a v4l capture card, and presented as a raw framebuffer for use by the processing tasks. It still somewhat operates this way internally, with the incoming camera stream decoded into a framebuffer for analysis. All detection is done purely by the CPU on raw decoded frames, and there is no native support for using lower resolution streams for motion detection and higher resolution streams for recording. The solution around this limitation is to setup two monitors, one with the low-res stream and one with the high-res stream, and have the low-res stream run detection and trigger the high-res camera so both record on motion. This results in twice as many recordings (one for each stream), although the low-res recordings are significantly smaller. It also means that analyzing and tweaking the motion analysis requires watching the low resolution 704x480 D1 resolution video to see the analysis results. After all of these negatives, I still liked the software and went forward with setting it up on the production server

Upgrading to New Hardware

The production server at this point in time was an AMD Bulldozer family APU designed for mobile applications, but I bought it as an embedded mini-ITX board with a soldered CPU. This APU performed well running Ubuntu 18.04 Bionic Beaver, as well as ZFS on Linux for the data pool. Prior to the installation of Zoneminder, it was already hosting an LXC container for the first generation home automation system, which comprised of an MQTT broker, InfluxDB server, Grafana server, and Node-Red server, with all logic being done by Node-Red. The Bulldozer CPU was a quad-core, but the AMD construction equipment family (Bulldozer/Piledriver/Excavator) was famous for having tightly coupled core pairs sharing execution units more similar to hyperthreading than truly distinct cores. To attempt to simulate the performance of this low end CPU, I ran my Zoneminder virtual machine with 2 cores of the Threadripper and an execution cap of 1/2 each CPU. It ran adequately with the 2 cameras in my test setup, although it was certainly reaching the limit of that hardware. Installed on the Bulldozer, it was unable to run more than two cameras with low resolution motion detection.

As it was unable to run the 2 cameras I already had installed and I still had 5 more cameras to install, a hardware upgrade was in order. I ended up replacing as few components as possible, resulting in the following hardware setup:

  • AMD Ryzen 5 3400G APU (4c/8t)
  • ASRock B450M Micro-ATX motherboard
  • Intel X520-DA2 10G SFP+ network card (half-height)
  • 16Gb DDR4-3200 RAM in two sticks of 8gb each
  • Existing 240Gb SSD boot drive and data storage pool were retained
  • Existing 120W PicoPSU was retained, along with the AC to DC converter, which was secured into the case with double sided foam tape.
  • Existing 80mm case fans were upgraded to Noctua equivalents since the cheap Rosewill case was very loud

With the new hardware setup, I was able to install the Ubuntu HWE (HardWare Enablement) package to get the latest kernel graphics drivers and permit the LXC container to access the GPU for hardware accelerated h.264 decoding. I was also able to connect the server to the switch with a 10G SFP+ DAC cable, although at this point in time there are no clients which can use 10G anyway, so at best it currently just allows higher aggregate throughput for multiple clients, and in reality it’s just the start of a future expansion to a 10G backbone.

Final Verdict

ZoneMinder is currently functioning and has been for several months. I continuously tweak the motion zones and thresholds to reduce the false triggers due to swaying tree shadows, flies, and spiders making webs in front of the camera. The visible area from two cameras could be improved by tree trimming. The LXC container has a 1Tb ZFS quota, ensuring it doesn’t fill my entire storage pool with months of recordings. The mobile app (zmNinja) works well, when combined with my personal home VPN (direct from my phone to my home router).

At a rate of approximately one per month, I installed 3 of the remaining 5 cameras around the house, leaving the last two as winter approached and I didn’t want to deal with running another conduit through brick to access the rear walkout of the house. But, there aren’t packages or cats waiting at that door, so it’s not high priority at this point in time.

Fall 2021 Update

The system described in this project was operational for 2 years without major issues. In the future, this setup was replaced with Frigate NVR, but the cameras, wiring advice, and software testing listed here is still valid.