Site icon Qianhe Chen
From Hikvision NVR to Frigate on TrueNAS

TL;DR

I kept the Hikvision NVR for storage, but moved detection to Frigate on my TrueNAS server. With zones, an ONNX YOLO detector, and an NVIDIA P4 for acceleration, I now get smarter alerts and a web UI that works perfectly on macOS.

Why I moved off the NVR

Last year, after moving into a new home, we installed four Hikvision cameras. I initially connected everything to a Hikvision NVR for live view and recording. It worked, but I soon ran into limitations.

flowchart TB
    subgraph Before["Before: NVR isolates the cameras"]
        VLAN3[VLAN 3] --> NVR["Hikvision NVR (on VLAN 3)"]
        NVR -->|built-in PoE / internal switch| CamNet["Camera subnet 192.168.254.x"]
        CamNet --> C1["Camera 1"]
        CamNet --> C2["Camera 2"]
        CamNet --> C3["Camera 3"]
        CamNet --> C4["Camera 4"]
        Mac[Mac on home network] -->|no direct access| CamNet
    end

The biggest surprise was networking. The NVR sat on VLAN 3, and all cameras were physically connected to the NVR. That meant the cameras lived behind the NVR on its private camera subnet (for example 192.168.254.x). From my normal home network I could not reach the cameras directly, so I assumed the NVR was the only gateway.

That assumption became painful because my daily machine is a Mac.

Hikvision’s web interface required browser plugins that only worked well on Windows, and the desktop client was not a good option on macOS. Checking the cameras became a chore, so I started looking for a setup that would work cleanly from macOS.

I even tried running a Windows virtual machine on my Mac. It worked, but it was clunky. Camera settings were slow to reach, and some configuration flows felt incomplete.

I also tried to keep the NVR at the center and forward video elsewhere via RTSP. That turned into a full day of debugging: the RTSP streams coming out of the NVR were not decodable in my setup.

Only after watching a few videos did I realize the obvious approach: connect the cameras to my network directly, log into each camera’s admin page, and grab RTSP from the source.

The first step was simple: move the cameras onto VLAN 3 directly so they have normal IPs and can be accessed and integrated like any other device.

flowchart TB
    subgraph After["After: cameras on VLAN 3 directly"]
        VLAN3a[VLAN 3] --> C1a["Camera 1 (VLAN 3 IP)"]
        VLAN3a --> C2a["Camera 2 (VLAN 3 IP)"]
        VLAN3a --> C3a["Camera 3 (VLAN 3 IP)"]
        VLAN3a --> C4a["Camera 4 (VLAN 3 IP)"]
        Maca[Mac on home network] -->|routed access| VLAN3a
    end

The migration: TrueNAS Apps + Frigate

Once the cameras were on VLAN 3, I wanted two things: something I could use daily on macOS, and a clean path to smarter detection and automation. That’s when I started building around Frigate.

I installed Frigate from the TrueNAS Apps catalog. It kept updates, storage paths, and GPU access in one place, and it made the whole setup feel like a “real” service instead of another weekend experiment.

I’m not going to paste my full config here. It is long and it changes as I iterate. Instead, I keep an up-to-date config and notes in a Github Gist.

From there, I added the cameras via RTSP. I started boring: confirm each stream decodes reliably first, then enable detection.

One small decision made everything easier to run and easier to debug:

  • Use a lower-resolution sub-stream for detection (lower latency, cheaper to run)
  • Keep a higher-quality stream for live view and storage

Once detection was running across multiple cameras, I enabled GPU acceleration with an NVIDIA P4 to keep the system responsive.

The model detour: YOLO-NAS → YOLOv9

Frigate’s documentation recommended YOLO-NAS, and it even provided a notebook that claims you can run it and export a final ONNX model.

In my case, that notebook did not run end-to-end. After a lot of time spent trying to reproduce the “happy path” (and seeing many similar complaints online), I stopped fighting it.

So I switched back to a classic YOLO workflow. I decided to try YOLOv9, exported it to ONNX locally, and plugged that ONNX model into Frigate. That was the moment the detection pipeline finally felt “done”.

If you are choosing a detector model today, my recommendation is simple: follow the official Frigate documentation, convert a supported YOLO model to ONNX, and skip YOLO-NAS. For me, YOLO-NAS was a disaster and it was surprisingly hard to get a clean, reproducible export.

Results

I ended up with a hybrid setup that fits my priorities:

  • Storage and playback: Hikvision NVR
  • Detection: Frigate (zones + ONNX model)
  • Acceleration: NVIDIA P4

Most importantly, everything is accessible from the web UI. That means my Mac workflow is no longer blocked by vendor plugins or Windows-only tooling.

Lessons learned

  • Get RTSP from the camera, not the NVR. Debugging “mystery” NVR streams is a time sink.
  • Keep detection cheap: use a sub-stream for detect, and save the main stream for viewing/storage.
  • Prefer boring, well-supported model paths (YOLO → ONNX). YOLO-NAS was not worth the hassle for me.

If you want the exact config (go2rtc restreams, camera streams, zones, and the ONNX model path), I keep it updated here: