From 3140eff6178558d8098ae3aac19735042c18050e Mon Sep 17 00:00:00 2001 From: jpmvaz Date: Sun, 13 Sep 2026 21:52:39 +0100 Subject: [PATCH] v12 --- Frigate/README.md | 201 +++++++++++++++++++++++++++++++++++++ Frigate/config.yml | 51 ++++++++++ Frigate/docker-compose.yml | 26 +++++ Frigate/frigate.tar.gz | Bin 0 -> 3988 bytes Frigate/frigate.zip | Bin 0 -> 4897 bytes 5 files changed, 278 insertions(+) create mode 100644 Frigate/README.md create mode 100644 Frigate/config.yml create mode 100644 Frigate/docker-compose.yml create mode 100644 Frigate/frigate.tar.gz create mode 100644 Frigate/frigate.zip diff --git a/Frigate/README.md b/Frigate/README.md new file mode 100644 index 0000000..6202b7a --- /dev/null +++ b/Frigate/README.md @@ -0,0 +1,201 @@ +# Frigate on Raspberry Pi 5 with a USB Google Coral + +A ready-to-use Frigate NVR deployment for a Raspberry Pi 5 using a USB Google +Coral EdgeTPU for hardware-accelerated object detection. + +Based on the official Frigate documentation: https://docs.frigate.video/ + +--- + +## What's in this folder + +``` +frigate/ +├── docker-compose.yml # Container definition (USB Coral passthrough, ports, volumes) +├── config/ +│ └── config.yml # Frigate configuration (detector, cameras, recording) +├── storage/ # Recordings, snapshots, and exports live here +└── README.md # This file +``` + +--- + +## Before you start — hardware notes + +- **Power the Pi properly.** Use the official 27W USB-C supply for the Pi 5. +- **The USB Coral is power-hungry.** If you also attach a USB SSD or other USB + devices, the Pi may not supply enough power and you'll get instability. Use a + **powered external USB hub** in that case. +- **Plug the Coral into a USB 3.0 (blue) port**, ideally through the powered hub. +- **No hardware video decode on the Pi 5.** Unlike the Pi 4, the Pi 5 does not + expose a `/dev/video11` decoder for Frigate, so camera decoding runs on the + CPU. Keep camera count and detect resolution modest, and use camera + **substreams** for the detect role (the included config already does this). + +--- + +## Step 1 — Prepare the OS + +Use a **64-bit** Debian-based OS (Raspberry Pi OS 64-bit, Bookworm or Trixie). +Flash it, boot, then update: + +```bash +sudo apt update && sudo apt full-upgrade -y +sudo reboot +``` + +## Step 2 — Install Docker and Docker Compose + +```bash +curl -fsSL https://get.docker.com -o get-docker.sh +sudo sh get-docker.sh +``` + +Add your user to the `docker` group so you don't need `sudo` each time: + +```bash +sudo usermod -aG docker $USER +``` + +Log out and back in (or reboot) for the group change to apply, then verify: + +```bash +docker --version +docker compose version +``` + +## Step 3 — Connect and verify the USB Coral + +Plug the Coral in (USB 3.0 port, powered hub if you have other USB devices). +The Frigate container ships with the EdgeTPU libraries built in, so you do **not** +need to install any Coral runtime on the host — passing `/dev/bus/usb` into the +container (already configured in `docker-compose.yml`) is enough. + +Confirm the host sees it: + +```bash +lsusb +``` + +A freshly plugged Coral appears as `Global Unichip Corp.`; after it runs +inference once it re-enumerates as `Google Inc.`. Either is fine. + +## Step 4 — Put these files on the Pi + +Copy this entire `frigate/` folder to the Pi (e.g. to your home directory so it +lives at `~/frigate`). You can use `scp`, a USB stick, or `git`. + +```bash +cd ~/frigate +``` + +## Step 5 — Set your shm-size (shared memory) + +Frigate stores decoded frames in shared memory. Calculate the minimum per camera +using your **detect** resolution (this example is 720p, including logs): + +```bash +python3 -c 'print("{:.2f}MB".format((1280 * 720 * 1.5 * 20 + 270480) / 1048576 + 40))' +# ~66.63MB for one 720p camera +``` + +Multiply the per-camera portion by your number of cameras and add ~40MB for +logs. The provided `docker-compose.yml` uses `512mb`, which comfortably covers +several cameras. Adjust the `shm_size` value if needed. + +## Step 6 — Edit the config for your cameras + +Open `config/config.yml` and update: + +- **Camera RTSP URLs** — replace `user`, `password`, IP, and stream paths with + your camera's real values. The RTSP path format varies by manufacturer. +- **`detect` width/height** — must match the resolution of the stream assigned + the `detect` role. +- **MQTT** — set `enabled: true` and fill in the host if you use Home Assistant. + +Also change `FRIGATE_RTSP_PASSWORD` in `docker-compose.yml` from `password` to +something of your own. + +## Step 7 — Start Frigate + +```bash +cd ~/frigate +docker compose up -d +``` + +Follow the logs to confirm a clean startup and that the Coral was found: + +```bash +docker logs -f frigate +``` + +Look for the EdgeTPU being detected and an inference speed (typically ~8–15ms on +a USB Coral). Press `Ctrl+C` to stop following the logs. + +## Step 8 — Open the web UI + +``` +https://:8971 +``` + +On first launch Frigate creates an admin account. Check the container logs for +the initial password, log in, and change it. + +--- + +## Verifying the Coral is actually being used + +In the web UI, open the **System / Metrics** page. Your `coral` detector should +be listed with an inference speed and a detection FPS. If the inference speed is +very high (hundreds of ms), detection is running on CPU and the Coral is not +being used properly — see troubleshooting below. + +## Troubleshooting: Coral not detected + +Try these in order: + +1. Restart the container: `docker compose restart` +2. Unplug/replug the Coral, then restart. +3. Use a **powered USB hub** if other USB devices are attached — power + starvation is the most common cause of instability on the Pi. +4. Try a different USB port; prefer USB 3.0 (blue). +5. Confirm `lsusb` shows the Global Unichip or Google device. + +Official EdgeTPU troubleshooting: https://docs.frigate.video/troubleshooting/edgetpu + +--- + +## Updating Frigate later + +```bash +cd ~/frigate +docker compose pull +docker compose up -d +``` + +## Useful commands + +```bash +docker compose up -d # start (detached) +docker compose down # stop and remove the container +docker compose restart # restart +docker logs -f frigate # follow logs +``` + +--- + +## Ports reference + +| Port | Purpose | +|------|----------------------------------------------------| +| 8971 | Authenticated web UI + API (use this) | +| 5000 | Internal unauthenticated UI/API (expose carefully) | +| 8554 | RTSP restreaming | +| 8555 | WebRTC (two-way talk), TCP + UDP | + +## Documentation + +- Installation: https://docs.frigate.video/frigate/installation +- Object detectors (Coral): https://docs.frigate.video/configuration/object_detectors +- Full config reference: https://docs.frigate.video/configuration/reference +- Camera setup: https://docs.frigate.video/frigate/camera_setup diff --git a/Frigate/config.yml b/Frigate/config.yml new file mode 100644 index 0000000..7d8e77a --- /dev/null +++ b/Frigate/config.yml @@ -0,0 +1,51 @@ +mqtt: + enabled: false # set to true and fill in host below if you use Home Assistant / MQTT + # host: 192.168.1.10 + # port: 1883 + # user: mqtt_user + # password: mqtt_password + +detectors: + coral: + type: edgetpu + device: usb # single USB Coral. Uses the bundled Mobiledet model by default. + +cameras: + camera_1: + ffmpeg: + inputs: + # Full-resolution main stream -> used for recording + - path: rtsp://user:password@192.168.1.50:554/stream1 + roles: + - record + # Lower-resolution substream -> used for detection (saves CPU on the Pi 5) + # If your camera has no substream, delete this block and add "detect" + # to the roles list above instead. + - path: rtsp://user:password@192.168.1.50:554/stream2 + roles: + - detect + detect: + width: 1280 # must match your detect (sub)stream resolution + height: 720 + fps: 5 + +record: + enabled: true + retain: + days: 7 + mode: motion + +snapshots: + enabled: true + retain: + default: 14 + +# Objects to track. Defaults to person if omitted. +objects: + track: + - person + - car + - cat + - dog + +version: 0.16-0 diff --git a/Frigate/docker-compose.yml b/Frigate/docker-compose.yml new file mode 100644 index 0000000..8bdb5c6 --- /dev/null +++ b/Frigate/docker-compose.yml @@ -0,0 +1,26 @@ +services: + frigate: + container_name: frigate + privileged: true # simplifies USB Coral access; can be tightened later + restart: unless-stopped + stop_grace_period: 30s + image: ghcr.io/blakeblackshear/frigate:stable + shm_size: "512mb" # adjust per the calculation in the README (Step 5) + devices: + - /dev/bus/usb:/dev/bus/usb # passes the USB Coral into the container + volumes: + - /etc/localtime:/etc/localtime:ro + - ./config:/config + - ./storage:/media/frigate + - type: tmpfs # 1GB in-memory cache for recording segments + target: /tmp/cache + tmpfs: + size: 1000000000 + ports: + - "8971:8971" # authenticated UI + API + # - "5000:5000" # internal unauthenticated access — expose carefully + - "8554:8554" # RTSP restreaming + - "8555:8555/tcp" # WebRTC over TCP + - "8555:8555/udp" # WebRTC over UDP + environment: + FRIGATE_RTSP_PASSWORD: "password" # change this diff --git a/Frigate/frigate.tar.gz b/Frigate/frigate.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..b5f01a8a7057ce7ae8eb6050aa62741e60bd33b8 GIT binary patch literal 3988 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