Upgrading Frigate NVR: yolonas 640×640 on Intel Arc A310 via OpenVINO

A crow kept getting flagged as a cat. Inference was fast enough, coverage was fine, and nothing was broken — but the model was making mistakes I knew were fixable. When a hardware migration gave me a proper discrete GPU, I used it as an opportunity to rethink the whole detection stack. Here’s what changed.


The problem with good enough

My Frigate setup was working — mostly. Object detection ran on an Intel iGPU via OpenVINO, inference times were acceptable, and I had cameras covering the areas I cared about. But a few things kept bothering me.

A crow kept getting detected as a cat. The bounding boxes were similar enough at 320×320 input resolution that the model couldn’t reliably tell them apart. Face recognition on outdoor cameras was hit or miss — at small bounding box sizes, the crops fed to ArcFace were too pixelated to be useful. And I knew I wanted to add more cameras, which meant I needed more headroom.

The trigger to actually fix this was hardware: I was already migrating Frigate to a dedicated host with an Intel Arc A310. That meant significantly more GPU compute. Time to stop patching around the limitations of the old setup.


Architecture

Dedicated host (low-power, small form factor)
└── Proxmox LXC
    └── Frigate 0.17
        ├── Detector: OpenVINO → Intel Arc A310 (dGPU)
        └── Model: Frigate+ yolonas 640×640

Cameras → go2rtc → Frigate
                 → MQTT → Home Assistant

I run Proxmox on the bare metal, Frigate in an unprivileged LXC with GPU passthrough. I’ve written about why I use Proxmox instead of running Frigate directly — here’s why.


Why Arc A310

The Arc A310 is Intel’s entry-level discrete GPU — around €100 refurbished in low-profile format. For an NVR workload it’s a good fit: OpenVINO support is first-class, power consumption is low, and the performance delta vs. an iGPU is significant for inference workloads.

One thing to know if you’re running Frigate in an LXC: earlier OpenVINO versions had a bug that caused crashes specifically with iGPU passthrough in LXC environments. That bug doesn’t affect discrete GPUs like the Arc A310, so you can run current OpenVINO without workarounds.

GPU passthrough in a Proxmox LXC for a discrete GPU looks like this in /etc/pve/lxc/XXXX.conf:

lxc.cgroup2.devices.allow: c 226:* rwm
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file

Verify the GPU is recognized inside the LXC:

apt install intel-gpu-tools
intel_gpu_top

You should see the Arc listed and GPU utilization rising during inference.


The model decision: yolonas vs yolov9s

Frigate+ offers several model architectures. For OpenVINO specifically, the relevant options are yolov9t, yolov9s, and yolonas — each available at 320×320 and 640×640 input resolution. Other architectures (mobiledet, hailo variants) target different accelerators.

I was running yolov9s 320×320. The upgrade path had two dimensions: architecture and resolution.

Resolution first. Going from 320×320 to 640×640 doubles the pixel count per object. For small or distant objects — a cat far from the camera, a face in an outdoor scene — this matters a lot. The model sees more detail to work with.

Architecture second. yolonas (Neural Architecture Search) is optimized for accuracy rather than speed. Compared to yolov9s, it handles similar-looking objects better and produces more consistent scores on difficult cases. The tradeoff is slightly higher compute cost per inference.

On Arc A310, the measured inference time for yolonas 640×640 is around 10ms — well within the 100ms budget Frigate works with, and with plenty of headroom for more cameras.

The Frigate config for this:

detectors:
  detector01:
    type: openvino
    device: GPU

model:
  path: plus://YOUR_MODEL_ID
  width: 640
  height: 640
  input_tensor: nhwc      # yolonas-specific — yolov9s uses nchw
  input_pixel_format: bgr # yolonas-specific — yolov9s uses rgb
  model_type: yolonas

Note the input_tensor and input_pixel_format values — they’re different from yolov9s. Getting these wrong won’t necessarily produce an error, just bad detections.


Threshold reset

When you switch model architectures, don’t carry over your thresholds. Score distributions differ between models — a value that worked well for yolov9s will likely be wrong for yolonas, which tends to produce higher scores.

Start from defaults and observe for 48 hours before tuning:

objects:
  filters:
    person:
      min_score: 0.5   # Frigate default
      threshold: 0.7
    cat:
      min_score: 0.5   # Start here, not at your old tuned value
      threshold: 0.7

Geometric filters — min_areamax_area, zone coordinates, object filter masks — are model-independent and can be carried over directly.


Object filter masks for fixed false positives

One practical improvement I made alongside the model upgrade: using object filter masks for fixed objects that consistently produce false positives.

The difference between a motion mask and an object filter mask matters here. A motion mask tells Frigate not to send frames from that area to the detector at all. An object filter mask lets detection run everywhere, but ignores detections whose center point falls within the masked area.

For a stationary object like a trailer or a lamp that keeps triggering — object filter mask is the right tool. A person who appears next to or behind the masked object will still be detected.

cameras:
  my-camera:
    objects:
      filters:
        person:
          mask:
            - 0.10,0.40,0.35,0.40,0.35,0.85,0.10,0.85  # trailer, left side
        cat:
          mask:
            - 0.85,0.60,1.0,0.60,1.0,1.0,0.85,1.0      # lamp, right edge

Coordinates come from Frigate’s built-in mask editor — draw the polygon, copy the values.

Frigate also supports license plate recognition and face recognition via the same OpenVINO pipeline. Both are outside the scope of this post — the privacy and legal considerations for residential deployments deserve more space than a footnote.


Performance after migration

After switching to yolonas 640×640 on Arc A310:

  • Detector inference: ~10ms (expected 25–35ms — pleasantly surprised)
  • Skipped frames: 0 across all cameras
  • System CPU: ~15% total

The crow hasn’t come back as a cat since.


Views expressed are my own and not those of my employer.