Optimising the Rockchip RK3588 SBC for Frigate NVR: CPU, GPU, NPU and VPU offloading.
How I turned a low cost SBC into a hardware-accelerated Network Video Recorder (NVR). Offloading video decoding, object detection, and…
Optimising the Rockchip RK3588 SBC for Frigate NVR: CPU, GPU, NPU and VPU offloading.
How I turned a low cost SBC into a hardware-accelerated Network Video Recorder (NVR). Offloading video decoding, object detection, and transcoding to the CPU, GPU, and NPU and drawing under 10W at full load.
Most home NVRs force you to choose: buy a power-hungry x86 mini-PC, or settle for a basic recorder with no AI. I wanted; , 8-channel 1080p recording, real-time motion and object detection with extension capabilities into license plate recognition, facial recognition and AI linkage. All without the heat, noise or large power draw. The answer was hiding in a ‘hobbyist level’ single-board computer with dedicated hardware and onboard AI silicon
My design goals were simple but demanding:
- 8 × 1080p 25fps recording streams plus 8 × 640×480 5fps detection streams
- Motion filtering, object detection, and transcoding entirely on-device
- Deliver real-time facial, pet, and license plate recognition
- Integrate cleanly with Home Assistant
- Run like an appliance: <10W loaded, silent, and thermally stable even during hot Sydney summers
Why the ArmSOM Sige7?
The Sige7 from ArmSOM fits this brief because Rockchip’s RK3588 isn’t just a CPU — it’s a media SoC with lots of compute and dedicated co-processors:

Rockchip RK3588 specifications
A huge thanks to Platima Tinkers for the board introduction: https://www.youtube.com/watch?v=dwth8_nQvG4

External cameras view
Step 1: NVMe Boot (Skip the SD Card)
ArmSOM ships firmware configured to support SD or eMMC boot, but an NVMe SSD is faster to boot and much better at handling sustained multi-channel writes. The process to configure for NVMe boot is straightforward using Joshua Riek’s Ubuntu Server 24.04 image which includes an ubuntu rockchip installer;
a. Flash the Ubuntu Server image to an SD Card and boot from it
b. Clone the running system to NVMe with the following command:
sudo ubuntu-rockchip-install /dev/nvme0n1
c. Flash the U-Boot loader to the eMMC so the board boots directly from NVMe:
cd /usr/lib/u-boot
sudo dd if=idbloader.img of=/dev/mmcblk0 seek=64 conv=notrunc
sudo dd if=u-boot.itb of=/dev/mmcblk0 seek=16384 conv=notrunc
d. Remove the SD card and reboot. lsblk should show the root filesystem on nvme0n1p2.
That’s it. The board now boots in seconds from the NVMe.

lsblk showing nvme0n1p2 as / root
Step 2: Cooling and OS Tuning
a. Cooling. Sydney summers regularly exceed 40°C so I installed the ArmSOM active cooling kit which is a low-profile heatsink with builtin PWM fan for only $12. On Joshua Riek’s image, the kernel device tree handles fan curves natively with no fancontrol daemon required. The standard presets are:

Ubuntu Server default fan speeds
b. Memory Tuning.
Docker shm_size. In the compose file I set shm_size: "512mb". This is generous for the 8 x 640x480 detection streams and can support a camera or two at the higher 1080p detection (for example if required for License Plate Recognition at distance).
Frigate tmpfs swap size. Within the frigate config file set the tmpfs size: 26843545. Frigate uses tmpfs as a ram-drive to store recording camera streams. With 8 cameras a 256mb tmpfs is enought for 1–2 minutes. As the queue is flushed to SSD every 10 seconds this is ample headroom and a reduction from the Ubuntu default.
OS Swap file. As a final guard-rail to protect from out-of-memory errors I implemented an 8GB swapfile with low swappiness.
LPR and facial recognition each take RAM so there is a possibility of running out of memory if everything is happening at once. A swap file provides final insurance that the system will remain stable.
sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile && sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
Step 3: Docker and Optional Monitoring
The system runs Frigate in Docker with a simple folder structure under /home/ubuntu/smarthome/ (~.smarthome/). Install Docker from the official repository, then add your user to the docker group.
I also run a lightweight monitoring stack:
- Portainer (:9000) — container GUI
- Beszel (:8090) — server monitoring platform with graphics
- Glances (:61208) — deep system metrics
- Scrutiny (:8080) — NVMe SMART monitoring
- Duplicati (:8200) — encrypted cloud backups

