Compare commits

...
8 Commits
Author SHA1 Message Date
ZhaiSoul e040500410 feat: update shm calculator tips && style 2026-03-21 17:53:20 +08:00
ZhaiSoulandcnb 73fe8f97d4 docs: add shm calulator 2026-02-24 12:16:58 +08:00
Josh HawkinsandGitHub 352d271fe4 Update HA docs with MQTT example (#22098)
* update HA docs with MQTT example

* format block as yaml
2026-02-23 10:25:03 -06:00
a6e11a59d6 docs: Add detail to face recognition MQTT update docs (#21942)
* Add detail to face recognition MQTT update docs

Clarify that the weighted average favors larger faces and
higher-confidence detections, that unknown attempts are excluded,
and document when name/score will be null/0.0.

* Fix score decimal in MQTT face recognition documentation

`0.0` in JSON is just `0`.

* Clarify score is a running weighted average

* Simplify MQTT tracked_object_update docs with inline comments

Move scoring logic details to face recognition docs and keep
MQTT reference concise with inline field comments and links.

* fix (expand) lpr doc link

* rm obvious lpr comments

---------

Co-authored-by: Kai Curry <kai@wjerk.com>
2026-02-23 06:46:55 -07:00
a7d8d13d9a docs: Add frame selection and clean copy details to snapshots docs (#21946)
* docs: Add frame selection and clean copy details to snapshots docs

Document how Frigate selects the best frame for snapshots, explain the
difference between regular snapshots and clean copies, fix internal
links to use absolute paths, and highlight Frigate+ as the primary
reason to keep clean_copy enabled if regular snapshot is configured clean.

* revert - do not use the word event

* rm clean copy is only saved when `clean_copy` is enabled

* Simplified the Frame Selection section down to a single paragraph.

* rm note about snapshot file ext change from png to webp

---------

Co-authored-by: Kai Curry <kai@wjerk.com>
2026-02-23 06:45:29 -07:00
Matt RusiniakandGitHub 4d51f7a1bb Fix script for downloading RF-DETR (#22083) 2026-02-22 07:57:27 -07:00
GuoQing LiuandGitHub c9be98f935 docs: fix hailo setup numbering error (#22066)
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
2026-02-21 12:19:46 -06:00
GuoQing LiuandGitHub 85ed8c6432 docs: fix image address (#22067) 2026-02-21 12:19:21 -06:00
7 changed files with 388 additions and 34 deletions
+3 -3
View File
@@ -1514,11 +1514,11 @@ RF-DETR can be exported as ONNX by running the command below. You can copy and p
```sh
docker build . --build-arg MODEL_SIZE=Nano --rm --output . -f- <<'EOF'
FROM python:3.11 AS build
FROM python:3.12 AS build
RUN apt-get update && apt-get install --no-install-recommends -y libgl1 && rm -rf /var/lib/apt/lists/*
COPY --from=ghcr.io/astral-sh/uv:0.8.0 /uv /bin/
COPY --from=ghcr.io/astral-sh/uv:0.10.4 /uv /bin/
WORKDIR /rfdetr
RUN uv pip install --system rfdetr[onnxexport] torch==2.8.0 onnx==1.19.1 onnxscript
RUN uv pip install --system rfdetr[onnxexport] torch==2.8.0 onnx==1.19.1 transformers==4.57.6 onnxscript
ARG MODEL_SIZE
RUN python3 -c "from rfdetr import RFDETR${MODEL_SIZE}; x = RFDETR${MODEL_SIZE}(resolution=320); x.export(simplify=True)"
FROM scratch
+22 -1
View File
@@ -9,4 +9,25 @@ Snapshots are accessible in the UI in the Explore pane. This allows for quick su
To only save snapshots for objects that enter a specific zone, [see the zone docs](./zones.md#restricting-snapshots-to-specific-zones)
Snapshots sent via MQTT are configured in the [config file](https://docs.frigate.video/configuration/) under `cameras -> your_camera -> mqtt`
Snapshots sent via MQTT are configured in the [config file](/configuration) under `cameras -> your_camera -> mqtt`
## Frame Selection
Frigate does not save every frame — it picks a single "best" frame for each tracked object and uses it for both the snapshot and clean copy. As the object is tracked across frames, Frigate continuously evaluates whether the current frame is better than the previous best based on detection confidence, object size, and the presence of key attributes like faces or license plates. Frames where the object touches the edge of the frame are deprioritized. The snapshot is written to disk once tracking ends using whichever frame was determined to be the best.
MQTT snapshots are published more frequently — each time a better thumbnail frame is found during tracking, or when the current best image is older than `best_image_timeout` (default: 60s). These use their own annotation settings configured under `cameras -> your_camera -> mqtt`.
## Clean Copy
Frigate can produce up to two snapshot files per event, each used in different places:
| Version | File | Annotations | Used by |
| --- | --- | --- | --- |
| **Regular snapshot** | `<camera>-<id>.jpg` | Respects your `timestamp`, `bounding_box`, `crop`, and `height` settings | API (`/api/events/<id>/snapshot.jpg`), MQTT (`<camera>/<label>/snapshot`), Explore pane in the UI |
| **Clean copy** | `<camera>-<id>-clean.webp` | Always unannotated — no bounding box, no timestamp, no crop, full resolution | API (`/api/events/<id>/snapshot-clean.webp`), [Frigate+](/plus/first_model) submissions, "Download Clean Snapshot" in the UI |
MQTT snapshots are configured separately under `cameras -> your_camera -> mqtt` and are unrelated to the clean copy.
The clean copy is required for submitting events to [Frigate+](/plus/first_model) — if you plan to use Frigate+, keep `clean_copy` enabled regardless of your other snapshot settings.
If you are not using Frigate+ and `timestamp`, `bounding_box`, and `crop` are all disabled, the regular snapshot is already effectively clean, so `clean_copy` provides no benefit and only uses additional disk space. You can safely set `clean_copy: False` in this case.
+8 -19
View File
@@ -3,6 +3,8 @@ id: installation
title: Installation
---
import ShmCalculator from '@site/src/components/ShmCalculator'
Frigate is a Docker container that can be run on any Docker host including as a [Home Assistant Add-on](https://www.home-assistant.io/addons/). Note that the Home Assistant Add-on is **not** the same thing as the integration. The [integration](/integrations/home-assistant) is required to integrate Frigate into Home Assistant, whether you are running Frigate as a standalone Docker container or as a Home Assistant Add-on.
:::tip
@@ -77,20 +79,7 @@ The default shm size of **128MB** is fine for setups with **2 cameras** detectin
The Frigate container also stores logs in shm, which can take up to **40MB**, so make sure to take this into account in your math as well.
You can calculate the **minimum** shm size for each camera with the following formula using the resolution specified for detect:
```console
# Template for one camera without logs, replace <width> and <height>
$ python -c 'print("{:.2f}MB".format((<width> * <height> * 1.5 * 20 + 270480) / 1048576))'
# Example for 1280x720, including logs
$ python -c 'print("{:.2f}MB".format((1280 * 720 * 1.5 * 20 + 270480) / 1048576 + 40))'
66.63MB
# Example for eight cameras detecting at 1280x720, including logs
$ python -c 'print("{:.2f}MB".format(((1280 * 720 * 1.5 * 20 + 270480) / 1048576) * 8 + 40))'
253MB
```
<ShmCalculator/>
The shm size cannot be set per container for Home Assistant add-ons. However, this is probably not required since by default Home Assistant Supervisor allocates `/dev/shm` with half the size of your total memory. If your machine has 8GB of memory, chances are that Frigate will have access to up to 4GB without any additional configuration.
@@ -185,7 +174,7 @@ On Raspberry Pi OS **Trixie**, the Hailo driver is no longer shipped with the ke
This command should return no results.
3. **Run the installation script**:
2. **Run the installation script**:
Download the installation script:
@@ -213,7 +202,7 @@ On Raspberry Pi OS **Trixie**, the Hailo driver is no longer shipped with the ke
- Download and install the required firmware
- Set up udev rules
4. **Reboot your system**:
3. **Reboot your system**:
After the script completes successfully, reboot to load the firmware:
@@ -221,7 +210,7 @@ On Raspberry Pi OS **Trixie**, the Hailo driver is no longer shipped with the ke
sudo reboot
```
5. **Verify the installation**:
4. **Verify the installation**:
After rebooting, verify that the Hailo device is available:
@@ -709,7 +698,7 @@ To allow Frigate to use the Apple Silicon Neural Engine / Processing Unit (NPU)
services:
frigate:
container_name: frigate
image: ghcr.io/blakeblackshear/frigate:stable-arm64
image: ghcr.io/blakeblackshear/frigate:stable-standard-arm64
restart: unless-stopped
shm_size: "512mb" # update for your cameras based on calculation above
volumes:
@@ -727,4 +716,4 @@ services:
- "host.docker.internal:host-gateway" # Required to talk to the NPU detector
environment:
- FRIGATE_RTSP_PASSWORD: "password"
```
```
+15 -7
View File
@@ -16,7 +16,15 @@ See the [MQTT integration
documentation](https://www.home-assistant.io/integrations/mqtt/) for more
details.
In addition, MQTT must be enabled in your Frigate configuration file and Frigate must be connected to the same MQTT server as Home Assistant for many of the entities created by the integration to function.
In addition, MQTT must be enabled in your Frigate configuration file and Frigate must be connected to the same MQTT server as Home Assistant for many of the entities created by the integration to function, e.g.:
```yaml
mqtt:
enabled: True
host: mqtt.server.com # the address of your HA server that's running the MQTT integration
user: your_mqtt_broker_username
password: your_mqtt_broker_password
```
### Integration installation
@@ -95,12 +103,12 @@ services:
If you are using Home Assistant Add-on, the URL should be one of the following depending on which Add-on variant you are using. Note that if you are using the Proxy Add-on, you should NOT point the integration at the proxy URL. Just enter the same URL used to access Frigate directly from your network.
| Add-on Variant | URL |
| -------------------------- | ----------------------------------------- |
| Frigate | `http://ccab4aaf-frigate:5000` |
| Frigate (Full Access) | `http://ccab4aaf-frigate-fa:5000` |
| Frigate Beta | `http://ccab4aaf-frigate-beta:5000` |
| Frigate Beta (Full Access) | `http://ccab4aaf-frigate-fa-beta:5000` |
| Add-on Variant | URL |
| -------------------------- | -------------------------------------- |
| Frigate | `http://ccab4aaf-frigate:5000` |
| Frigate (Full Access) | `http://ccab4aaf-frigate-fa:5000` |
| Frigate Beta | `http://ccab4aaf-frigate-beta:5000` |
| Frigate Beta (Full Access) | `http://ccab4aaf-frigate-fa-beta:5000` |
### Frigate running on a separate machine
+8 -4
View File
@@ -120,7 +120,7 @@ Message published for each changed tracked object. The first message is publishe
### `frigate/tracked_object_update`
Message published for updates to tracked object metadata, for example:
Message published for updates to tracked object metadata. All messages include an `id` field which is the tracked object's event ID, and can be used to look up the event via the API or match it to items in the UI.
#### Generative AI Description Update
@@ -134,12 +134,14 @@ Message published for updates to tracked object metadata, for example:
#### Face Recognition Update
Published after each recognition attempt, regardless of whether the score meets `recognition_threshold`. See the [Face Recognition](/configuration/face_recognition) documentation for details on how scoring works.
```json
{
"type": "face",
"id": "1607123955.475377-mxklsc",
"name": "John",
"score": 0.95,
"name": "John", // best matching person, or null if no match
"score": 0.95, // running weighted average across all recognition attempts
"camera": "front_door_cam",
"timestamp": 1607123958.748393
}
@@ -147,11 +149,13 @@ Message published for updates to tracked object metadata, for example:
#### License Plate Recognition Update
Published when a license plate is recognized on a car object. See the [License Plate Recognition](/configuration/license_plate_recognition) documentation for details.
```json
{
"type": "lpr",
"id": "1607123955.475377-mxklsc",
"name": "John's Car",
"name": "John's Car", // known name for the plate, or null
"plate": "123ABC",
"score": 0.95,
"camera": "driveway_cam",
+201
View File
@@ -0,0 +1,201 @@
import React, { useState, useEffect } from "react";
import Admonition from "@theme/Admonition";
import styles from "./styles.module.css";
const ShmCalculator = () => {
const [width, setWidth] = useState(1280);
const [height, setHeight] = useState(720);
const [cameraCount, setCameraCount] = useState(1);
const [result, setResult] = useState("26.32MB");
const [singleCameraShm, setSingleCameraShm] = useState("26.32MB");
const [totalShm, setTotalShm] = useState("26.32MB");
const calculate = () => {
if (!width || !height || !cameraCount) {
setResult("Please enter valid values");
setSingleCameraShm("-");
setTotalShm("-");
return;
}
// Single camera base SHM calculation (excluding logs)
// Formula: (width * height * 1.5 * 20 + 270480) / 1048576
const singleCameraBase =
(width * height * 1.5 * 20 + 270480) / 1048576;
setSingleCameraShm(`${singleCameraBase.toFixed(2)}mb`);
// Total SHM calculation (multiple cameras, including logs)
const totalBase = singleCameraBase * cameraCount;
const finalResult = totalBase + 40; // Default includes logs +40mb
setTotalShm(`${(totalBase + 40).toFixed(2)}mb`);
// Format result
if (finalResult < 1) {
setResult(`${(finalResult * 1024).toFixed(2)}kb`);
} else if (finalResult >= 1024) {
setResult(`${(finalResult / 1024).toFixed(2)}gb`);
} else {
setResult(`${finalResult.toFixed(2)}mb`);
}
};
const formatWithUnit = (value) => {
const match = value.match(/^([\d.]+)(mb|kb|gb)$/i);
if (match) {
return (
<>
{match[1]}<span className={styles.unit}>{match[2]}</span>
</>
);
}
return value;
};
const applyPreset = (w, h, count) => {
setWidth(w);
setHeight(h);
setCameraCount(count);
calculate();
};
useEffect(() => {
calculate();
}, [width, height, cameraCount]);
return (
<div className={styles.shmCalculator}>
<div className={styles.card}>
<h3 className={styles.title}>SHM Calculator</h3>
<p className={styles.description}>
Calculate required shared memory (SHM) based on camera resolution and
count
</p>
<Admonition type="note">
The resolution below is the <strong>detect</strong> stream resolution,
not the <strong>record</strong> stream resolution. SHM size is
determined by the detect resolution used for object detection.{" "}
<a href="/frigate/camera_setup#choosing-a-detect-resolution">
Learn more about choosing a detect resolution.
</a>
</Admonition>
{width * height > 1280 * 720 && (
<Admonition type="warning">
Using a detect resolution higher than 720p is not recommended.
Higher resolutions do not improve object detection accuracy and will
consume significantly more resources.
</Admonition>
)}
<div className="row">
<div className="col col--6">
<div className={styles.formGroup}>
<label htmlFor="width" className={styles.label}>
Width:
</label>
<input
id="width"
type="number"
min="1"
placeholder="e.g.: 1280"
className={styles.input}
value={width}
onChange={(e) => setWidth(Number(e.target.value))}
/>
</div>
</div>
<div className="col col--6">
<div className={styles.formGroup}>
<label htmlFor="height" className={styles.label}>
Height:
</label>
<input
id="height"
type="number"
min="1"
placeholder="e.g.: 720"
className={styles.input}
value={height}
onChange={(e) => setHeight(Number(e.target.value))}
/>
</div>
</div>
</div>
<div className={styles.formGroup}>
<label htmlFor="cameraCount" className={styles.label}>
Camera Count:
</label>
<input
id="cameraCount"
type="number"
min="1"
placeholder="e.g.: 8"
className={styles.input}
value={cameraCount}
onChange={(e) => setCameraCount(Number(e.target.value))}
/>
</div>
<div className={styles.resultSection}>
<h4>Calculation Result</h4>
<div className={styles.resultValue}>
<span className={styles.resultNumber}>{formatWithUnit(result)}</span>
</div>
<div className={styles.formulaDisplay}>
<p>
<strong>Single Camera:</strong> {formatWithUnit(singleCameraShm)}
</p>
<p>
<strong>Formula:</strong> (width × height × 1.5 × 20 + 270480) ÷
1048576
</p>
{cameraCount > 1 && (
<p>
<strong>Total ({cameraCount} cameras):</strong> {formatWithUnit(totalShm)}
</p>
)}
<p>
<strong>With Logs:</strong> + 40<span className={styles.unit}>mb</span>
</p>
</div>
</div>
<div className={styles.presets}>
<h4>Common Presets</h4>
<div className={styles.presetButtons}>
<button
className="button button--outline button--primary button--sm"
onClick={() => applyPreset(640, 360, 1)}
>
640x360 × 1
</button>
<button
className="button button--outline button--primary button--sm"
onClick={() => applyPreset(1280, 720, 1)}
>
1280x720 × 1
</button>
<button
className="button button--outline button--primary button--sm"
onClick={() => applyPreset(1280, 720, 4)}
>
1280x720 × 4
</button>
<button
className="button button--outline button--primary button--sm"
onClick={() => applyPreset(1280, 720, 8)}
>
1280x720 × 8
</button>
</div>
</div>
</div>
</div>
);
};
export default ShmCalculator;
@@ -0,0 +1,131 @@
.shmCalculator {
margin: 2rem 0;
max-width: 600px;
}
.card {
background: var(--ifm-background-surface-color);
border: 1px solid var(--ifm-border-color);
border-radius: 12px;
padding: 2rem;
box-shadow: var(--ifm-global-shadow-lw);
}
[data-theme='light'] .card {
background: var(--ifm-color-emphasis-100);
border: 1px solid var(--ifm-color-emphasis-300);
}
.title {
margin: 0 0 0.5rem 0;
font-size: 1.5rem;
color: var(--ifm-font-color-base);
font-weight: var(--ifm-font-weight-semibold);
}
.description {
margin: 0 0 1.5rem 0;
color: var(--ifm-font-color-secondary);
font-size: 0.9rem;
}
.formGroup {
margin-bottom: 1rem;
}
.label {
display: block;
margin-bottom: 0.25rem;
color: var(--ifm-font-color-base);
font-weight: var(--ifm-font-weight-semibold);
font-size: 0.9rem;
}
.input {
width: 100%;
padding: 0.5rem 0.75rem;
border: 1px solid var(--ifm-border-color);
border-radius: 6px;
background: var(--ifm-background-color);
color: var(--ifm-font-color-base);
font-size: 0.95rem;
transition: border-color 0.2s, box-shadow 0.2s;
}
[data-theme='light'] .input {
background: #fff;
border: 1px solid #d0d7de;
}
.input:focus {
outline: none;
border-color: var(--ifm-color-primary);
box-shadow: 0 0 0 3px var(--ifm-color-primary-lightest);
}
.resultSection {
margin-top: 1rem;
padding: 1.5rem;
background: var(--ifm-background-color);
border-radius: 8px;
border: 1px solid var(--ifm-border-color);
}
[data-theme='light'] .resultSection {
background: #f6f8fa;
border: 1px solid #d0d7de;
}
.resultSection h4 {
margin: 0 0 1rem 0;
color: var(--ifm-font-color-base);
font-weight: var(--ifm-font-weight-semibold);
}
.resultValue {
text-align: center;
padding: 1rem;
background: var(--ifm-color-primary);
border-radius: 6px;
margin-bottom: 1rem;
}
.resultNumber {
font-size: 2rem;
font-weight: var(--ifm-font-weight-bold);
color: #fff;
}
.formulaDisplay {
font-size: 0.85rem;
color: var(--ifm-font-color-secondary);
line-height: 1.6;
}
.formulaDisplay p {
margin: 0.25rem 0;
}
.formulaDisplay strong {
color: var(--ifm-font-color-base);
}
.unit {
text-transform: uppercase;
}
.presets {
margin-top: 1.5rem;
}
.presets h4 {
margin: 0 0 0.75rem 0;
color: var(--ifm-font-color-base);
font-weight: var(--ifm-font-weight-semibold);
}
.presetButtons {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}