From 7d4b87946ec7c2fc6c9ceb5bf717084a21d020ad Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Sun, 25 Oct 2026 18:13:00 -0500 Subject: [PATCH] Miscellaneous fixes (#24790) * stagger the daily region grid rebuild across cameras Every camera requested its region grid at exactly 02:00, so the requests queued up in the dispatcher and held up recording segment inserts behind them. Each camera now picks a random offset of up to an hour. * only log ffmpeg crashes when restarting * round preview skeleton corners to match the player --- frigate/video/detect.py | 9 ++++++--- frigate/video/ffmpeg.py | 12 ++++++------ web/src/components/player/PreviewPlayer.tsx | 8 ++++++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/frigate/video/detect.py b/frigate/video/detect.py index 591b57f97e..a9c17d33cb 100644 --- a/frigate/video/detect.py +++ b/frigate/video/detect.py @@ -2,10 +2,11 @@ import logging import queue +import random import threading import time from collections import deque -from datetime import UTC, datetime +from datetime import UTC, datetime, timedelta from multiprocessing import Queue from multiprocessing.synchronize import Event as MpEvent from typing import Any @@ -255,7 +256,9 @@ def process_frames( region_grid: list[list[dict[str, Any]]], exit_on_empty: bool = False, ): - next_region_update = get_tomorrow_at_time(2) + # cameras share one dispatcher, so stagger the daily grid rebuilds + region_update_offset = timedelta(seconds=random.randrange(3600)) + next_region_update = get_tomorrow_at_time(2) + region_update_offset config_subscriber = CameraConfigUpdateSubscriber( None, {camera_config.name: camera_config}, @@ -344,7 +347,7 @@ def process_frames( if updated_grid: region_grid = updated_grid - next_region_update = get_tomorrow_at_time(2) + next_region_update = get_tomorrow_at_time(2) + region_update_offset try: if exit_on_empty: diff --git a/frigate/video/ffmpeg.py b/frigate/video/ffmpeg.py index 35b22458c7..9cf5dcd4e1 100644 --- a/frigate/video/ffmpeg.py +++ b/frigate/video/ffmpeg.py @@ -474,10 +474,10 @@ class CameraWatchdog(threading.Thread): if not self.capture_thread.is_alive(): self.detect_status.send("offline", now) self.camera_fps.value = 0 - self.logger.error( - f"Ffmpeg process crashed unexpectedly for {self.config.name}." - ) if can_restart: + self.logger.error( + f"Ffmpeg process crashed unexpectedly for {self.config.name}." + ) self.reset_capture_thread(terminate=False) last_restart_time = now elif self.camera_fps.value >= (self.config.detect.fps + 10): @@ -498,10 +498,10 @@ class CameraWatchdog(threading.Thread): elif now - self.capture_thread.current_frame.value > 20: self.detect_status.send("offline", now) self.camera_fps.value = 0 - self.logger.info( - f"No frames received from {self.config.name} in 20 seconds. Exiting ffmpeg..." - ) if can_restart: + self.logger.info( + f"No frames received from {self.config.name} in 20 seconds. Exiting ffmpeg..." + ) self.reset_capture_thread() last_restart_time = now else: diff --git a/web/src/components/player/PreviewPlayer.tsx b/web/src/components/player/PreviewPlayer.tsx index 6a11942b30..0c89294703 100644 --- a/web/src/components/player/PreviewPlayer.tsx +++ b/web/src/components/player/PreviewPlayer.tsx @@ -332,7 +332,9 @@ function PreviewVideoPlayer({ {t("noPreviewFoundFor", { cameraName: cameraName })} )} - {firstLoad && } + {firstLoad && ( + + )} ); } @@ -555,7 +557,9 @@ function PreviewFramesPlayer({ {t("noPreviewFoundFor", { cameraName: cameraName })} )} - {firstLoad && } + {firstLoad && ( + + )} ); }