Beszel monitoring of Frigate NVR
Step 4: Frigate with RK3588 Hardware Offload
This is where the magic happens. The Frigate stable-rk image supports Rockchip’s VPU, NPU, and GPU out of the box.
Here is mu woprking Docker Compose file. Key points: privileged: true, network_mode: host, and mapping the specific /dev/ nodes for the RK3588 media pipeline for the respective hardware offloading.
services:
frigate:
container_name: frigate
network_mode: host
privileged: true
restart: unless-stopped
stop_grace_period: 30s
image: ghcr.io/blakeblackshear/frigate:stable-rk
platform: linux/arm64
shm_size: "512mb"
security_opt:
- apparmor=unconfined
- systempaths=unconfined
devices:
- /dev/rknpu:/dev/rknpu
- /dev/dri:/dev/dri
- /dev/mali0:/dev/mali0
- /dev/dma_heap:/dev/dma_heap
- /dev/mpp_service:/dev/mpp_service
- /dev/rga:/dev/rga
- /dev/bus/usb:/dev/bus/usb
volumes:
- /sys:/sys:ro
- /etc/localtime:/etc/localtime:ro
- /home/ubuntu/smarthome/frigate/config:/config
- /home/ubuntu/smarthome/frigate/storage:/media/frigate
- type: tmpfs
target: /tmp/cache
tmpfs:
size: 268435456
environment:
FRIGATE_RTSP_PASSWORD: "password-here"
healthcheck:
test: ["CMD-SHELL", "python3 -c 'import socket; s = socket.socket(); s.connect((\"127.0.0.1\", 5000))' || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 45s
For the Frigate config file, here are some key snippets from config.yml for optimal Frigate setup. Tell Frigate to use the hardware decoder and the 3-core NPU:
ffmpeg:
hwaccel_args: preset-rk-h264
detectors:
rknn:
type: rknn
num_cores: 3
Enable enhanced features:
lpr:
enabled: true
model_size: small
face_recognition:
enabled: true
model_size: large
detection_threshold: 0.7
recognition_threshold: 0.85
min_area: 500
Use go2rtc to pull both high-res (record) and low-res (detect) streams from each camera. Frigate becomes the single client connecting to the camera; everything else — Home Assistant, browsers, mobile apps — reads from Frigate’s restream. This slashes camera CPU load and lets the VPU handle all inbound compression.
go2rtc:
ffmpeg:
bin: /usr/lib/ffmpeg/7.0/bin/ffmpeg
streams:
garage_hires: rtsp://user:pass@ip:554/av_stream1/ch0
garage_detect: rtsp://user:pass@ip:554/av_stream2/ch1
# ... repeat for all cameras
I keep Birdseye on continuous mode with restream: true so the dashboard is available to LAN users as a camera stream which can display on any browser, including the family TV.
birdseye:
enabled: true
restream: true
idle_heartbeat_fps: 2
mode: continuous
Frigate metrics view shows the CPU and GPU just idlingduring normal daily operation…

Frigate Metrics view
Step 5: Camera Tuning and Network Isolation
My first four-camera setup failed with continuous board overloading and overheating: wind-triggered motion on trees and shrubs saturated the CPU because every pixel change was fed to object detection.
The following fixes were simple but transformative:
- Detection masks in Frigate to ignore swaying foliage, reducing CPU load
- Resolution split: 1080p H.265 for recording; 640×480 H.264 at 5fps for detection. Object recognition works fine on 640 x 480
- Substreams for clients: Household devices range from PCs and phones to a Samsung AI fridge and NS PanelPro. Standardizing on the low-res H.264 detect stream guarantees universal compatibility.
With eight cameras running, inbound traffic is only ~18 Mbps—not a big load for 2.5GbE. Still, for security and to keep video off the family Wi-Fi, I connected the POE cameras to a small managed switch on the second Sige7 ethernet port. Camera traffic is completely isolated now and with the PoE management software I can even power-cycle individual cameras remotely.

Step 6: Backing Up a Live Database
Frigate uses SQLite, and copying a live .db file will corrupt it. The Duplicati backup uses two shell scripts to snapshot the database cleanly:
- Pre-backup:
docker exec frigate sqlite3 /config/frigate.db ".backup '/config/frigate_backup.db'" - Post-backup: Delete the temporary snapshot.
Duplicati grabs the media folders and the static snapshot, excluding the transient /frigate/media/cache. To restore, you stop Frigate, restore the snapshot, and run a SQLite VACUUM INTO to rebuild the live database.
Results: An Appliance-Grade NVR
By distributing work across the RK3588’s dedicated silicon and using the SoC onbaord hardware for all the heavy lifting, the system barely sweats:
Typical Load is;

Typical Sige7 load
The system boots in seconds and simply stays up. After months of operation, I’ve stopped SSHing in to check on it.
Future Upgrades
With headroom remaining, I’m expanding the system:
- Indoor POE cameras to broaden coverage and for cat tracking
- Garage door state detection: Training Frigate’s model to recognize open/closed states as the house has no door sensors. The Frigate status can feed directly into Home Assistant security automations
- Mail/courier alerts: Frigate supports monitoring Loitering zones on the camera feeds which can trigger WhatsApp messages with snapshots. Using external AI calls to analyse the images to determine courier vs. regular mail
- Smart arrival: LPR identifies the family car in the driveway fast enough and opens the garage door on arrival (target <2 seconds).
- Cat finder: With indoor cameras, I can query the last-known location of our hiding cat by working backward through detection events—no GPS collar required.
Conclusion
Building an AI NVR doesn’t require an expensive x86 server or cloud subscriptions. The Rockchip RK3588—when properly configured—turns the ArmSOM Sige7 into a genuinely appliance-grade platform: silent, stable, sub-10W, and capable of real-time object detection across eight cameras. The key was respecting the hardware architecture: let the VPU decode, the NPU infer, the GPU render, and keep the CPU almost idle.
ArmSOM’s documentation rewards patience, and using the pre-built Ubuntu images remove much of the kernel-level grunt work. If you’re comfortable with Docker and YAML, this is one of the most cost-effective ways to add privacy-first, local AI surveillance to a smart home.
메타데이터
- post_id
- ee226ee85cf1
- slug
- optimising-the-rockchip-rk3588-sbc-for-frigate-nvr-cpu-gpu-npu-and-vpu-offloading-ee226ee85cf1
- url
- https://medium.com/@beegeenz/optimising-the-rockchip-rk3588-sbc-for-frigate-nvr-cpu-gpu-npu-and-vpu-offloading-ee226ee85cf1
- canonical_url
- https://medium.com/@beegeenz/optimising-the-rockchip-rk3588-sbc-for-frigate-nvr-cpu-gpu-npu-and-vpu-offloading-ee226ee85cf1
- author_url
- https://medium.com/@beegeenz
- status
- ok
- fetched_at
- 2026-07-11 09:39:04