mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-21 19:29:00 +03:00
Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f316244495 | ||
|
|
d1f3a807d3 | ||
|
|
ab3cef813c | ||
|
|
c338533c83 | ||
|
|
8c67704ffb | ||
|
|
d311974949 | ||
|
|
0dd1e94d60 | ||
|
|
720e949fef | ||
|
|
c687aa5119 | ||
|
|
e064024a31 | ||
|
|
96c70eee4c | ||
|
|
0310a9654d | ||
|
|
7df3622243 | ||
|
|
dd8282ff3c | ||
|
|
984d654c40 |
@@ -1,7 +1,7 @@
|
||||
default_target: local
|
||||
|
||||
COMMIT_HASH := $(shell git log -1 --pretty=format:"%h"|tail -1)
|
||||
VERSION = 0.17.0
|
||||
VERSION = 0.17.1
|
||||
IMAGE_REPO ?= ghcr.io/blakeblackshear/frigate
|
||||
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BOARDS= #Initialized empty
|
||||
|
||||
@@ -86,7 +86,7 @@ Frigate looks for a JWT token secret in the following order:
|
||||
|
||||
1. An environment variable named `FRIGATE_JWT_SECRET`
|
||||
2. A file named `FRIGATE_JWT_SECRET` in the directory specified by the `CREDENTIALS_DIRECTORY` environment variable (defaults to the Docker Secrets directory: `/run/secrets/`)
|
||||
3. A `jwt_secret` option from the Home Assistant Add-on options
|
||||
3. A `jwt_secret` option from the Home Assistant App options
|
||||
4. A `.jwt_secret` file in the config directory
|
||||
|
||||
If no secret is found on startup, Frigate generates one and stores it in a `.jwt_secret` file in the config directory.
|
||||
|
||||
@@ -7,11 +7,11 @@ Object classification allows you to train a custom MobileNetV2 classification mo
|
||||
|
||||
## Minimum System Requirements
|
||||
|
||||
Object classification models are lightweight and run very fast on CPU. Inference should be usable on virtually any machine that can run Frigate.
|
||||
Object classification models are lightweight and run very fast on CPU.
|
||||
|
||||
Training the model does briefly use a high amount of system resources for about 1–3 minutes per training run. On lower-power devices, training may take longer.
|
||||
|
||||
A CPU with AVX instructions is required for training and inference.
|
||||
A CPU with AVX + AVX2 instructions is required for training and inference.
|
||||
|
||||
## Classes
|
||||
|
||||
@@ -27,7 +27,6 @@ For object classification:
|
||||
### Classification Type
|
||||
|
||||
- **Sub label**:
|
||||
|
||||
- Applied to the object’s `sub_label` field.
|
||||
- Ideal for a single, more specific identity or type.
|
||||
- Example: `cat` → `Leo`, `Charlie`, `None`.
|
||||
|
||||
@@ -7,11 +7,11 @@ State classification allows you to train a custom MobileNetV2 classification mod
|
||||
|
||||
## Minimum System Requirements
|
||||
|
||||
State classification models are lightweight and run very fast on CPU. Inference should be usable on virtually any machine that can run Frigate.
|
||||
State classification models are lightweight and run very fast on CPU.
|
||||
|
||||
Training the model does briefly use a high amount of system resources for about 1–3 minutes per training run. On lower-power devices, training may take longer.
|
||||
|
||||
A CPU with AVX instructions is required for training and inference.
|
||||
A CPU with AVX + AVX2 instructions is required for training and inference.
|
||||
|
||||
## Classes
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ All of these features run locally on your system.
|
||||
|
||||
## Minimum System Requirements
|
||||
|
||||
A CPU with AVX + AVX2 instructions is required to run Face Recognition.
|
||||
|
||||
The `small` model is optimized for efficiency and runs on the CPU, most CPUs should run the model efficiently.
|
||||
|
||||
The `large` model is optimized for accuracy, an integrated or discrete GPU / NPU is required. See the [Hardware Accelerated Enrichments](/configuration/hardware_acceleration_enrichments.md) documentation.
|
||||
@@ -143,17 +145,14 @@ Start with the [Usage](#usage) section and re-read the [Model Requirements](#mod
|
||||
1. Ensure `person` is being _detected_. A `person` will automatically be scanned by Frigate for a face. Any detected faces will appear in the Recent Recognitions tab in the Frigate UI's Face Library.
|
||||
|
||||
If you are using a Frigate+ or `face` detecting model:
|
||||
|
||||
- Watch the debug view (Settings --> Debug) to ensure that `face` is being detected along with `person`.
|
||||
- You may need to adjust the `min_score` for the `face` object if faces are not being detected.
|
||||
|
||||
If you are **not** using a Frigate+ or `face` detecting model:
|
||||
|
||||
- Check your `detect` stream resolution and ensure it is sufficiently high enough to capture face details on `person` objects.
|
||||
- You may need to lower your `detection_threshold` if faces are not being detected.
|
||||
|
||||
2. Any detected faces will then be _recognized_.
|
||||
|
||||
- Make sure you have trained at least one face per the recommendations above.
|
||||
- Adjust `recognition_threshold` settings per the suggestions [above](#advanced-configuration).
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import CommunityBadge from '@site/src/components/CommunityBadge';
|
||||
It is highly recommended to use an integrated or discrete GPU for hardware acceleration video decoding in Frigate.
|
||||
|
||||
Some types of hardware acceleration are detected and used automatically, but you may need to update your configuration to enable hardware accelerated decoding in ffmpeg. To verify that hardware acceleration is working:
|
||||
|
||||
- Check the logs: A message will either say that hardware acceleration was automatically detected, or there will be a warning that no hardware acceleration was automatically detected
|
||||
- If hardware acceleration is specified in the config, verification can be done by ensuring the logs are free from errors. There is no CPU fallback for hardware acceleration.
|
||||
|
||||
@@ -67,7 +68,7 @@ Frigate can utilize most Intel integrated GPUs and Arc GPUs to accelerate video
|
||||
|
||||
:::note
|
||||
|
||||
The default driver is `iHD`. You may need to change the driver to `i965` by adding the following environment variable `LIBVA_DRIVER_NAME=i965` to your docker-compose file or [in the `config.yml` for HA Add-on users](advanced.md#environment_vars).
|
||||
The default driver is `iHD`. You may need to change the driver to `i965` by adding the following environment variable `LIBVA_DRIVER_NAME=i965` to your docker-compose file or [in the `config.yml` for HA App users](advanced.md#environment_vars).
|
||||
|
||||
See [The Intel Docs](https://www.intel.com/content/www/us/en/support/articles/000005505/processors.html) to figure out what generation your CPU is.
|
||||
|
||||
@@ -188,7 +189,7 @@ Frigate can utilize modern AMD integrated GPUs and AMD GPUs to accelerate video
|
||||
|
||||
### Configuring Radeon Driver
|
||||
|
||||
You need to change the driver to `radeonsi` by adding the following environment variable `LIBVA_DRIVER_NAME=radeonsi` to your docker-compose file or [in the `config.yml` for HA Add-on users](advanced.md#environment_vars).
|
||||
You need to change the driver to `radeonsi` by adding the following environment variable `LIBVA_DRIVER_NAME=radeonsi` to your docker-compose file or [in the `config.yml` for HA App users](advanced.md#environment_vars).
|
||||
|
||||
### Via VAAPI
|
||||
|
||||
@@ -292,7 +293,7 @@ These instructions were originally based on the [Jellyfin documentation](https:/
|
||||
## Raspberry Pi 3/4
|
||||
|
||||
Ensure you increase the allocated RAM for your GPU to at least 128 (`raspi-config` > Performance Options > GPU Memory).
|
||||
If you are using the HA Add-on, you may need to use the full access variant and turn off _Protection mode_ for hardware acceleration.
|
||||
If you are using the HA App, you may need to use the full access variant and turn off _Protection mode_ for hardware acceleration.
|
||||
|
||||
```yaml
|
||||
# if you want to decode a h264 stream
|
||||
|
||||
@@ -3,7 +3,7 @@ id: index
|
||||
title: Frigate Configuration
|
||||
---
|
||||
|
||||
For Home Assistant Add-on installations, the config file should be at `/addon_configs/<addon_directory>/config.yml`, where `<addon_directory>` is specific to the variant of the Frigate Add-on you are running. See the list of directories [here](#accessing-add-on-config-dir).
|
||||
For Home Assistant App installations, the config file should be at `/addon_configs/<addon_directory>/config.yml`, where `<addon_directory>` is specific to the variant of the Frigate App you are running. See the list of directories [here](#accessing-app-config-dir).
|
||||
|
||||
For all other installation types, the config file should be mapped to `/config/config.yml` inside the container.
|
||||
|
||||
@@ -25,11 +25,11 @@ cameras:
|
||||
- detect
|
||||
```
|
||||
|
||||
## Accessing the Home Assistant Add-on configuration directory {#accessing-add-on-config-dir}
|
||||
## Accessing the Home Assistant App configuration directory {#accessing-app-config-dir}
|
||||
|
||||
When running Frigate through the HA Add-on, the Frigate `/config` directory is mapped to `/addon_configs/<addon_directory>` in the host, where `<addon_directory>` is specific to the variant of the Frigate Add-on you are running.
|
||||
When running Frigate through the HA App, the Frigate `/config` directory is mapped to `/addon_configs/<addon_directory>` in the host, where `<addon_directory>` is specific to the variant of the Frigate App you are running.
|
||||
|
||||
| Add-on Variant | Configuration directory |
|
||||
| App Variant | Configuration directory |
|
||||
| -------------------------- | ----------------------------------------- |
|
||||
| Frigate | `/addon_configs/ccab4aaf_frigate` |
|
||||
| Frigate (Full Access) | `/addon_configs/ccab4aaf_frigate-fa` |
|
||||
@@ -38,11 +38,11 @@ When running Frigate through the HA Add-on, the Frigate `/config` directory is m
|
||||
|
||||
**Whenever you see `/config` in the documentation, it refers to this directory.**
|
||||
|
||||
If for example you are running the standard Add-on variant and use the [VS Code Add-on](https://github.com/hassio-addons/addon-vscode) to browse your files, you can click _File_ > _Open folder..._ and navigate to `/addon_configs/ccab4aaf_frigate` to access the Frigate `/config` directory and edit the `config.yaml` file. You can also use the built-in file editor in the Frigate UI to edit the configuration file.
|
||||
If for example you are running the standard App variant and use the [VS Code App](https://github.com/hassio-addons/addon-vscode) to browse your files, you can click _File_ > _Open folder..._ and navigate to `/addon_configs/ccab4aaf_frigate` to access the Frigate `/config` directory and edit the `config.yaml` file. You can also use the built-in file editor in the Frigate UI to edit the configuration file.
|
||||
|
||||
## VS Code Configuration Schema
|
||||
|
||||
VS Code supports JSON schemas for automatically validating configuration files. You can enable this feature by adding `# yaml-language-server: $schema=http://frigate_host:5000/api/config/schema.json` to the beginning of the configuration file. Replace `frigate_host` with the IP address or hostname of your Frigate server. If you're using both VS Code and Frigate as an Add-on, you should use `ccab4aaf-frigate` instead. Make sure to expose the internal unauthenticated port `5000` when accessing the config from VS Code on another machine.
|
||||
VS Code supports JSON schemas for automatically validating configuration files. You can enable this feature by adding `# yaml-language-server: $schema=http://frigate_host:5000/api/config/schema.json` to the beginning of the configuration file. Replace `frigate_host` with the IP address or hostname of your Frigate server. If you're using both VS Code and Frigate as an App, you should use `ccab4aaf-frigate` instead. Make sure to expose the internal unauthenticated port `5000` when accessing the config from VS Code on another machine.
|
||||
|
||||
## Environment Variable Substitution
|
||||
|
||||
@@ -82,10 +82,10 @@ genai:
|
||||
|
||||
Here are some common starter configuration examples. Refer to the [reference config](./reference.md) for detailed information about all the config values.
|
||||
|
||||
### Raspberry Pi Home Assistant Add-on with USB Coral
|
||||
### Raspberry Pi Home Assistant App with USB Coral
|
||||
|
||||
- Single camera with 720p, 5fps stream for detect
|
||||
- MQTT connected to the Home Assistant Mosquitto Add-on
|
||||
- MQTT connected to the Home Assistant Mosquitto App
|
||||
- Hardware acceleration for decoding video
|
||||
- USB Coral detector
|
||||
- Save all video with any detectable motion for 7 days regardless of whether any objects were detected or not
|
||||
|
||||
@@ -30,7 +30,7 @@ In the default mode, Frigate's LPR needs to first detect a `car` or `motorcycle`
|
||||
|
||||
## Minimum System Requirements
|
||||
|
||||
License plate recognition works by running AI models locally on your system. The YOLOv9 plate detector model and the OCR models ([PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)) are relatively lightweight and can run on your CPU or GPU, depending on your configuration. At least 4GB of RAM is required.
|
||||
License plate recognition works by running AI models locally on your system. The YOLOv9 plate detector model and the OCR models ([PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)) are relatively lightweight and can run on your CPU or GPU, depending on your configuration. At least 4GB of RAM and a CPU with AVX + AVX2 instructions is required.
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -375,7 +375,6 @@ Use `match_distance` to allow small character mismatches. Alternatively, define
|
||||
Start with ["Why isn't my license plate being detected and recognized?"](#why-isnt-my-license-plate-being-detected-and-recognized). If you are still having issues, work through these steps.
|
||||
|
||||
1. Start with a simplified LPR config.
|
||||
|
||||
- Remove or comment out everything in your LPR config, including `min_area`, `min_plate_length`, `format`, `known_plates`, or `enhancement` values so that the only values left are `enabled` and `debug_save_plates`. This will run LPR with Frigate's default values.
|
||||
|
||||
```yaml
|
||||
@@ -386,7 +385,6 @@ Start with ["Why isn't my license plate being detected and recognized?"](#why-is
|
||||
```
|
||||
|
||||
2. Enable debug logs to see exactly what Frigate is doing.
|
||||
|
||||
- Enable debug logs for LPR by adding `frigate.data_processing.common.license_plate: debug` to your `logger` configuration. These logs are _very_ verbose, so only keep this enabled when necessary. Restart Frigate after this change.
|
||||
|
||||
```yaml
|
||||
@@ -399,18 +397,15 @@ Start with ["Why isn't my license plate being detected and recognized?"](#why-is
|
||||
3. Ensure your plates are being _detected_.
|
||||
|
||||
If you are using a Frigate+ or `license_plate` detecting model:
|
||||
|
||||
- Watch the debug view (Settings --> Debug) to ensure that `license_plate` is being detected.
|
||||
- View MQTT messages for `frigate/events` to verify detected plates.
|
||||
- You may need to adjust your `min_score` and/or `threshold` for the `license_plate` object if your plates are not being detected.
|
||||
|
||||
If you are **not** using a Frigate+ or `license_plate` detecting model:
|
||||
|
||||
- Watch the debug logs for messages from the YOLOv9 plate detector.
|
||||
- You may need to adjust your `detection_threshold` if your plates are not being detected.
|
||||
|
||||
4. Ensure the characters on detected plates are being _recognized_.
|
||||
|
||||
- Enable `debug_save_plates` to save images of detected text on plates to the clips directory (`/media/frigate/clips/lpr`). Ensure these images are readable and the text is clear.
|
||||
- Watch the debug view to see plates recognized in real-time. For non-dedicated LPR cameras, the `car` or `motorcycle` label will change to the recognized plate when LPR is enabled and working.
|
||||
- Adjust `recognition_threshold` settings per the suggestions [above](#advanced-configuration).
|
||||
|
||||
@@ -15,7 +15,7 @@ The jsmpeg live view will use more browser and client GPU resources. Using go2rt
|
||||
| ------ | ------------------------------------- | ---------- | ---------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| jsmpeg | same as `detect -> fps`, capped at 10 | 720p | no | no | Resolution is configurable, but go2rtc is recommended if you want higher resolutions and better frame rates. jsmpeg is Frigate's default without go2rtc configured. |
|
||||
| mse | native | native | yes (depends on audio codec) | yes | iPhone requires iOS 17.1+, Firefox is h.264 only. This is Frigate's default when go2rtc is configured. |
|
||||
| webrtc | native | native | yes (depends on audio codec) | yes | Requires extra configuration. Frigate attempts to use WebRTC when MSE fails or when using a camera's two-way talk feature. |
|
||||
| webrtc | native | native | yes (depends on audio codec) | yes | Requires extra configuration. Frigate attempts to use WebRTC when MSE fails or when using a camera's two-way talk feature. |
|
||||
|
||||
### Camera Settings Recommendations
|
||||
|
||||
@@ -114,7 +114,7 @@ cameras:
|
||||
WebRTC works by creating a TCP or UDP connection on port `8555`. However, it requires additional configuration:
|
||||
|
||||
- For external access, over the internet, setup your router to forward port `8555` to port `8555` on the Frigate device, for both TCP and UDP.
|
||||
- For internal/local access, unless you are running through the HA Add-on, you will also need to set the WebRTC candidates list in the go2rtc config. For example, if `192.168.1.10` is the local IP of the device running Frigate:
|
||||
- For internal/local access, unless you are running through the HA App, you will also need to set the WebRTC candidates list in the go2rtc config. For example, if `192.168.1.10` is the local IP of the device running Frigate:
|
||||
|
||||
```yaml title="config.yml"
|
||||
go2rtc:
|
||||
@@ -128,13 +128,13 @@ WebRTC works by creating a TCP or UDP connection on port `8555`. However, it req
|
||||
|
||||
- For access through Tailscale, the Frigate system's Tailscale IP must be added as a WebRTC candidate. Tailscale IPs all start with `100.`, and are reserved within the `100.64.0.0/10` CIDR block.
|
||||
|
||||
- Note that some browsers may not support H.265 (HEVC). You can check your browser's current version for H.265 compatibility [here](https://github.com/AlexxIT/go2rtc?tab=readme-ov-file#codecs-madness).
|
||||
- Note that some browsers may not support H.265 (HEVC). You can check your browser's current version for H.265 compatibility [here](https://github.com/AlexxIT/go2rtc?tab=readme-ov-file#codecs-madness).
|
||||
|
||||
:::tip
|
||||
|
||||
This extra configuration may not be required if Frigate has been installed as a Home Assistant Add-on, as Frigate uses the Supervisor's API to generate a WebRTC candidate.
|
||||
This extra configuration may not be required if Frigate has been installed as a Home Assistant App, as Frigate uses the Supervisor's API to generate a WebRTC candidate.
|
||||
|
||||
However, it is recommended if issues occur to define the candidates manually. You should do this if the Frigate Add-on fails to generate a valid candidate. If an error occurs you will see some warnings like the below in the Add-on logs page during the initialization:
|
||||
However, it is recommended if issues occur to define the candidates manually. You should do this if the Frigate App fails to generate a valid candidate. If an error occurs you will see some warnings like the below in the App logs page during the initialization:
|
||||
|
||||
```log
|
||||
[WARN] Failed to get IP address from supervisor
|
||||
@@ -222,34 +222,28 @@ Note that disabling a camera through the config file (`enabled: False`) removes
|
||||
When your browser runs into problems playing back your camera streams, it will log short error messages to the browser console. They indicate playback, codec, or network issues on the client/browser side, not something server side with Frigate itself. Below are the common messages you may see and simple actions you can take to try to resolve them.
|
||||
|
||||
- **startup**
|
||||
|
||||
- What it means: The player failed to initialize or connect to the live stream (network or startup error).
|
||||
- What to try: Reload the Live view or click _Reset_. Verify `go2rtc` is running and the camera stream is reachable. Try switching to a different stream from the Live UI dropdown (if available) or use a different browser.
|
||||
|
||||
- Possible console messages from the player code:
|
||||
|
||||
- `Error opening MediaSource.`
|
||||
- `Browser reported a network error.`
|
||||
- `Max error count ${errorCount} exceeded.` (the numeric value will vary)
|
||||
|
||||
- **mse-decode**
|
||||
|
||||
- What it means: The browser reported a decoding error while trying to play the stream, which usually is a result of a codec incompatibility or corrupted frames.
|
||||
- What to try: Check the browser console for the supported and negotiated codecs. Ensure your camera/restream is using H.264 video and AAC audio (these are the most compatible). If your camera uses a non-standard audio codec, configure `go2rtc` to transcode the stream to AAC. Try another browser (some browsers have stricter MSE/codec support) and, for iPhone, ensure you're on iOS 17.1 or newer.
|
||||
|
||||
- Possible console messages from the player code:
|
||||
|
||||
- `Safari cannot open MediaSource.`
|
||||
- `Safari reported InvalidStateError.`
|
||||
- `Safari reported decoding errors.`
|
||||
|
||||
- **stalled**
|
||||
|
||||
- What it means: Playback has stalled because the player has fallen too far behind live (extended buffering or no data arriving).
|
||||
- What to try: This is usually indicative of the browser struggling to decode too many high-resolution streams at once. Try selecting a lower-bandwidth stream (substream), reduce the number of live streams open, improve the network connection, or lower the camera resolution. Also check your camera's keyframe (I-frame) interval — shorter intervals make playback start and recover faster. You can also try increasing the timeout value in the UI pane of Frigate's settings.
|
||||
|
||||
- Possible console messages from the player code:
|
||||
|
||||
- `Buffer time (10 seconds) exceeded, browser may not be playing media correctly.`
|
||||
- `Media playback has stalled after <n> seconds due to insufficient buffering or a network interruption.` (the seconds value will vary)
|
||||
|
||||
@@ -270,21 +264,18 @@ When your browser runs into problems playing back your camera streams, it will l
|
||||
If you are using continuous streaming or you are loading more than a few high resolution streams at once on the dashboard, your browser may struggle to begin playback of your streams before the timeout. Frigate always prioritizes showing a live stream as quickly as possible, even if it is a lower quality jsmpeg stream. You can use the "Reset" link/button to try loading your high resolution stream again.
|
||||
|
||||
Errors in stream playback (e.g., connection failures, codec issues, or buffering timeouts) that cause the fallback to low bandwidth mode (jsmpeg) are logged to the browser console for easier debugging. These errors may include:
|
||||
|
||||
- Network issues (e.g., MSE or WebRTC network connection problems).
|
||||
- Unsupported codecs or stream formats (e.g., H.265 in WebRTC, which is not supported in some browsers).
|
||||
- Buffering timeouts or low bandwidth conditions causing fallback to jsmpeg.
|
||||
- Browser compatibility problems (e.g., iOS Safari limitations with MSE).
|
||||
|
||||
To view browser console logs:
|
||||
|
||||
1. Open the Frigate Live View in your browser.
|
||||
2. Open the browser's Developer Tools (F12 or right-click > Inspect > Console tab).
|
||||
3. Reproduce the error (e.g., load a problematic stream or simulate network issues).
|
||||
4. Look for messages prefixed with the camera name.
|
||||
|
||||
These logs help identify if the issue is player-specific (MSE vs. WebRTC) or related to camera configuration (e.g., go2rtc streams, codecs). If you see frequent errors:
|
||||
|
||||
- Verify your camera's H.264/AAC settings (see [Frigate's camera settings recommendations](#camera_settings_recommendations)).
|
||||
- Check go2rtc configuration for transcoding (e.g., audio to AAC/OPUS).
|
||||
- Test with a different stream via the UI dropdown (if `live -> streams` is configured).
|
||||
@@ -324,9 +315,7 @@ When your browser runs into problems playing back your camera streams, it will l
|
||||
To prevent this, make the `detect` stream match the go2rtc live stream's aspect ratio (resolution does not need to match, just the aspect ratio). You can either adjust the camera's output resolution or set the `width` and `height` values in your config's `detect` section to a resolution with an aspect ratio that matches.
|
||||
|
||||
Example: Resolutions from two streams
|
||||
|
||||
- Mismatched (may cause aspect ratio switching on the dashboard):
|
||||
|
||||
- Live/go2rtc stream: 1920x1080 (16:9)
|
||||
- Detect stream: 640x352 (~1.82:1, not 16:9)
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ YOLOv9 models that are compiled for TensorFlow Lite and properly quantized are s
|
||||
|
||||
:::tip
|
||||
|
||||
**Frigate+ Users:** Follow the [instructions](../integrations/plus#use-models) to set a model ID in your config file.
|
||||
**Frigate+ Users:** Follow the [instructions](/integrations/plus#use-models) to set a model ID in your config file.
|
||||
|
||||
:::
|
||||
|
||||
@@ -1571,12 +1571,12 @@ YOLOv9 model can be exported as ONNX using the command below. You can copy and p
|
||||
```sh
|
||||
docker build . --build-arg MODEL_SIZE=t --build-arg IMG_SIZE=320 --output . -f- <<'EOF'
|
||||
FROM python:3.11 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/
|
||||
RUN apt-get update && apt-get install --no-install-recommends -y cmake libgl1 && rm -rf /var/lib/apt/lists/*
|
||||
COPY --from=ghcr.io/astral-sh/uv:0.10.4 /uv /bin/
|
||||
WORKDIR /yolov9
|
||||
ADD https://github.com/WongKinYiu/yolov9.git .
|
||||
RUN uv pip install --system -r requirements.txt
|
||||
RUN uv pip install --system onnx==1.18.0 onnxruntime onnx-simplifier>=0.4.1 onnxscript
|
||||
RUN uv pip install --system onnx==1.18.0 onnxruntime onnx-simplifier==0.4.* onnxscript
|
||||
ARG MODEL_SIZE
|
||||
ARG IMG_SIZE
|
||||
ADD https://github.com/WongKinYiu/yolov9/releases/download/v0.1/yolov9-${MODEL_SIZE}-converted.pt yolov9-${MODEL_SIZE}.pt
|
||||
|
||||
@@ -13,7 +13,7 @@ Semantic Search is accessed via the _Explore_ view in the Frigate UI.
|
||||
|
||||
Semantic Search works by running a large AI model locally on your system. Small or underpowered systems like a Raspberry Pi will not run Semantic Search reliably or at all.
|
||||
|
||||
A minimum of 8GB of RAM is required to use Semantic Search. A GPU is not strictly required but will provide a significant performance increase over CPU-only systems.
|
||||
A minimum of 8GB of RAM is required to use Semantic Search. A CPU with AVX + AVX2 instructions is required to run Semantic Search. A GPU is not strictly required but will provide a significant performance increase over CPU-only systems.
|
||||
|
||||
For best performance, 16GB or more of RAM and a dedicated GPU are recommended.
|
||||
|
||||
|
||||
@@ -17,15 +17,15 @@ From here, follow the guides for:
|
||||
- [Web Interface](#web-interface)
|
||||
- [Documentation](#documentation)
|
||||
|
||||
### Frigate Home Assistant Add-on
|
||||
### Frigate Home Assistant App
|
||||
|
||||
This repository holds the Home Assistant Add-on, for use with Home Assistant OS and compatible installations. It is the piece that allows you to run Frigate from your Home Assistant Supervisor tab.
|
||||
This repository holds the Home Assistant App, for use with Home Assistant OS and compatible installations. It is the piece that allows you to run Frigate from your Home Assistant Supervisor tab.
|
||||
|
||||
Fork [blakeblackshear/frigate-hass-addons](https://github.com/blakeblackshear/frigate-hass-addons) to your own Github profile, then clone the forked repo to your local machine.
|
||||
|
||||
### Frigate Home Assistant Integration
|
||||
|
||||
This repository holds the custom integration that allows your Home Assistant installation to automatically create entities for your Frigate instance, whether you are running Frigate as a standalone Docker container or as a [Home Assistant Add-on](#frigate-home-assistant-add-on).
|
||||
This repository holds the custom integration that allows your Home Assistant installation to automatically create entities for your Frigate instance, whether you are running Frigate as a standalone Docker container or as a [Home Assistant App](#frigate-home-assistant-app).
|
||||
|
||||
Fork [blakeblackshear/frigate-hass-integration](https://github.com/blakeblackshear/frigate-hass-integration) to your own GitHub profile, then clone the forked repo to your local machine.
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ I may earn a small commission for my endorsement, recommendation, testimonial, o
|
||||
|
||||
## Server
|
||||
|
||||
My current favorite is the Beelink EQ13 because of the efficient N100 CPU and dual NICs that allow you to setup a dedicated private network for your cameras where they can be blocked from accessing the internet. There are many used workstation options on eBay that work very well. Anything with an Intel CPU and capable of running Debian should work fine. As a bonus, you may want to look for devices with a M.2 or PCIe express slot that is compatible with the Google Coral, Hailo, or other AI accelerators.
|
||||
My current favorite is the Beelink EQ13 because of the efficient N100 CPU and dual NICs that allow you to setup a dedicated private network for your cameras where they can be blocked from accessing the internet. There are many used workstation options on eBay that work very well. Anything with an Intel CPU (with AVX + AVX2 instructions) and capable of running Debian should work fine. As a bonus, you may want to look for devices with a M.2 or PCIe express slot that is compatible with the Google Coral, Hailo, or other AI accelerators.
|
||||
|
||||
Note that many of these mini PCs come with Windows pre-installed, and you will need to install Linux according to the [getting started guide](../guides/getting_started.md).
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ id: installation
|
||||
title: Installation
|
||||
---
|
||||
|
||||
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.
|
||||
Frigate is a Docker container that can be run on any Docker host including as a [Home Assistant App](https://www.home-assistant.io/addons/). Note that the Home Assistant App 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 App.
|
||||
|
||||
:::tip
|
||||
|
||||
If you already have Frigate installed as a Home Assistant Add-on, check out the [getting started guide](../guides/getting_started#configuring-frigate) to configure Frigate.
|
||||
If you already have Frigate installed as a Home Assistant App, check out the [getting started guide](../guides/getting_started#configuring-frigate) to configure Frigate.
|
||||
|
||||
:::
|
||||
|
||||
@@ -92,7 +92,7 @@ $ python -c 'print("{:.2f}MB".format(((1280 * 720 * 1.5 * 20 + 270480) / 1048576
|
||||
253MB
|
||||
```
|
||||
|
||||
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.
|
||||
The shm size cannot be set per container for Home Assistant Apps. 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.
|
||||
|
||||
## Extra Steps for Specific Hardware
|
||||
|
||||
@@ -510,7 +510,7 @@ The community supported docker image tags for the current stable version are:
|
||||
- `stable-tensorrt-jp6` - Frigate build optimized for Nvidia Jetson devices running Jetpack 6
|
||||
- `stable-rk` - Frigate build for SBCs with Rockchip SoC
|
||||
|
||||
## Home Assistant Add-on
|
||||
## Home Assistant App
|
||||
|
||||
:::warning
|
||||
|
||||
@@ -521,7 +521,7 @@ There are important limitations in HA OS to be aware of:
|
||||
- Separate local storage for media is not yet supported by Home Assistant
|
||||
- AMD GPUs are not supported because HA OS does not include the mesa driver.
|
||||
- Intel NPUs are not supported because HA OS does not include the NPU firmware.
|
||||
- Nvidia GPUs are not supported because addons do not support the Nvidia runtime.
|
||||
- Nvidia GPUs are not supported because HA Apps do not support the Nvidia runtime.
|
||||
|
||||
:::
|
||||
|
||||
@@ -531,27 +531,27 @@ See [the network storage guide](/guides/ha_network_storage.md) for instructions
|
||||
|
||||
:::
|
||||
|
||||
Home Assistant OS users can install via the Add-on repository.
|
||||
Home Assistant OS users can install via the App repository.
|
||||
|
||||
1. In Home Assistant, navigate to _Settings_ > _Add-ons_ > _Add-on Store_ > _Repositories_
|
||||
1. In Home Assistant, navigate to _Settings_ > _Apps_ > _App Store_ > _Repositories_
|
||||
2. Add `https://github.com/blakeblackshear/frigate-hass-addons`
|
||||
3. Install the desired variant of the Frigate Add-on (see below)
|
||||
3. Install the desired variant of the Frigate App (see below)
|
||||
4. Setup your network configuration in the `Configuration` tab
|
||||
5. Start the Add-on
|
||||
5. Start the App
|
||||
6. Use the _Open Web UI_ button to access the Frigate UI, then click in the _cog icon_ > _Configuration editor_ and configure Frigate to your liking
|
||||
|
||||
There are several variants of the Add-on available:
|
||||
There are several variants of the App available:
|
||||
|
||||
| Add-on Variant | Description |
|
||||
| App Variant | Description |
|
||||
| -------------------------- | ---------------------------------------------------------- |
|
||||
| Frigate | Current release with protection mode on |
|
||||
| Frigate (Full Access) | Current release with the option to disable protection mode |
|
||||
| Frigate Beta | Beta release with protection mode on |
|
||||
| Frigate Beta (Full Access) | Beta release with the option to disable protection mode |
|
||||
|
||||
If you are using hardware acceleration for ffmpeg, you **may** need to use the _Full Access_ variant of the Add-on. This is because the Frigate Add-on runs in a container with limited access to the host system. The _Full Access_ variant allows you to disable _Protection mode_ and give Frigate full access to the host system.
|
||||
If you are using hardware acceleration for ffmpeg, you **may** need to use the _Full Access_ variant of the App. This is because the Frigate App runs in a container with limited access to the host system. The _Full Access_ variant allows you to disable _Protection mode_ and give Frigate full access to the host system.
|
||||
|
||||
You can also edit the Frigate configuration file through the [VS Code Add-on](https://github.com/hassio-addons/addon-vscode) or similar. In that case, the configuration file will be at `/addon_configs/<addon_directory>/config.yml`, where `<addon_directory>` is specific to the variant of the Frigate Add-on you are running. See the list of directories [here](../configuration/index.md#accessing-add-on-config-dir).
|
||||
You can also edit the Frigate configuration file through the [VS Code App](https://github.com/hassio-addons/addon-vscode) or similar. In that case, the configuration file will be at `/addon_configs/<addon_directory>/config.yml`, where `<addon_directory>` is specific to the variant of the Frigate App you are running. See the list of directories [here](../configuration/index.md#accessing-app-config-dir).
|
||||
|
||||
## Kubernetes
|
||||
|
||||
|
||||
@@ -34,11 +34,14 @@ For commercial installations it is important to verify the number of supported c
|
||||
|
||||
There are many different hardware options for object detection depending on priorities and available hardware. See [the recommended hardware page](./hardware.md#detectors) for more specifics on what hardware is recommended for object detection.
|
||||
|
||||
### CPU
|
||||
|
||||
Frigate requires a CPU with AVX + AVX2 instructions. Most modern CPUs (post-2011) support AVX and AVX2, but it is generally absent in low-power or budget-oriented processors, particularly older Intel Pentium, Celeron, and Atom-based chips. Specifically, Intel Celeron and Pentium models prior to the 2020 Tiger Lake generation typically lack AVX. Older Intel Xeon models may have AVX, but may lack AVX2.
|
||||
|
||||
### Storage
|
||||
|
||||
Storage is an important consideration when planning a new installation. To get a more precise estimate of your storage requirements, you can use an IP camera storage calculator. Websites like [IPConfigure Storage Calculator](https://calculator.ipconfigure.com/) can help you determine the necessary disk space based on your camera settings.
|
||||
|
||||
|
||||
#### SSDs (Solid State Drives)
|
||||
|
||||
SSDs are an excellent choice for Frigate, offering high speed and responsiveness. The older concern that SSDs would quickly "wear out" from constant video recording is largely no longer valid for modern consumer and enterprise-grade SSDs.
|
||||
@@ -71,4 +74,4 @@ While supported, using network-attached storage (NAS) for recordings can introdu
|
||||
|
||||
- **Basic Minimum: 4GB RAM**: This is generally sufficient for a very basic Frigate setup with a few cameras and a dedicated object detection accelerator, without running any enrichments. Performance might be tight, especially with higher resolution streams or numerous detections.
|
||||
- **Minimum for Enrichments: 8GB RAM**: If you plan to utilize Frigate's enrichment features (e.g., facial recognition, license plate recognition, or other AI models that run alongside standard object detection), 8GB of RAM should be considered the minimum. Enrichments require additional memory to load and process their respective models and data.
|
||||
- **Recommended: 16GB RAM**: For most users, especially those with many cameras (8+) or who plan to heavily leverage enrichments, 16GB of RAM is highly recommended. This provides ample headroom for smooth operation, reduces the likelihood of swapping to disk (which can impact performance), and allows for future expansion.
|
||||
- **Recommended: 16GB RAM**: For most users, especially those with many cameras (8+) or who plan to heavily leverage enrichments, 16GB of RAM is highly recommended. This provides ample headroom for smooth operation, reduces the likelihood of swapping to disk (which can impact performance), and allows for future expansion.
|
||||
|
||||
@@ -7,7 +7,7 @@ title: Updating
|
||||
|
||||
The current stable version of Frigate is **0.17.0**. The release notes and any breaking changes for this version can be found on the [Frigate GitHub releases page](https://github.com/blakeblackshear/frigate/releases/tag/v0.17.0).
|
||||
|
||||
Keeping Frigate up to date ensures you benefit from the latest features, performance improvements, and bug fixes. The update process varies slightly depending on your installation method (Docker, Home Assistant Addon, etc.). Below are instructions for the most common setups.
|
||||
Keeping Frigate up to date ensures you benefit from the latest features, performance improvements, and bug fixes. The update process varies slightly depending on your installation method (Docker, Home Assistant App, etc.). Below are instructions for the most common setups.
|
||||
|
||||
## Before You Begin
|
||||
|
||||
@@ -67,30 +67,30 @@ If you’re running Frigate via Docker (recommended method), follow these steps:
|
||||
- If you’ve customized other settings (e.g., `shm-size`), ensure they’re still appropriate after the update.
|
||||
- Docker will automatically use the updated image when you restart the container, as long as you pulled the correct version.
|
||||
|
||||
## Updating the Home Assistant Addon
|
||||
## Updating the Home Assistant App (formerly Addon)
|
||||
|
||||
For users running Frigate as a Home Assistant Addon:
|
||||
For users running Frigate as a Home Assistant App:
|
||||
|
||||
1. **Check for Updates**:
|
||||
- Navigate to **Settings > Add-ons** in Home Assistant.
|
||||
- Find your installed Frigate addon (e.g., "Frigate NVR" or "Frigate NVR (Full Access)").
|
||||
- Navigate to **Settings > Apps** in Home Assistant.
|
||||
- Find your installed Frigate app (e.g., "Frigate NVR" or "Frigate NVR (Full Access)").
|
||||
- If an update is available, you’ll see an "Update" button.
|
||||
|
||||
2. **Update the Addon**:
|
||||
- Click the "Update" button next to the Frigate addon.
|
||||
2. **Update the App**:
|
||||
- Click the "Update" button next to the Frigate app.
|
||||
- Wait for the process to complete. Home Assistant will handle downloading and installing the new version.
|
||||
|
||||
3. **Restart the Addon**:
|
||||
- After updating, go to the addon’s page and click "Restart" to apply the changes.
|
||||
3. **Restart the App**:
|
||||
- After updating, go to the app’s page and click "Restart" to apply the changes.
|
||||
|
||||
4. **Verify the Update**:
|
||||
- Check the addon logs (under the "Log" tab) to ensure Frigate starts without errors.
|
||||
- Check the app logs (under the "Log" tab) to ensure Frigate starts without errors.
|
||||
- Access the Frigate Web UI to confirm the new version is running.
|
||||
|
||||
### Notes
|
||||
|
||||
- Ensure your `/config/frigate.yml` is compatible with the new version by reviewing the [Release notes](https://github.com/blakeblackshear/frigate/releases).
|
||||
- If using custom hardware (e.g., Coral or GPU), verify that configurations still work, as addon updates don’t modify your hardware settings.
|
||||
- If using custom hardware (e.g., Coral or GPU), verify that configurations still work, as app updates don’t modify your hardware settings.
|
||||
|
||||
## Rolling Back
|
||||
|
||||
@@ -101,7 +101,7 @@ If an update causes issues:
|
||||
3. Revert to the previous image version:
|
||||
- For Docker: Specify an older tag (e.g., `ghcr.io/blakeblackshear/frigate:0.16.4`) in your `docker run` command.
|
||||
- For Docker Compose: Edit your `docker-compose.yml`, specify the older version tag (e.g., `ghcr.io/blakeblackshear/frigate:0.16.4`), and re-run `docker compose up -d`.
|
||||
- For Home Assistant: Reinstall the previous addon version manually via the repository if needed and restart the addon.
|
||||
- For Home Assistant: Restore from the app/addon backup you took before you updated.
|
||||
4. Verify the old version is running again.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -37,18 +37,18 @@ The following diagram adds a lot more detail than the simple view explained befo
|
||||
%%{init: {"themeVariables": {"edgeLabelBackground": "transparent"}}}%%
|
||||
|
||||
flowchart TD
|
||||
RecStore[(Recording\nstore)]
|
||||
SnapStore[(Snapshot\nstore)]
|
||||
RecStore[(Recording<br>store)]
|
||||
SnapStore[(Snapshot<br>store)]
|
||||
|
||||
subgraph Acquisition
|
||||
Cam["Camera"] -->|FFmpeg supported| Stream
|
||||
Cam -->|"Other streaming\nprotocols"| go2rtc
|
||||
Cam -->|"Other streaming<br>protocols"| go2rtc
|
||||
go2rtc("go2rtc") --> Stream
|
||||
Stream[Capture main and\nsub streams] --> |detect stream|Decode(Decode and\ndownscale)
|
||||
Stream[Capture main and<br>sub streams] --> |detect stream|Decode(Decode and<br>downscale)
|
||||
end
|
||||
subgraph Motion
|
||||
Decode --> MotionM(Apply\nmotion masks)
|
||||
MotionM --> MotionD(Motion\ndetection)
|
||||
Decode --> MotionM(Apply<br>motion masks)
|
||||
MotionM --> MotionD(Motion<br>detection)
|
||||
end
|
||||
subgraph Detection
|
||||
MotionD --> |motion regions| ObjectD(Object detection)
|
||||
@@ -60,8 +60,8 @@ flowchart TD
|
||||
MotionD --> |motion event|Birdseye
|
||||
ObjectZ --> |object event|Birdseye
|
||||
|
||||
MotionD --> |"video segments\n(retain motion)"|RecStore
|
||||
MotionD --> |"video segments<br>(retain motion)"|RecStore
|
||||
ObjectZ --> |detection clip|RecStore
|
||||
Stream -->|"video segments\n(retain all)"| RecStore
|
||||
Stream -->|"video segments<br>(retain all)"| RecStore
|
||||
ObjectZ --> |detection snapshot|SnapStore
|
||||
```
|
||||
|
||||
@@ -33,19 +33,16 @@ After adding this to the config, restart Frigate and try to watch the live strea
|
||||
### What if my video doesn't play?
|
||||
|
||||
- Check Logs:
|
||||
|
||||
- Access the go2rtc logs in the Frigate UI under Logs in the sidebar.
|
||||
- If go2rtc is having difficulty connecting to your camera, you should see some error messages in the log.
|
||||
|
||||
- Check go2rtc Web Interface: if you don't see any errors in the logs, try viewing the camera through go2rtc's web interface.
|
||||
|
||||
- Navigate to port 1984 in your browser to access go2rtc's web interface.
|
||||
- If using Frigate through Home Assistant, enable the web interface at port 1984.
|
||||
- If using Docker, forward port 1984 before accessing the web interface.
|
||||
- Click `stream` for the specific camera to see if the camera's stream is being received.
|
||||
|
||||
- Check Video Codec:
|
||||
|
||||
- If the camera stream works in go2rtc but not in your browser, the video codec might be unsupported.
|
||||
- If using H265, switch to H264. Refer to [video codec compatibility](https://github.com/AlexxIT/go2rtc/tree/v1.9.10#codecs-madness) in go2rtc documentation.
|
||||
- If unable to switch from H265 to H264, or if the stream format is different (e.g., MJPEG), re-encode the video using [FFmpeg parameters](https://github.com/AlexxIT/go2rtc/tree/v1.9.10#source-ffmpeg). It supports rotating and resizing video feeds and hardware acceleration. Keep in mind that transcoding video from one format to another is a resource intensive task and you may be better off using the built-in jsmpeg view.
|
||||
@@ -58,7 +55,6 @@ After adding this to the config, restart Frigate and try to watch the live strea
|
||||
```
|
||||
|
||||
- Switch to FFmpeg if needed:
|
||||
|
||||
- Some camera streams may need to use the ffmpeg module in go2rtc. This has the downside of slower startup times, but has compatibility with more stream types.
|
||||
|
||||
```yaml
|
||||
@@ -101,9 +97,9 @@ After adding this to the config, restart Frigate and try to watch the live strea
|
||||
|
||||
:::warning
|
||||
|
||||
To access the go2rtc stream externally when utilizing the Frigate Add-On (for
|
||||
To access the go2rtc stream externally when utilizing the Frigate App (for
|
||||
instance through VLC), you must first enable the RTSP Restream port.
|
||||
You can do this by visiting the Frigate Add-On configuration page within Home
|
||||
You can do this by visiting the Frigate App configuration page within Home
|
||||
Assistant and revealing the hidden options under the "Show disabled ports"
|
||||
section.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ title: Getting started
|
||||
|
||||
If you already have an environment with Linux and Docker installed, you can continue to [Installing Frigate](#installing-frigate) below.
|
||||
|
||||
If you already have Frigate installed through Docker or through a Home Assistant Add-on, you can continue to [Configuring Frigate](#configuring-frigate) below.
|
||||
If you already have Frigate installed through Docker or through a Home Assistant App, you can continue to [Configuring Frigate](#configuring-frigate) below.
|
||||
|
||||
:::
|
||||
|
||||
@@ -81,7 +81,7 @@ Now you have a minimal Debian server that requires very little maintenance.
|
||||
|
||||
## Installing Frigate
|
||||
|
||||
This section shows how to create a minimal directory structure for a Docker installation on Debian. If you have installed Frigate as a Home Assistant Add-on or another way, you can continue to [Configuring Frigate](#configuring-frigate).
|
||||
This section shows how to create a minimal directory structure for a Docker installation on Debian. If you have installed Frigate as a Home Assistant App or another way, you can continue to [Configuring Frigate](#configuring-frigate).
|
||||
|
||||
### Setup directories
|
||||
|
||||
@@ -174,7 +174,46 @@ cameras:
|
||||
|
||||
### Step 4: Configure detectors
|
||||
|
||||
By default, Frigate will use a single CPU detector. If you have a USB Coral, you will need to add a detectors section to your config.
|
||||
By default, Frigate will use a single CPU detector.
|
||||
|
||||
In many cases, the integrated graphics on Intel CPUs provides sufficient performance for typical Frigate setups. If you have an Intel processor, you can follow the configuration below.
|
||||
|
||||
<details>
|
||||
<summary>Use Intel OpenVINO detector</summary>
|
||||
|
||||
You need to refer to **Configure hardware acceleration** above to enable the container to use the GPU.
|
||||
|
||||
```yaml
|
||||
mqtt: ...
|
||||
|
||||
detectors: # <---- add detectors
|
||||
ov:
|
||||
type: openvino # <---- use openvino detector
|
||||
device: GPU
|
||||
|
||||
# We will use the default MobileNet_v2 model from OpenVINO.
|
||||
model:
|
||||
width: 300
|
||||
height: 300
|
||||
input_tensor: nhwc
|
||||
input_pixel_format: bgr
|
||||
path: /openvino-model/ssdlite_mobilenet_v2.xml
|
||||
labelmap_path: /openvino-model/coco_91cl_bkgr.txt
|
||||
|
||||
cameras:
|
||||
name_of_your_camera:
|
||||
ffmpeg: ...
|
||||
detect:
|
||||
enabled: True # <---- turn on detection
|
||||
...
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
If you have a USB Coral, you will need to add a detectors section to your config.
|
||||
|
||||
<details>
|
||||
<summary>Use USB Coral detector</summary>
|
||||
|
||||
`docker-compose.yml` (after modifying, you will need to run `docker compose up -d` to apply changes)
|
||||
|
||||
@@ -204,6 +243,8 @@ cameras:
|
||||
...
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
More details on available detectors can be found [here](../configuration/object_detectors.md).
|
||||
|
||||
Restart Frigate and you should start seeing detections for `person`. If you want to track other objects, they will need to be added according to the [configuration file reference](../configuration/reference.md).
|
||||
|
||||
@@ -3,7 +3,7 @@ id: ha_network_storage
|
||||
title: Home Assistant network storage
|
||||
---
|
||||
|
||||
As of Home Assistant 2023.6, Network Mounted Storage is supported for Add-ons.
|
||||
As of Home Assistant 2023.6, Network Mounted Storage is supported for Apps.
|
||||
|
||||
## Setting Up Remote Storage For Frigate
|
||||
|
||||
@@ -14,7 +14,7 @@ As of Home Assistant 2023.6, Network Mounted Storage is supported for Add-ons.
|
||||
|
||||
### Initial Setup
|
||||
|
||||
1. Stop the Frigate Add-on
|
||||
1. Stop the Frigate App
|
||||
|
||||
### Move current data
|
||||
|
||||
@@ -37,4 +37,4 @@ Keeping the current data is optional, but the data will need to be moved regardl
|
||||
4. Fill out the additional required info for your particular NAS
|
||||
5. Connect
|
||||
6. Move files from `/media/frigate_tmp` to `/media/frigate` if they were kept in previous step
|
||||
7. Start the Frigate Add-on
|
||||
7. Start the Frigate App
|
||||
|
||||
@@ -99,11 +99,11 @@ services:
|
||||
...
|
||||
```
|
||||
|
||||
### Home Assistant Add-on
|
||||
### Home Assistant App
|
||||
|
||||
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.
|
||||
If you are using Home Assistant App, the URL should be one of the following depending on which App variant you are using. Note that if you are using the Proxy App, 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 |
|
||||
| App Variant | URL |
|
||||
| -------------------------- | -------------------------------------- |
|
||||
| Frigate | `http://ccab4aaf-frigate:5000` |
|
||||
| Frigate (Full Access) | `http://ccab4aaf-frigate-fa:5000` |
|
||||
|
||||
@@ -19,11 +19,11 @@ Once logged in, you can generate an API key for Frigate in Settings.
|
||||
|
||||
### Set your API key
|
||||
|
||||
In Frigate, you can use an environment variable or a docker secret named `PLUS_API_KEY` to enable the `Frigate+` buttons on the Explore page. Home Assistant Addon users can set it under Settings > Add-ons > Frigate > Configuration > Options (be sure to toggle the "Show unused optional configuration options" switch).
|
||||
In Frigate, you can use an environment variable or a docker secret named `PLUS_API_KEY` to enable the `Frigate+` buttons on the Explore page. Home Assistant App users can set it under Settings > Apps > Frigate > Configuration > Options (be sure to toggle the "Show unused optional configuration options" switch).
|
||||
|
||||
:::warning
|
||||
|
||||
You cannot use the `environment_vars` section of your Frigate configuration file to set this environment variable. It must be defined as an environment variable in the docker config or Home Assistant Add-on config.
|
||||
You cannot use the `environment_vars` section of your Frigate configuration file to set this environment variable. It must be defined as an environment variable in the docker config or Home Assistant App config.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ The USB coral can draw up to 900mA and this can be too much for some on-device U
|
||||
The USB coral has different IDs when it is uninitialized and initialized.
|
||||
|
||||
- When running Frigate in a VM, Proxmox lxc, etc. you must ensure both device IDs are mapped.
|
||||
- When running through the Home Assistant OS you may need to run the Full Access variant of the Frigate Add-on with the _Protection mode_ switch disabled so that the coral can be accessed.
|
||||
- When running through the Home Assistant OS you may need to run the Full Access variant of the Frigate App with the _Protection mode_ switch disabled so that the coral can be accessed.
|
||||
|
||||
### Synology 716+II running DSM 7.2.1-69057 Update 5
|
||||
|
||||
|
||||
+65
-1
@@ -986,7 +986,16 @@ async def require_camera_access(
|
||||
|
||||
current_user = await get_current_user(request)
|
||||
if isinstance(current_user, JSONResponse):
|
||||
return current_user
|
||||
detail = "Authentication required"
|
||||
try:
|
||||
error_payload = json.loads(current_user.body)
|
||||
detail = (
|
||||
error_payload.get("message") or error_payload.get("detail") or detail
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
raise HTTPException(status_code=current_user.status_code, detail=detail)
|
||||
|
||||
role = current_user["role"]
|
||||
all_camera_names = set(request.app.frigate_config.cameras.keys())
|
||||
@@ -1004,6 +1013,61 @@ async def require_camera_access(
|
||||
)
|
||||
|
||||
|
||||
def _get_stream_owner_cameras(request: Request, stream_name: str) -> set[str]:
|
||||
owner_cameras: set[str] = set()
|
||||
|
||||
for camera_name, camera in request.app.frigate_config.cameras.items():
|
||||
if stream_name == camera_name:
|
||||
owner_cameras.add(camera_name)
|
||||
continue
|
||||
|
||||
if stream_name in camera.live.streams.values():
|
||||
owner_cameras.add(camera_name)
|
||||
|
||||
return owner_cameras
|
||||
|
||||
|
||||
async def require_go2rtc_stream_access(
|
||||
stream_name: Optional[str] = None,
|
||||
request: Request = None,
|
||||
):
|
||||
"""Dependency to enforce go2rtc stream access based on owning camera access."""
|
||||
if stream_name is None:
|
||||
return
|
||||
|
||||
current_user = await get_current_user(request)
|
||||
if isinstance(current_user, JSONResponse):
|
||||
detail = "Authentication required"
|
||||
try:
|
||||
error_payload = json.loads(current_user.body)
|
||||
detail = (
|
||||
error_payload.get("message") or error_payload.get("detail") or detail
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
raise HTTPException(status_code=current_user.status_code, detail=detail)
|
||||
|
||||
role = current_user["role"]
|
||||
all_camera_names = set(request.app.frigate_config.cameras.keys())
|
||||
roles_dict = request.app.frigate_config.auth.roles
|
||||
allowed_cameras = User.get_allowed_cameras(role, roles_dict, all_camera_names)
|
||||
|
||||
# Admin or full access bypasses
|
||||
if role == "admin" or not roles_dict.get(role):
|
||||
return
|
||||
|
||||
owner_cameras = _get_stream_owner_cameras(request, stream_name)
|
||||
|
||||
if owner_cameras & set(allowed_cameras):
|
||||
return
|
||||
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail=f"Access denied to camera '{stream_name}'. Allowed: {allowed_cameras}",
|
||||
)
|
||||
|
||||
|
||||
async def get_allowed_cameras_for_filter(request: Request):
|
||||
"""Dependency to get allowed_cameras for filtering lists."""
|
||||
current_user = await get_current_user(request)
|
||||
|
||||
+18
-5
@@ -17,7 +17,7 @@ from zeep.transports import AsyncTransport
|
||||
|
||||
from frigate.api.auth import (
|
||||
allow_any_authenticated,
|
||||
require_camera_access,
|
||||
require_go2rtc_stream_access,
|
||||
require_role,
|
||||
)
|
||||
from frigate.api.defs.tags import Tags
|
||||
@@ -71,14 +71,27 @@ def go2rtc_streams():
|
||||
|
||||
|
||||
@router.get(
|
||||
"/go2rtc/streams/{camera_name}", dependencies=[Depends(require_camera_access)]
|
||||
"/go2rtc/streams/{stream_name}",
|
||||
dependencies=[Depends(require_go2rtc_stream_access)],
|
||||
)
|
||||
def go2rtc_camera_stream(request: Request, camera_name: str):
|
||||
def go2rtc_camera_stream(request: Request, stream_name: str):
|
||||
r = requests.get(
|
||||
f"http://127.0.0.1:1984/api/streams?src={camera_name}&video=all&audio=allµphone"
|
||||
"http://127.0.0.1:1984/api/streams",
|
||||
params={
|
||||
"src": stream_name,
|
||||
"video": "all",
|
||||
"audio": "all",
|
||||
"microphone": "",
|
||||
},
|
||||
)
|
||||
if not r.ok:
|
||||
camera_config = request.app.frigate_config.cameras.get(camera_name)
|
||||
camera_config = request.app.frigate_config.cameras.get(stream_name)
|
||||
|
||||
if camera_config is None:
|
||||
for camera_name, camera in request.app.frigate_config.cameras.items():
|
||||
if stream_name in camera.live.streams.values():
|
||||
camera_config = request.app.frigate_config.cameras.get(camera_name)
|
||||
break
|
||||
|
||||
if camera_config and camera_config.enabled:
|
||||
logger.error("Failed to fetch streams from go2rtc")
|
||||
|
||||
@@ -50,10 +50,12 @@ from frigate.models import Event, Previews, Recordings, Regions, ReviewSegment
|
||||
from frigate.track.object_processing import TrackedObjectProcessor
|
||||
from frigate.util.file import get_event_thumbnail_bytes
|
||||
from frigate.util.image import get_image_from_recording
|
||||
from frigate.util.media import get_keyframe_before
|
||||
from frigate.util.time import get_dst_transitions
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
router = APIRouter(tags=[Tags.media])
|
||||
|
||||
|
||||
@@ -900,6 +902,33 @@ async def vod_ts(
|
||||
if recording.end_time > end_ts:
|
||||
duration -= int((recording.end_time - end_ts) * 1000)
|
||||
|
||||
# nginx-vod-module pushes clipFrom forward to the next keyframe,
|
||||
# which can leave too few frames and produce an empty/unplayable
|
||||
# segment. Snap clipFrom back to the preceding keyframe so the
|
||||
# segment always starts with a decodable frame.
|
||||
if "clipFrom" in clip:
|
||||
keyframe_ms = get_keyframe_before(recording.path, clip["clipFrom"])
|
||||
if keyframe_ms is not None:
|
||||
gained = clip["clipFrom"] - keyframe_ms
|
||||
clip["clipFrom"] = keyframe_ms
|
||||
duration += gained
|
||||
logger.debug(
|
||||
"VOD: snapped clipFrom to keyframe at %sms for %s, duration now %sms",
|
||||
keyframe_ms,
|
||||
recording.path,
|
||||
duration,
|
||||
)
|
||||
else:
|
||||
# could not read keyframes, remove clipFrom to use full recording
|
||||
logger.debug(
|
||||
"VOD: no keyframe info for %s, removing clipFrom to use full recording",
|
||||
recording.path,
|
||||
)
|
||||
del clip["clipFrom"]
|
||||
duration = int(recording.duration * 1000)
|
||||
if recording.end_time > end_ts:
|
||||
duration -= int((recording.end_time - end_ts) * 1000)
|
||||
|
||||
if duration < min_duration_ms:
|
||||
# skip if the clip has no valid duration (too short to contain frames)
|
||||
logger.debug(
|
||||
|
||||
@@ -103,16 +103,19 @@ class ObjectDescriptionProcessor(PostProcessorApi):
|
||||
logger.debug(f"{camera} sending early request to GenAI")
|
||||
|
||||
self.early_request_sent[data["id"]] = True
|
||||
# Copy thumbnails to avoid holding references after cleanup
|
||||
thumbnails_copy = [
|
||||
data["thumbnail"][:] if data.get("thumbnail") else None
|
||||
for data in self.tracked_events[data["id"]]
|
||||
if data.get("thumbnail")
|
||||
]
|
||||
threading.Thread(
|
||||
target=self._genai_embed_description,
|
||||
name=f"_genai_embed_description_{event.id}",
|
||||
daemon=True,
|
||||
args=(
|
||||
event,
|
||||
[
|
||||
data["thumbnail"]
|
||||
for data in self.tracked_events[data["id"]]
|
||||
],
|
||||
thumbnails_copy,
|
||||
),
|
||||
).start()
|
||||
|
||||
@@ -172,8 +175,13 @@ class ObjectDescriptionProcessor(PostProcessorApi):
|
||||
embed_image = (
|
||||
[snapshot_image]
|
||||
if event.has_snapshot and source == "snapshot"
|
||||
# Copy thumbnails to avoid holding references
|
||||
else (
|
||||
[data["thumbnail"] for data in self.tracked_events[event_id]]
|
||||
[
|
||||
data["thumbnail"][:] if data.get("thumbnail") else None
|
||||
for data in self.tracked_events[event_id]
|
||||
if data.get("thumbnail")
|
||||
]
|
||||
if len(self.tracked_events.get(event_id, [])) > 0
|
||||
else [thumbnail]
|
||||
)
|
||||
@@ -276,8 +284,13 @@ class ObjectDescriptionProcessor(PostProcessorApi):
|
||||
embed_image = (
|
||||
[snapshot_image]
|
||||
if event.has_snapshot and camera_config.objects.genai.use_snapshot
|
||||
# Copy thumbnails to avoid holding references after cleanup
|
||||
else (
|
||||
[data["thumbnail"] for data in self.tracked_events[event.id]]
|
||||
[
|
||||
data["thumbnail"][:] if data.get("thumbnail") else None
|
||||
for data in self.tracked_events[event.id]
|
||||
if data.get("thumbnail")
|
||||
]
|
||||
if num_thumbnails > 0
|
||||
else [thumbnail]
|
||||
)
|
||||
|
||||
@@ -679,4 +679,7 @@ class EmbeddingMaintainer(threading.Thread):
|
||||
if not self.config.semantic_search.enabled:
|
||||
return
|
||||
|
||||
self.embeddings.embed_thumbnail(event_id, thumbnail)
|
||||
try:
|
||||
self.embeddings.embed_thumbnail(event_id, thumbnail)
|
||||
except ValueError:
|
||||
logger.warning(f"Failed to embed thumbnail for event {event_id}")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
from fastapi import HTTPException, Request
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from frigate.api.auth import (
|
||||
get_allowed_cameras_for_filter,
|
||||
@@ -9,6 +10,33 @@ from frigate.api.auth import (
|
||||
from frigate.models import Event, Recordings, ReviewSegment
|
||||
from frigate.test.http_api.base_http_test import AuthTestClient, BaseTestHttp
|
||||
|
||||
# Minimal multi-camera config used by go2rtc stream access tests.
|
||||
# front_door has a stream alias "front_door_main"; back_door uses its own name.
|
||||
# The "limited_user" role is restricted to front_door only.
|
||||
_MULTI_CAMERA_CONFIG = {
|
||||
"mqtt": {"host": "mqtt"},
|
||||
"auth": {
|
||||
"roles": {
|
||||
"limited_user": ["front_door"],
|
||||
}
|
||||
},
|
||||
"cameras": {
|
||||
"front_door": {
|
||||
"ffmpeg": {
|
||||
"inputs": [{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}]
|
||||
},
|
||||
"detect": {"height": 1080, "width": 1920, "fps": 5},
|
||||
"live": {"streams": {"default": "front_door_main"}},
|
||||
},
|
||||
"back_door": {
|
||||
"ffmpeg": {
|
||||
"inputs": [{"path": "rtsp://10.0.0.2:554/video", "roles": ["detect"]}]
|
||||
},
|
||||
"detect": {"height": 1080, "width": 1920, "fps": 5},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class TestCameraAccessEventReview(BaseTestHttp):
|
||||
def setUp(self):
|
||||
@@ -190,3 +218,179 @@ class TestCameraAccessEventReview(BaseTestHttp):
|
||||
resp = client.get("/events/summary")
|
||||
summary_list = resp.json()
|
||||
assert len(summary_list) == 2
|
||||
|
||||
|
||||
class TestGo2rtcStreamAccess(BaseTestHttp):
|
||||
"""Tests for require_go2rtc_stream_access — the auth dependency on
|
||||
GET /go2rtc/streams/{stream_name}.
|
||||
|
||||
go2rtc is not running in unit tests, so an authorized request returns
|
||||
500 (the proxy call fails), while an unauthorized request returns 401/403
|
||||
before the proxy is ever reached.
|
||||
"""
|
||||
|
||||
def _make_app(self, config_override: dict | None = None):
|
||||
"""Build a test app, optionally replacing self.minimal_config."""
|
||||
if config_override is not None:
|
||||
self.minimal_config = config_override
|
||||
app = super().create_app()
|
||||
|
||||
# Allow tests to control the current user via request headers.
|
||||
async def mock_get_current_user(request: Request):
|
||||
username = request.headers.get("remote-user")
|
||||
role = request.headers.get("remote-role")
|
||||
if not username or not role:
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
return JSONResponse(
|
||||
content={"message": "No authorization headers."},
|
||||
status_code=401,
|
||||
)
|
||||
return {"username": username, "role": role}
|
||||
|
||||
app.dependency_overrides[get_current_user] = mock_get_current_user
|
||||
return app
|
||||
|
||||
def setUp(self):
|
||||
super().setUp([Event, ReviewSegment, Recordings])
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _get_stream(
|
||||
self, app, stream_name: str, role: str = "admin", user: str = "test"
|
||||
):
|
||||
"""Issue GET /go2rtc/streams/{stream_name} with the given role."""
|
||||
with AuthTestClient(app) as client:
|
||||
return client.get(
|
||||
f"/go2rtc/streams/{stream_name}",
|
||||
headers={"remote-user": user, "remote-role": role},
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Tests
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def test_admin_can_access_any_stream(self):
|
||||
"""Admin role bypasses camera restrictions."""
|
||||
app = self._make_app(_MULTI_CAMERA_CONFIG)
|
||||
# front_door stream — go2rtc is not running so expect 500, not 401/403
|
||||
resp = self._get_stream(app, "front_door", role="admin")
|
||||
assert resp.status_code not in (401, 403), (
|
||||
f"Admin should not be blocked; got {resp.status_code}"
|
||||
)
|
||||
|
||||
# back_door stream
|
||||
resp = self._get_stream(app, "back_door", role="admin")
|
||||
assert resp.status_code not in (401, 403)
|
||||
|
||||
def test_missing_auth_headers_returns_401(self):
|
||||
"""Requests without auth headers must be rejected with 401."""
|
||||
app = self._make_app(_MULTI_CAMERA_CONFIG)
|
||||
# Use plain TestClient (not AuthTestClient) so no headers are injected.
|
||||
with TestClient(app, raise_server_exceptions=False) as client:
|
||||
resp = client.get("/go2rtc/streams/front_door")
|
||||
assert resp.status_code == 401, f"Expected 401, got {resp.status_code}"
|
||||
|
||||
def test_unconfigured_role_can_access_any_stream(self):
|
||||
"""When no camera restrictions are configured for a role the user
|
||||
should have access to all streams (no roles_dict entry ⇒ no restriction)."""
|
||||
no_roles_config = {
|
||||
"mqtt": {"host": "mqtt"},
|
||||
"cameras": {
|
||||
"front_door": {
|
||||
"ffmpeg": {
|
||||
"inputs": [
|
||||
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
|
||||
]
|
||||
},
|
||||
"detect": {"height": 1080, "width": 1920, "fps": 5},
|
||||
},
|
||||
"back_door": {
|
||||
"ffmpeg": {
|
||||
"inputs": [
|
||||
{"path": "rtsp://10.0.0.2:554/video", "roles": ["detect"]}
|
||||
]
|
||||
},
|
||||
"detect": {"height": 1080, "width": 1920, "fps": 5},
|
||||
},
|
||||
},
|
||||
}
|
||||
app = self._make_app(no_roles_config)
|
||||
|
||||
# "myuser" role is not listed in roles_dict — should be allowed everywhere
|
||||
for stream in ("front_door", "back_door"):
|
||||
resp = self._get_stream(app, stream, role="myuser")
|
||||
assert resp.status_code not in (401, 403), (
|
||||
f"Unconfigured role should not be blocked on '{stream}'; "
|
||||
f"got {resp.status_code}"
|
||||
)
|
||||
|
||||
def test_restricted_role_can_access_allowed_camera(self):
|
||||
"""limited_user role (restricted to front_door) can access front_door stream."""
|
||||
app = self._make_app(_MULTI_CAMERA_CONFIG)
|
||||
resp = self._get_stream(app, "front_door", role="limited_user")
|
||||
assert resp.status_code not in (401, 403), (
|
||||
f"limited_user should be allowed on front_door; got {resp.status_code}"
|
||||
)
|
||||
|
||||
def test_restricted_role_blocked_from_disallowed_camera(self):
|
||||
"""limited_user role (restricted to front_door) cannot access back_door stream."""
|
||||
app = self._make_app(_MULTI_CAMERA_CONFIG)
|
||||
resp = self._get_stream(app, "back_door", role="limited_user")
|
||||
assert resp.status_code == 403, (
|
||||
f"limited_user should be denied on back_door; got {resp.status_code}"
|
||||
)
|
||||
|
||||
def test_stream_alias_allowed_for_owning_camera(self):
|
||||
"""Stream alias 'front_door_main' is owned by front_door; limited_user (who
|
||||
is allowed front_door) should be permitted."""
|
||||
app = self._make_app(_MULTI_CAMERA_CONFIG)
|
||||
# front_door_main is the alias defined in live.streams for front_door
|
||||
resp = self._get_stream(app, "front_door_main", role="limited_user")
|
||||
assert resp.status_code not in (401, 403), (
|
||||
f"limited_user should be allowed on alias front_door_main; "
|
||||
f"got {resp.status_code}"
|
||||
)
|
||||
|
||||
def test_stream_alias_blocked_when_owning_camera_disallowed(self):
|
||||
"""limited_user cannot access a stream alias that belongs to a camera they
|
||||
are not allowed to see."""
|
||||
# Give back_door a stream alias and restrict limited_user to front_door only
|
||||
config = {
|
||||
"mqtt": {"host": "mqtt"},
|
||||
"auth": {
|
||||
"roles": {
|
||||
"limited_user": ["front_door"],
|
||||
}
|
||||
},
|
||||
"cameras": {
|
||||
"front_door": {
|
||||
"ffmpeg": {
|
||||
"inputs": [
|
||||
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
|
||||
]
|
||||
},
|
||||
"detect": {"height": 1080, "width": 1920, "fps": 5},
|
||||
},
|
||||
"back_door": {
|
||||
"ffmpeg": {
|
||||
"inputs": [
|
||||
{"path": "rtsp://10.0.0.2:554/video", "roles": ["detect"]}
|
||||
]
|
||||
},
|
||||
"detect": {"height": 1080, "width": 1920, "fps": 5},
|
||||
"live": {"streams": {"default": "back_door_main"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
app = self._make_app(config)
|
||||
resp = self._get_stream(app, "back_door_main", role="limited_user")
|
||||
assert resp.status_code == 403, (
|
||||
f"limited_user should be denied on alias back_door_main; "
|
||||
f"got {resp.status_code}"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
"""Utilities for media file inspection."""
|
||||
|
||||
import subprocess as sp
|
||||
|
||||
from frigate.const import DEFAULT_FFMPEG_VERSION
|
||||
|
||||
FFPROBE_PATH = (
|
||||
f"/usr/lib/ffmpeg/{DEFAULT_FFMPEG_VERSION}/bin/ffprobe"
|
||||
if DEFAULT_FFMPEG_VERSION
|
||||
else "ffprobe"
|
||||
)
|
||||
|
||||
|
||||
def get_keyframe_before(path: str, offset_ms: int) -> int | None:
|
||||
"""Get the timestamp (ms) of the last keyframe at or before offset_ms.
|
||||
|
||||
Uses ffprobe packet index to read keyframe positions from the mp4 file.
|
||||
Returns None if ffprobe fails or no keyframe is found before the offset.
|
||||
"""
|
||||
try:
|
||||
result = sp.run(
|
||||
[
|
||||
FFPROBE_PATH,
|
||||
"-select_streams",
|
||||
"v:0",
|
||||
"-show_entries",
|
||||
"packet=pts_time,flags",
|
||||
"-of",
|
||||
"csv=p=0",
|
||||
"-loglevel",
|
||||
"error",
|
||||
path,
|
||||
],
|
||||
capture_output=True,
|
||||
timeout=5,
|
||||
)
|
||||
except (sp.TimeoutExpired, FileNotFoundError):
|
||||
return None
|
||||
|
||||
if result.returncode != 0:
|
||||
return None
|
||||
|
||||
offset_s = offset_ms / 1000.0
|
||||
best_ms = None
|
||||
for line in result.stdout.decode().strip().splitlines():
|
||||
parts = line.strip().split(",")
|
||||
if len(parts) != 2:
|
||||
continue
|
||||
ts_str, flags = parts
|
||||
if "K" not in flags:
|
||||
continue
|
||||
try:
|
||||
ts = float(ts_str)
|
||||
except ValueError:
|
||||
continue
|
||||
if ts <= offset_s:
|
||||
best_ms = int(ts * 1000)
|
||||
else:
|
||||
break
|
||||
|
||||
return best_ms
|
||||
@@ -77,6 +77,7 @@ import { useStreamingSettings } from "@/context/streaming-settings-provider";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { CameraNameLabel } from "../camera/FriendlyNameLabel";
|
||||
import { useAllowedCameras } from "@/hooks/use-allowed-cameras";
|
||||
import { useHasFullCameraAccess } from "@/hooks/use-has-full-camera-access";
|
||||
import { useIsAdmin } from "@/hooks/use-is-admin";
|
||||
import { useUserPersistedOverlayState } from "@/hooks/use-overlay-state";
|
||||
|
||||
@@ -677,7 +678,7 @@ export function CameraGroupEdit({
|
||||
);
|
||||
|
||||
const allowedCameras = useAllowedCameras();
|
||||
const isAdmin = useIsAdmin();
|
||||
const hasFullCameraAccess = useHasFullCameraAccess();
|
||||
|
||||
const [openCamera, setOpenCamera] = useState<string | null>();
|
||||
|
||||
@@ -866,8 +867,7 @@ export function CameraGroupEdit({
|
||||
<FormDescription>{t("group.cameras.desc")}</FormDescription>
|
||||
<FormMessage />
|
||||
{[
|
||||
...(birdseyeConfig?.enabled &&
|
||||
(isAdmin || "birdseye" in allowedCameras)
|
||||
...(birdseyeConfig?.enabled && hasFullCameraAccess
|
||||
? ["birdseye"]
|
||||
: []),
|
||||
...Object.keys(config?.cameras ?? {})
|
||||
|
||||
@@ -1010,7 +1010,7 @@ function LifecycleIconRow({
|
||||
<div className="ml-3 flex-shrink-0 px-1 text-right text-xs text-primary-variant">
|
||||
<div className="flex flex-row items-center gap-3">
|
||||
<div className="whitespace-nowrap">{formattedEventTimestamp}</div>
|
||||
{isAdmin && config?.plus?.enabled && item.data.box && (
|
||||
{isAdmin && (config?.plus?.enabled || item.data.box) && (
|
||||
<DropdownMenu open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DropdownMenuTrigger>
|
||||
<div className="rounded p-1 pr-2" role="button">
|
||||
|
||||
@@ -18,18 +18,25 @@ export default function useCameraLiveMode(
|
||||
|
||||
const streamNames = new Set<string>();
|
||||
cameras.forEach((camera) => {
|
||||
const isRestreamed = Object.keys(config.go2rtc.streams || {}).includes(
|
||||
Object.values(camera.live.streams)[0],
|
||||
);
|
||||
if (activeStreams && activeStreams[camera.name]) {
|
||||
const selectedStreamName = activeStreams[camera.name];
|
||||
const isRestreamed = Object.keys(config.go2rtc.streams || {}).includes(
|
||||
selectedStreamName,
|
||||
);
|
||||
|
||||
if (isRestreamed) {
|
||||
if (activeStreams && activeStreams[camera.name]) {
|
||||
streamNames.add(activeStreams[camera.name]);
|
||||
} else {
|
||||
Object.values(camera.live.streams).forEach((streamName) => {
|
||||
streamNames.add(streamName);
|
||||
});
|
||||
if (isRestreamed) {
|
||||
streamNames.add(selectedStreamName);
|
||||
}
|
||||
} else {
|
||||
Object.values(camera.live.streams).forEach((streamName) => {
|
||||
const isRestreamed = Object.keys(
|
||||
config.go2rtc.streams || {},
|
||||
).includes(streamName);
|
||||
|
||||
if (isRestreamed) {
|
||||
streamNames.add(streamName);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -66,11 +73,11 @@ export default function useCameraLiveMode(
|
||||
} = {};
|
||||
|
||||
cameras.forEach((camera) => {
|
||||
const selectedStreamName =
|
||||
activeStreams?.[camera.name] ?? Object.values(camera.live.streams)[0];
|
||||
const isRestreamed =
|
||||
config &&
|
||||
Object.keys(config.go2rtc.streams || {}).includes(
|
||||
Object.values(camera.live.streams)[0],
|
||||
);
|
||||
Object.keys(config.go2rtc.streams || {}).includes(selectedStreamName);
|
||||
|
||||
newIsRestreamedStates[camera.name] = isRestreamed ?? false;
|
||||
|
||||
@@ -101,14 +108,21 @@ export default function useCameraLiveMode(
|
||||
setPreferredLiveModes(newPreferredLiveModes);
|
||||
setIsRestreamedStates(newIsRestreamedStates);
|
||||
setSupportsAudioOutputStates(newSupportsAudioOutputStates);
|
||||
}, [cameras, config, windowVisible, streamMetadata]);
|
||||
}, [activeStreams, cameras, config, windowVisible, streamMetadata]);
|
||||
|
||||
const resetPreferredLiveMode = useCallback(
|
||||
(cameraName: string) => {
|
||||
const mseSupported =
|
||||
"MediaSource" in window || "ManagedMediaSource" in window;
|
||||
const cameraConfig = cameras.find((camera) => camera.name === cameraName);
|
||||
const selectedStreamName =
|
||||
activeStreams?.[cameraName] ??
|
||||
(cameraConfig
|
||||
? Object.values(cameraConfig.live.streams)[0]
|
||||
: cameraName);
|
||||
const isRestreamed =
|
||||
config && Object.keys(config.go2rtc.streams || {}).includes(cameraName);
|
||||
config &&
|
||||
Object.keys(config.go2rtc.streams || {}).includes(selectedStreamName);
|
||||
|
||||
setPreferredLiveModes((prevModes) => {
|
||||
const newModes = { ...prevModes };
|
||||
@@ -122,7 +136,7 @@ export default function useCameraLiveMode(
|
||||
return newModes;
|
||||
});
|
||||
},
|
||||
[config],
|
||||
[activeStreams, cameras, config],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { useAllowedCameras } from "@/hooks/use-allowed-cameras";
|
||||
import useSWR from "swr";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
|
||||
/**
|
||||
* Returns true if the current user has access to all cameras.
|
||||
* This is used to determine birdseye access — users who can see
|
||||
* all cameras should also be able to see the birdseye view.
|
||||
*/
|
||||
export function useHasFullCameraAccess() {
|
||||
const allowedCameras = useAllowedCameras();
|
||||
const { data: config } = useSWR<FrigateConfig>("config", {
|
||||
revalidateOnFocus: false,
|
||||
});
|
||||
|
||||
if (!config?.cameras) return false;
|
||||
|
||||
const enabledCameraNames = Object.entries(config.cameras)
|
||||
.filter(([, cam]) => cam.enabled_in_config)
|
||||
.map(([name]) => name);
|
||||
|
||||
return (
|
||||
enabledCameraNames.length > 0 &&
|
||||
enabledCameraNames.every((name) => allowedCameras.includes(name))
|
||||
);
|
||||
}
|
||||
@@ -11,12 +11,12 @@ import { useTranslation } from "react-i18next";
|
||||
import { useEffect, useMemo, useRef } from "react";
|
||||
import useSWR from "swr";
|
||||
import { useAllowedCameras } from "@/hooks/use-allowed-cameras";
|
||||
import { useIsAdmin } from "@/hooks/use-is-admin";
|
||||
import { useHasFullCameraAccess } from "@/hooks/use-has-full-camera-access";
|
||||
|
||||
function Live() {
|
||||
const { t } = useTranslation(["views/live"]);
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
const isAdmin = useIsAdmin();
|
||||
const hasFullCameraAccess = useHasFullCameraAccess();
|
||||
|
||||
// selection
|
||||
|
||||
@@ -90,8 +90,8 @@ function Live() {
|
||||
const allowedCameras = useAllowedCameras();
|
||||
|
||||
const includesBirdseye = useMemo(() => {
|
||||
// Restricted users should never have access to birdseye
|
||||
if (!isAdmin) {
|
||||
// Users without access to all cameras should not have access to birdseye
|
||||
if (!hasFullCameraAccess) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ function Live() {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}, [config, cameraGroup, isAdmin]);
|
||||
}, [config, cameraGroup, hasFullCameraAccess]);
|
||||
|
||||
const cameras = useMemo(() => {
|
||||
if (!config) {
|
||||
@@ -151,7 +151,9 @@ function Live() {
|
||||
|
||||
return (
|
||||
<div className="size-full" ref={mainRef}>
|
||||
{selectedCameraName === "birdseye" ? (
|
||||
{selectedCameraName === "birdseye" &&
|
||||
hasFullCameraAccess &&
|
||||
config?.birdseye?.enabled ? (
|
||||
<LiveBirdseyeView
|
||||
supportsFullscreen={supportsFullScreen}
|
||||
fullscreen={fullscreen}
|
||||
|
||||
Reference in New Issue
Block a user