Commit Graph
21 Commits
Author SHA1 Message Date
Josh HawkinsandGitHub 796aec7a4a Limit concurrent motion searches (#24717)
* limit concurrent motion search jobs and search range

Any viewer could start unlimited motion search jobs over an unbounded time range, and finished jobs were never dropped from memory. Each user now gets one active job (409), at most 3 run at once (429), the range is capped at 48 hours, and finished jobs are evicted 10 minutes after they end. Jobs are no longer filed in the shared job manager, which kept every finished job forever.

* show translated errors for motion search limits

* release the motion search slot if the runner fails to start

* keep wedged or shared-identity motion searches from locking out users

A stalled VOD read blocked the runner forever, so a wedged job held its user and global slot until restart, and on installs without per-user identity (internal port, or auth disabled without a proxy user header) everyone shared one per-user slot. VOD ffmpeg and ffprobe inputs now use a 30 s rw_timeout, a cancel also drops queued parallel runs, a cancelled job stops counting after 60 s, and the per-user limit only applies when the request carries a real username. A failed runner start also stops its requestor.

* treat timed-out VOD segments as motion search errors

With rw_timeout, the HLS demuxer skipped a timed-out segment and exited cleanly, so a run reported success with a hole in it, and when the keyframe probe and the decode lost different segments the equal frame counts paired frames with the wrong timestamps. The keyframe path now requires the probe to cover the whole run without a gap over 5 s, a decode whose stderr shows a skipped segment fails the run, and a cadence decode more than 5 s short of the run's duration fails it too, so these runs land in segments_with_errors. The keyframe probe polls should_stop and is killed on cancel, probe_video_dimensions gets the read timeout, and a user's own cancelled job no longer blocks their next search while it still counts toward the global cap.

* drop motion search stall detection and range cap

* remove motion search range check from the UI
2026-10-19 04:52:15 -10:00
Josh HawkinsandGitHub cabdffea20 Update more web deps and reformat with updated prettier (#24358)
* update date-fns, i18next, react-dropzone, react-markdown and @types/node

react-i18next 17 peers `i18next >= 26.2.0`, so the two move together. react-day-picker already depends on date-fns 4, so date-fns now dedupes to a single copy. react-dropzone 20 declares `node >=22` in `engines`, but npm only warns on Node 20 and nothing in the build needs Node 22.

* update js-yaml, @hookform/resolvers and prettier

js-yaml 5 has no default export, so `DictAsYamlField` imports `dump`, `load` and `YAMLException` by name. @hookform/resolvers 5 types `zodResolver` with the schema's input and output types separately, and fields with defaults are optional on input, so the zone and classification model forms pass both types to `useForm`. zod's range now starts at 3.25, which resolvers 5 requires.

* format with prettier 3.9
2026-09-15 15:18:49 -06:00
Josh HawkinsandNicolas Mowen 53b04f44ef Fix preview players at the hour rollover (#24157)
* fix preview players at the hour rollover

* clean up
2026-09-12 07:30:04 -06:00
Josh HawkinsandNicolas Mowen 1498231eb9 Add sub stream recording with adaptive quality playback (#24009)
* add sub stream recording with adaptive quality playback

Optionally record a second, lower bitrate stream alongside the main
recording stream via a `record_sub` input role and `record.sub` config block, with its own retention windows.
Recordings rows now carry the stream type plus the media details needed to serve both streams from one manifest: video codec, audio presence, audio codec and rate, and a record-time keyframe index.

Playback resolves coverage across both streams and merges them into a single VOD sequence, falling back to a discontinuity manifest with per-clip init segments when the media signatures differ. The player exposes a quality selector, and an auto governor picks the stream from stall time, bandwidth, codec support, and the save-data hint.

* fix tests and i18n
2026-09-12 07:30:04 -06:00
Josh HawkinsandGitHub c75611b4df Multi-export UI fixes (#23959)
CI / AMD64 Build (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
* multi export fixes

* i18n

* new tests
2026-08-11 10:11:47 -06:00
Josh HawkinsandGitHub e73a14db5d Miscellaneous fixes (0.18 beta) (#23898)
CI / AMD64 Build (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
* update homekit docs

* update dictionary

* preserve function names in production builds

adds only 162kb gzipped/450k unzipped to the bundle

* margin tweak

* fix maximum update depth exceeded when dragging the timeline handlebar

Dragging the handlebar, especially quickly or with fast direction changes, could exceed React's nested update limit and unmount the whole app, leaving a blank screen. Motion search was worst affected.

The drag loop committed a new time into React state on every animation frame. Edge auto-scrolling mutates scrollTop each iteration, so the value always differed and React's same-value bail-out never engaged, letting the update chain run to the limit of 50. Pace those commits to one per 100ms and flush the pending value on release, so the drop position is still exact. The handlebar position and label are written to the DOM directly and remain at frame rate.

useUserInteraction dispatched state on every scroll and touchmove event; only commit on the leading edge.

Motion search also passed fresh array literals for the timeline's events, motion events and unavailable ranges, giving the segment memo and the drag effect new dependencies on every render. Both views also passed an inline arrow for onHandlebarDraggingChange, which is an effect dependency that calls setState.

* Verify motion search jobs belong to the requested camera

* Apply persisted profile and runtime overrides before workers start

Worker processes are handed a copy of the config when they start and only learn about later changes from the config_updater broadcast, which is plain ZMQ PUB/SUB with no queue, ack, or retained value, so a message published before a subscriber has connected is dropped and never re-sent. The persisted profile and the runtime camera toggles were restored only by that broadcast, at the very end of startup, so a worker that lost the race kept its yaml values for the rest of the session: audio detection kept running on a camera whose audio had been toggled off, even though /api/config, the UI, and the runtime state file all showed it disabled. Split both restores into a config half and a publish half. ProfileManager.restore_persisted_profile_to_config() and Dispatcher.reapply_runtime_state_to_config() now run right after init_profile_manager(), before the first worker starts, so every worker is handed a config that already carries both layers. ProfileManager.restore_persisted_profile() and Dispatcher.restore_runtime_state() still run at the end of startup: the recording, review, and embeddings processes start before the dispatcher exists, so the broadcast remains their only channel, and MQTT needs the retained switch states. Both config passes have to stay after init_profile_manager(), which snapshots the config as the no-profile base that deactivation resets to.

* End timeline drags on touchcancel
2026-08-05 07:40:24 -05:00
d02a1156b7 Miscellaneous fixes (0.18 beta) (#23736)
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
* Catch faces that become empty after cropping

* don't drop batched camera add/remove config updates

TrackedObjectProcessor drained all pending camera config updates at once but handled them in a mutually exclusive if/elif on enabled/add/remove, so only one topic was processed per drain. When an add arrived in the same batch as an enabled update, the add was skipped and the new camera never got a camera state. Adding a camera reliably produced that batch: config_set now re-applies runtime overrides, which republishes an enabled update for every previously toggled camera immediately before the add, in the same request. The dashboard and camera capture still saw the camera (the maintainer does not subscribe to enabled, so it got a clean add-only batch), but object_processing did not, and disabling the camera then crashed with a KeyError on the unguarded camera_states lookup.

Handle add and remove independently instead of as exclusive branches so a batched add is no longer dropped, and guard the remove lookup so a missing state is skipped rather than raising. Drop the enabled branch entirely: it only ever set prev_enabled when it was None, but prev_enabled is seeded to a bool at camera state creation and is never None (mypy flags the body as unreachable), and the actual enable/disable transition is already driven by the disabled-state loop from config.enabled.

* Don't stay on motion search page when user cancels flow

* fix notification test button being blocked by websocket auth

* fix overflowing model names in settings genai widget

* add note about auth debugging

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2026-07-17 08:00:15 -06:00
Martin WeineltandGitHub f3c09ae169 Typo fixes (#23669)
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
* Fix typos

With help from https://github.com/crate-ci/typos

* Fix repeated article "the"

* Fix repeated "changed"
2026-07-10 08:10:13 -05:00
Josh HawkinsandGitHub 8073174c20 Refactor motion search (#23378)
* refactor motion search

* cleanup dead code and tests

* tweaks

* fix multi-day seeking

* start playback a few seconds before the change so the motion is in view
2026-06-01 12:08:46 -05:00
Josh HawkinsandGitHub 407817a3b1 Motion search fixes (#23359)
* improve error parsing and increase skip default

* improve motion search  layout to match tracking details

* implement draw and move mode on mobile

* update motion search docs

* language tweaks

* improve tips

* note actions menu
2026-05-31 07:51:32 -06:00
Josh HawkinsandGitHub 08be019bed Miscellaneous fixes (#23358)
CI / AMD64 Build (push) Waiting to run
CI / Assemble and push default build (push) Blocked by required conditions
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
* improve visibility of blurred icon buttons

* add motion search to history actions menu and mobile drawer

* i18n

* use pure css for motion search dialog video

* defer profile restoration until subscribers are connected

* change order of features in mobile review settings drawer
2026-05-30 21:35:03 -06:00
Josh HawkinsandGitHub 6fdd65ddb5 UI tweaks (#23346)
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
* remove redundant per-view toasters in settings

* add variants to standardize dialog footer button layouts

* remove text-md

this class name compiles to nothing in tailwind. we used to add it to prevent iOS from zooming when focusing on an input, but that is now solved via the viewport meta in index.html

* make wizard footers consistent with dialog footers

* consistent destructive button style

remove text-white from individual buttons and add it to the variant
2026-05-29 16:00:30 -06:00
Josh HawkinsandGitHub 32daf6f494 Miscellaneous fixes (#23217)
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
* fix hardcoded leading-slash hrefs to respect FRIGATE_BASE_PATH

* update docs for default detector
2026-05-17 14:40:33 -06:00
ba4a6a53d7 Miscellaneous fixes (#23053)
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
* don't exempt draft PRs from stalebot

* Fix import

* ensure toast shows when export API returns 20n (202, accepted)

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2026-04-30 17:19:53 -06:00
Josh HawkinsandGitHub 3b81416299 Update Radix deps (#22957)
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
* Bump radix-ui packages to align react-dismissable-layer version and fix nested overlay pointer-events bug

* remove workarounds for radix pointer events issues on dropdown and context menus

* remove disablePortal from popover

* remove modal on popovers

* remove workarounds in restart dialog

* keep onCloseAutoFocus for face, classification, and ptz

these are necessary to prevent tooltips from re-showing and from the arrow keys from reopening the ptz presets menu

* add tests
2026-04-21 08:48:48 -06:00
Josh HawkinsandGitHub e7e6f87682 Export improvements (#22867)
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
* backend

* frontend + i18n

* tests + api spec

* tweak backend to use Job infrastructure for exports

* frontend tweaks and Job infrastructure

* tests

* tweaks

- add ability to remove from case
- change location of counts in case card

* add stale export reaper on startup

* fix toaster close button color

* improve add dialog

* formatting

* hide max_concurrent from camera config export settings

* remove border

* refactor batch endpoint for multiple review items

* frontend

* tests and fastapi spec

* fix deletion of in-progress exports in a case

* tweaks

- hide cases when filtering cameras that have no exports from those cameras
- remove description from case card
- use textarea instead of input for case description in add new case dialog

* add auth exceptions for exports

* add e2e test for deleting cases with exports

* refactor delete and case endpoints

allow bulk deleting and reassigning

* frontend

- bulk selection like Review
- gate admin-only actions
- consolidate dialogs
- spacing/padding tweaks

* i18n and tests

* update openapi spec

* tweaks

- add None to case selection list
- allow new case creation from single cam export dialog

* fix codeql

* fix i18n

* remove unused

* fix frontend tests
2026-04-14 08:19:50 -06:00
Josh HawkinsandGitHub 8f13932c64 UI fixes (#22814)
* display area as proper percentage in debug view

* match replay objects list with debug view

* motion search fixes

- tweak progress bar to exclude heatmap and inactive segments
- show metrics immediately on search start
- fix preview frame loading race
- fix polygon missing after dialog remount
- don't try to drag the image when dragging vertex of polygon

* add activity indicator to storage metrics

* make sub label query for events API endpoints case insensitive
2026-04-08 08:21:48 -06:00
Josh HawkinsandGitHub 257dae11c1 Fix browser time format handling (#22694)
* implement hook to return resolved "24hour" | "12hour" string

delegate to existing use24HourTime(), which correctly detects the browser's locale preference via Intl.DateTimeFormat

* update frontend to use use24HourTime(config) or useTimeFormat(config) instead of directly comparing config.ui.time_format
2026-03-29 13:03:07 -06:00
Josh HawkinsandGitHub 34a06ac77b Tweaks (#22552)
* add weblate to contributing docs

* show vertex points in dialog only in motion search
2026-03-20 11:00:28 -06:00
Josh HawkinsandGitHub c9bd907721 Frontend fixes (#22294)
* fix useImageLoaded hook running on every render

* fix volume not applying for all cameras

* Fix maximum update depth exceeded errors on Review page

- use-overlay-state: use refs for location to keep setter identity
  stable across renders, preventing cascading re-render loops when
  effects depend on the setter. Add Object.is bail-out guard to skip
  redundant navigate calls. Move setPersistedValue after bail-out to
  avoid unnecessary IndexedDB writes.

* don't try to fetch previews when motion search dialog is open

* revert unneeded changes

re-rendering was caused by the overlay state hook, not this one

* filter dicts to only use id field in sync recordings
2026-03-06 13:41:15 -07:00
Josh HawkinsandGitHub 2babfd2ec9 Improve motion review and add motion search (#22253)
* implement motion search and motion previews

* tweaks

* fix merge issue

* fix copilot instructions
2026-03-05 17:53:48 -06:00