Compare commits

...
Author SHA1 Message Date
dependabot[bot]andGitHub 93701de7fa Update pandas requirement from ==3.0.* to ==3.1.* in /docker/main
Updates the requirements on [pandas](https://github.com/pandas-dev/pandas) to permit the latest version.
- [Release notes](https://github.com/pandas-dev/pandas/releases)
- [Commits](https://github.com/pandas-dev/pandas/compare/v3.0.0.dev0...v3.1.0)

---
updated-dependencies:
- dependency-name: pandas
  dependency-version: 3.1.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-01 13:43:49 +00:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
689a5b59ac Update sherpa-onnx requirement from ==1.13.* to ==2.0.* in /docker/main (#24842)
---
updated-dependencies:
- dependency-name: sherpa-onnx
  dependency-version: 2.0.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-11-01 07:41:48 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
69061d17f1 Update transformers requirement in /docker/main (#24841)
Updates the requirements on [transformers](https://github.com/huggingface/transformers) to permit the latest version.
- [Release notes](https://github.com/huggingface/transformers/releases)
- [Commits](https://github.com/huggingface/transformers/compare/v5.20.0...v5.21.1)

---
updated-dependencies:
- dependency-name: transformers
  dependency-version: 5.21.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-11-01 07:41:40 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
efb890e6e0 Bump the pip-main-minor-patch group in /docker/main with 3 updates (#24840)
Bumps the pip-main-minor-patch group in /docker/main with 3 updates: [ruff](https://github.com/astral-sh/ruff), [mypy](https://github.com/python/mypy) and [tzdata](https://github.com/python/tzdata).


Updates `ruff` from 0.17.1 to 0.17.3
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.17.1...0.17.3)

Updates `mypy` from 2.4.0 to 2.4.1
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v2.4.0...v2.4.1)

Updates `tzdata` from 2026.5 to 2026.6
- [Release notes](https://github.com/python/tzdata/releases)
- [Changelog](https://github.com/python/tzdata/blob/master/NEWS.md)
- [Commits](https://github.com/python/tzdata/compare/2026.5...2026.6)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.17.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: pip-main-minor-patch
- dependency-name: mypy
  dependency-version: 2.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: pip-main-minor-patch
- dependency-name: tzdata
  dependency-version: '2026.6'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: pip-main-minor-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-11-01 07:41:30 -06:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ea7b3e2336 Bump the actions group across 2 directories with 1 update (#24845)
Bumps the actions group with 1 update in the / directory: [docker/login-action](https://github.com/docker/login-action).
Bumps the actions group with 1 update in the /.github/actions/setup directory: [docker/login-action](https://github.com/docker/login-action).


Updates `docker/login-action` from 4.6.0 to 4.7.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/dbcb813823bdd20940b903addbd779551569679f...81c6f93d4bc991e510b342a00b419b3bb4efc5c6)

Updates `docker/login-action` from 4.6.0 to 4.7.0
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/dbcb813823bdd20940b903addbd779551569679f...81c6f93d4bc991e510b342a00b419b3bb4efc5c6)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: 4.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: docker/login-action
  dependency-version: 4.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-11-01 07:41:08 -06:00
Josh HawkinsandGitHub a0b8d40a66 guard relativemove failures (#24835)
CI / AMD64 Build (push) Canceled after 0s
CI / AMD64 Smoke Test (push) Canceled after 0s
CI / ARM Build (push) Canceled after 0s
CI / Jetson Jetpack 6 (push) Canceled after 0s
CI / AMD64 Extra Build (push) Canceled after 0s
CI / ARM Extra Build (push) Canceled after 0s
CI / Synaptics Build (push) Canceled after 0s
CI / Assemble and push default build (push) Canceled after 0s
2026-10-31 14:15:24 -06:00
Josh HawkinsandGitHub 9b0aa75312 Add configurable notification TTL (#24829)
CI / AMD64 Build (push) Canceled after 0s
CI / AMD64 Smoke Test (push) Canceled after 0s
CI / ARM Build (push) Canceled after 0s
CI / Jetson Jetpack 6 (push) Canceled after 0s
CI / AMD64 Extra Build (push) Canceled after 0s
CI / ARM Extra Build (push) Canceled after 0s
CI / Synaptics Build (push) Canceled after 0s
CI / Assemble and push default build (push) Canceled after 0s
* add configurable ttl for active alert notifications

Notifications sent while an alert was active always used a TTL of 0, so the push service dropped them if the device wasn't reachable at that moment and users only received the notification sent when the alert ended. A new `ttl` notifications option, settable globally or per camera, lets the push service retry these notifications for that many seconds. It defaults to 0, and the settings UI warns that a non-zero value can deliver stale notifications.

* make notification ttl a global advanced setting

- Read `ttl` from the global notifications config and hide it on the camera form
- Show it under Advanced Settings on the Notifications page
- Remove extra padding that misaligned the Notifications cards with the rest of the form
- Shorten the ttl warning

* tweaks

* use enum instead of raw seconds value
2026-10-30 12:52:22 -06:00
16 changed files with 100 additions and 18 deletions
+1 -1
View File
@@ -42,7 +42,7 @@ runs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f
uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6
with:
registry: ghcr.io
username: ${{ github.actor }}
+1 -1
View File
@@ -590,7 +590,7 @@ jobs:
with:
string: ${{ github.repository }}
- name: Log in to the Container registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f
uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6
with:
registry: ghcr.io
username: ${{ github.actor }}
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
with:
string: ${{ github.repository }}
- name: Log in to the Container registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f
uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6
with:
registry: ghcr.io
username: ${{ github.actor }}
+1 -1
View File
@@ -1,4 +1,4 @@
ruff == 0.17.1
ruff == 0.17.3
# types
types-peewee == 4.0.*
+5 -5
View File
@@ -16,16 +16,16 @@ python-multipart == 0.0.32
tensorflow == 2.19.* ; platform_machine == 'aarch64'
tensorflow-cpu == 2.21.* ; platform_machine == 'x86_64'
# General
mypy == 2.4.0
mypy == 2.4.1
onvif-zeep-async == 4.3.*
paho-mqtt == 2.1.*
pandas == 3.0.*
pandas == 3.1.*
peewee == 4.5.*
peewee_migrate == 2.3.*
psutil == 7.2.*
pydantic == 2.14.*
git+https://github.com/fbcotter/py3nvml#egg=py3nvml
tzdata == 2026.5
tzdata == 2026.6
pyzmq == 27.2.*
ruamel.yaml == 0.19.*
tzlocal == 5.4.5
@@ -45,7 +45,7 @@ scipy == 1.17.*
openvino == 2026.4.*
onnxruntime == 1.31.*
# Embeddings
transformers == 5.20.*
transformers == 5.21.*
# Generative AI
google-genai == 2.32.*
ollama == 0.6.*
@@ -68,7 +68,7 @@ prometheus-client == 0.26.*
tflite_runtime @ https://github.com/frigate-nvr/TFlite-builds/releases/download/v2.17.1/tflite_runtime-2.17.1-cp311-cp311-linux_x86_64.whl; platform_machine == 'x86_64'
tflite_runtime @ https://github.com/feranick/TFlite-builds/releases/download/v2.17.1/tflite_runtime-2.17.1-cp311-cp311-linux_aarch64.whl; platform_machine == 'aarch64'
# audio transcription
sherpa-onnx==1.13.*
sherpa-onnx==2.0.*
faster-whisper==1.2.*
librosa==0.11.*
soundfile==0.14.*
@@ -578,6 +578,10 @@ notifications:
email: "admin@example.com"
# Optional: Cooldown time for notifications in seconds (default: shown below)
cooldown: 0
# Optional: Delivery of notifications sent while an alert is active (default: shown below)
# Options are immediate (deliver right away or drop) and reliable (retry for up to 30 seconds)
# NOTE: reliable can deliver late notifications that still link to the live view
ttl: immediate
# Optional: Record configuration
# NOTE: Can be overridden at the camera level
+24 -1
View File
@@ -43,7 +43,7 @@ Notifications will be prevented if either:
<ConfigTabs>
<TabItem value="ui">
1. Navigate to <NavPath path="Settings > Notifications > Notifications" />.
1. Navigate to <NavPath path="Settings > Notifications" />.
- Set **Email** to your email address
- Enable notifications for the desired cameras
@@ -108,6 +108,29 @@ Currently, only Chrome supports images in notifications. Safari and Firefox will
Different platforms handle notifications differently, some settings changes may be required to get optimal notification delivery.
### Notification TTL
By default, Frigate sends notifications for an active alert with a `ttl` of `immediate`, so the push service either delivers them immediately or drops them. If your device is briefly unreachable (asleep, switching from Wi-Fi to cellular, or on a weak signal), those notifications are lost and you only receive the notification sent when the alert ends, which is always kept for up to an hour.
Setting `ttl` to `reliable` tells the push service to keep retrying these notifications for up to 30 seconds. This makes delivery more reliable, but a notification delivered late will still say an object is detected, even if the object has already left.
<ConfigTabs>
<TabItem value="ui">
1. Navigate to <NavPath path="Settings > Notifications" />.
- Expand **Advanced Settings** and set **Notification TTL** to **Reliable**
</TabItem>
<TabItem value="yaml">
```yaml
notifications:
ttl: reliable # retry an undelivered notification for up to 30 seconds
```
</TabItem>
</ConfigTabs>
### Android
Most Android phones have battery optimization settings. To get reliable Notification delivery the browser (Chrome, Firefox) should have battery optimizations disabled. If Frigate is running as a PWA then the Frigate app should have battery optimizations disabled as well.
+2 -1
View File
@@ -22,6 +22,7 @@ from frigate.comms.base_communicator import Communicator
from frigate.comms.config_updater import ConfigSubscriber
from frigate.config import FrigateConfig
from frigate.config.auth import AuthConfig
from frigate.config.camera.notification import NOTIFICATION_TTL_SECONDS
from frigate.config.camera.updater import (
CameraConfigUpdateEnum,
CameraConfigUpdateSubscriber,
@@ -623,7 +624,7 @@ class WebPushClient(Communicator):
# if event is ongoing open to live view otherwise open to recordings view
direct_url = f"/review?id={reviewId}" if ended else f"/#{camera}"
ttl = 3600 if ended else 0
ttl = 3600 if ended else NOTIFICATION_TTL_SECONDS[self.config.notifications.ttl]
logger.debug(f"Sending push notification for {camera}, review ID {reviewId}")
+19 -1
View File
@@ -1,10 +1,23 @@
from enum import Enum
from pydantic import Field
from frigate.util.env import EnvString
from ..base import FrigateBaseModel
__all__ = ["NotificationConfig"]
__all__ = ["NotificationConfig", "NotificationTTLEnum", "NOTIFICATION_TTL_SECONDS"]
class NotificationTTLEnum(str, Enum):
immediate = "immediate"
reliable = "reliable"
NOTIFICATION_TTL_SECONDS = {
NotificationTTLEnum.immediate: 0,
NotificationTTLEnum.reliable: 30,
}
class NotificationConfig(FrigateBaseModel):
@@ -24,6 +37,11 @@ class NotificationConfig(FrigateBaseModel):
title="Cooldown period",
description="Cooldown (seconds) between notifications to avoid spamming recipients.",
)
ttl: NotificationTTLEnum = Field(
default=NotificationTTLEnum.immediate,
title="Notification TTL",
description="How the push service handles a notification sent while an alert is active if your device can't be reached. Immediate delivers it right away or drops it. Reliable keeps retrying for up to 30 seconds. The notification sent when an alert ends is always kept for up to an hour.",
)
enabled_in_config: bool | None = Field(
default=None,
title="Original notifications state",
+6 -1
View File
@@ -625,7 +625,12 @@ class OnvifController:
move_request.Speed = move_speed
await cam["ptz"].RelativeMove(move_request)
try:
await cam["ptz"].RelativeMove(move_request)
except Exception as e:
logger.warning(
f"Onvif sending relative move request to {camera_name} failed: {e}"
)
# reset after the move request
move_request.Translation.PanTilt.x = 0
+9
View File
@@ -195,6 +195,15 @@ class TestManualRelativeMoveMetrics(unittest.IsolatedAsyncioTestCase):
)
)
async def test_failed_move_does_not_raise(self) -> None:
# an exception here ends the autotracker's move queue consumer for good
controller = _make_move_controller(autotracking_enabled=True)
controller.cams[CAMERA]["ptz"].RelativeMove.side_effect = TimeoutError
await controller._move_relative(CAMERA, 0.25, -0.25, 0, 1)
self.assertFalse(controller.cams[CAMERA]["active"])
async def test_metrics_written_when_autotracking_enabled(self) -> None:
# get_camera_status resets stop_time once the camera reports IDLE, so the
# autotracking path keeps its motion estimation timestamps
@@ -858,6 +858,10 @@
"label": "Cooldown period",
"description": "Cooldown (seconds) between notifications to avoid spamming recipients."
},
"ttl": {
"label": "Notification TTL",
"description": "How the push service handles a notification sent while an alert is active if your device can't be reached. Immediate delivers it right away or drops it. Reliable keeps retrying for up to 30 seconds. The notification sent when an alert ends is always kept for up to an hour."
},
"enabled_in_config": {
"label": "Original notifications state",
"description": "Indicates whether notifications were enabled in the original static configuration."
+4
View File
@@ -154,6 +154,10 @@
"label": "Cooldown period",
"description": "Cooldown (seconds) between notifications to avoid spamming recipients."
},
"ttl": {
"label": "Notification TTL",
"description": "How the push service handles a notification sent while an alert is active if your device can't be reached. Immediate delivers it right away or drops it. Reliable keeps retrying for up to 30 seconds. The notification sent when an alert ends is always kept for up to an hour."
},
"enabled_in_config": {
"label": "Original notifications state",
"description": "Indicates whether notifications were enabled in the original static configuration."
+6 -1
View File
@@ -1934,6 +1934,10 @@
"saved": "Saved"
}
},
"notificationTtl": {
"immediate": "Immediate",
"reliable": "Reliable"
},
"retainMode": {
"all": "All",
"motion": "Motion",
@@ -2051,7 +2055,8 @@
"profileBaseDisabled": "Recording is disabled in this camera's base config, so enabling it in a profile has no effect. Enable recording in the base config and use a profile to disable it instead."
},
"notifications": {
"profileBaseDisabled": "No cameras have notifications enabled in their base config, so enabling them in a profile has no effect. Enable notifications in the base config of at least one camera."
"profileBaseDisabled": "No cameras have notifications enabled in their base config, so enabling them in a profile has no effect. Enable notifications in the base config of at least one camera.",
"ttlDelay": "Notifications can arrive up to 30 seconds late and still link to the live view after the review item has ended."
},
"birdseye": {
"objectTrackingDetectDisabled": "Birdseye includes tracked objects, but object detection is disabled for this camera. The camera will not appear in Birdseye.",
@@ -7,7 +7,7 @@ const notifications: SectionConfigOverrides = {
fieldOrder: ["enabled", "email"],
fieldGroups: {},
hiddenFields: ["enabled_in_config"],
advancedFields: [],
advancedFields: ["ttl"],
fieldMessages: [
{
key: "profile-base-notifications-disabled",
@@ -24,6 +24,14 @@ const notifications: SectionConfigOverrides = {
camera.notifications.enabled_in_config,
),
},
{
key: "notifications-ttl-delay",
field: "ttl",
messageKey: "configMessages.notifications.ttlDelay",
severity: "warning",
position: "after",
condition: (ctx) => ctx.formData?.ttl === "reliable",
},
],
},
global: {
@@ -31,12 +39,13 @@ const notifications: SectionConfigOverrides = {
"ui:before": { render: "NotificationsSettingsExtras" },
enabled: { "ui:widget": "hidden" },
email: { "ui:widget": "hidden" },
ttl: { "ui:options": { enumI18nPrefix: "notificationTtl" } },
cooldown: { "ui:widget": "hidden" },
enabled_in_config: { "ui:widget": "hidden" },
},
},
camera: {
hiddenFields: ["enabled_in_config", "email"],
hiddenFields: ["enabled_in_config", "email", "ttl"],
},
};
@@ -340,7 +340,7 @@ export default function NotificationsSettingsExtras({
set(nextNotifications, "enabled", desiredEnabled);
const sanitizedNotifications = sanitizeSectionData(
nextNotifications as ConfigSectionData,
["enabled_in_config", "email"],
["enabled_in_config", "email", "ttl"],
);
onPendingDataChange("notifications", camera.name, sanitizedNotifications);
pendingCameraOverridesRef.current.add(camera.name);
@@ -490,7 +490,7 @@ export default function NotificationsSettingsExtras({
return (
<div className="flex size-full flex-col md:flex-row">
<div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto px-2 md:order-none">
<div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto md:order-none">
<div className={cn("w-full max-w-5xl space-y-6")}>
{isAdmin && (
<SettingsGroupCard