# Frigate Camera Control Bridge Generic sidecar for a single Frigate instance. The container reads Frigate configuration from `/api/config`, discovers cameras from `go2rtc` and direct `ffmpeg.inputs[].path` stream URLs, then exposes light and siren controls through Home Assistant MQTT Discovery plus an emergency HTTP fallback GUI. ## Design - One image works for Podman now and Kubernetes later. - Runtime configuration is environment-based; no Frigate config mount is needed. - The sidecar waits for Frigate startup and retries `/api/config`. - The sidecar periodically refreshes `/api/config`, so added or removed cameras can update MQTT Discovery without a container restart. - On startup it runs a safe `all-off` by default, sets switch entities to `OFF`, and publishes retained MQTT state. - Home Assistant MQTT Discovery payloads include semantic MDI icons for all-off, siren, red-blue/strobe, and white-light entities. - Alarms and lights have default auto-off timers: siren 180s, red-blue/strobe 300s, white light 600s. The GUI timer is rendered from a backend timestamp, so page refreshes do not reset it. - Siren `ON` actions require a browser confirmation in the fallback GUI. - If `ffmpeg.inputs[].path` points at `rtsp://127.0.0.1:8554/...`, the sidecar treats it as a go2rtc gateway and resolves the real camera URL from `go2rtc.streams`. - If Frigate uses a direct non-loopback stream URL in `ffmpeg.inputs[].path`, the sidecar uses that direct URL and does not resolve go2rtc in parallel. - In env mode, missing MQTT or camera credentials are startup errors; the sidecar does not look up credentials in Quadlets or Frigate config. - The fallback GUI listens on `5011` by default because `5001` may already be used by Frigate. - GUI languages use standard gettext files: `locale//LC_MESSAGES/*.po` and `.mo`. ## Environment | Variable | Meaning | | --- | --- | | `FRIGATE_NAME` | Instance name, for example `frigate-main`. | | `FRIGATE_URL` | Frigate API URL, for example `http://frigate-main.example.test:5000`. | | `FRIGATE_PUBLIC_URL` | Optional public GUI URL used by camera stream links, for example a reverse proxy URL. If omitted, stream links use `FRIGATE_URL`. | | `FRIGATE_CAMERA_PATH_TEMPLATE` | Optional camera page path or full URL template, defaults to `/#{camera_quoted}`. Available placeholders: `{camera}`, `{camera_quoted}`, `{frigate_url}`, `{frigate_public_url}`. | | `MQTT_HOST`, `MQTT_PORT` | MQTT broker. | | `MQTT_USER`, `MQTT_PASSWORD` | MQTT credentials. | | `DEFAULT_CAMERA_USER`, `DEFAULT_CAMERA_PASSWORD` | Default credentials for cameras discovered from Frigate. | | `BASE_TOPIC` | MQTT base topic, for example `frigate_camera_control/frigate-main`. | | `DISCOVERY_PREFIX` | Home Assistant MQTT Discovery prefix, usually `homeassistant`. | | `UI_LANGUAGE` | Default GUI and HA entity language, defaults to `en`. | | `HTTP_PORT` | Fallback GUI port, defaults to `5011`. | | `HTTP_TOKEN` | Optional HTTP GUI/API token. | | `FRIGATE_REFRESH_SECONDS` | Frigate config refresh interval, defaults to `300`; `0` disables it. | | `SNAPSHOT_RETRY_SECONDS` | Retry interval while a snapshot is missing, defaults to `600`. | | `SNAPSHOT_REFRESH_SECONDS` | Refresh interval after snapshots are available, defaults to `3600`. | | `SNAPSHOT_LIVE_ON_GUI` | Fetch a fresh Frigate snapshot when the GUI loads, defaults to `true`. | | `STARTUP_ALL_OFF` | Send safe OFF commands during startup, defaults to `true`. | | `AUTO_OFF_SIREN_SECONDS` | Siren auto-off, defaults to `180`. | | `AUTO_OFF_RED_BLUE_SECONDS` | Red-blue/strobe auto-off, defaults to `300`. | | `AUTO_OFF_WHITE_LIGHT_SECONDS` | White-light auto-off, defaults to `600`. | ## Build ```bash docker build -t frigate-camera-control-bridge:1.0 . docker build -f Dockerfile.dev -t frigate-camera-control-bridge:dev . ``` ## Run Podman Quadlet example: ```text examples/podman-quadlet/ ``` Docker Compose example: ```text examples/docker-compose/ ``` Kubernetes sidecar example: ```text examples/kubernetes/ ``` Local check: ```bash docker run --rm \ -e FRIGATE_NAME=example \ -e FRIGATE_URL=http://frigate:5000 \ -e MQTT_HOST=mqtt.local \ -e MQTT_USER=user \ -e MQTT_PASSWORD=password \ -e DEFAULT_CAMERA_USER=admin \ -e DEFAULT_CAMERA_PASSWORD=password \ -p 5011:5011 \ frigate-camera-control-bridge:1.0 --check ``` ## HTTP GUI ```text http://:5011/ http://:5011/?lang=pl http://:5011/api/actions http://:5011/snapshot/.jpg http://:5011/healthz http://:5011/readyz ``` If `HTTP_TOKEN` is set, pass `?token=` or the `X-Bridge-Token` header. ## Manual Commands ```bash /app/frigate-camera-control-bridge.py --list /app/frigate-camera-control-bridge.py --check /app/frigate-camera-control-bridge.py --all-off /app/frigate-camera-control-bridge.py --action frigate_main_camera_a_red_blue off ``` ## Languages 1. Add `locale/de/LC_MESSAGES/`. 2. Copy `frigate_camera_control_bridge.po` from `locale/en/LC_MESSAGES/`. 3. Translate `msgstr`. 4. Run `python3 tools/compile_gettext.py locale`. 5. Rebuild the image. The GUI will discover the new language automatically. ## Kubernetes Notes - Put the bridge container in the same pod as Frigate, or point `FRIGATE_URL` at the Frigate service. - Use `readinessProbe` on `/readyz`. - Pass secrets through env vars from `Secret`. - Keep `/var/lib/frigate-camera-control-bridge` on a small persistent volume if stale Home Assistant discovery cleanup should survive pod recreation.