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
This commit is contained in:
Josh Hawkins
2026-10-25 18:13:00 -05:00
committed by GitHub
parent 7738f022e7
commit 7d4b87946e
3 changed files with 18 additions and 11 deletions
+6 -3
View File
@@ -2,10 +2,11 @@
import logging import logging
import queue import queue
import random
import threading import threading
import time import time
from collections import deque from collections import deque
from datetime import UTC, datetime from datetime import UTC, datetime, timedelta
from multiprocessing import Queue from multiprocessing import Queue
from multiprocessing.synchronize import Event as MpEvent from multiprocessing.synchronize import Event as MpEvent
from typing import Any from typing import Any
@@ -255,7 +256,9 @@ def process_frames(
region_grid: list[list[dict[str, Any]]], region_grid: list[list[dict[str, Any]]],
exit_on_empty: bool = False, 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( config_subscriber = CameraConfigUpdateSubscriber(
None, None,
{camera_config.name: camera_config}, {camera_config.name: camera_config},
@@ -344,7 +347,7 @@ def process_frames(
if updated_grid: if updated_grid:
region_grid = 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: try:
if exit_on_empty: if exit_on_empty:
+2 -2
View File
@@ -474,10 +474,10 @@ class CameraWatchdog(threading.Thread):
if not self.capture_thread.is_alive(): if not self.capture_thread.is_alive():
self.detect_status.send("offline", now) self.detect_status.send("offline", now)
self.camera_fps.value = 0 self.camera_fps.value = 0
if can_restart:
self.logger.error( self.logger.error(
f"Ffmpeg process crashed unexpectedly for {self.config.name}." f"Ffmpeg process crashed unexpectedly for {self.config.name}."
) )
if can_restart:
self.reset_capture_thread(terminate=False) self.reset_capture_thread(terminate=False)
last_restart_time = now last_restart_time = now
elif self.camera_fps.value >= (self.config.detect.fps + 10): 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: elif now - self.capture_thread.current_frame.value > 20:
self.detect_status.send("offline", now) self.detect_status.send("offline", now)
self.camera_fps.value = 0 self.camera_fps.value = 0
if can_restart:
self.logger.info( self.logger.info(
f"No frames received from {self.config.name} in 20 seconds. Exiting ffmpeg..." f"No frames received from {self.config.name} in 20 seconds. Exiting ffmpeg..."
) )
if can_restart:
self.reset_capture_thread() self.reset_capture_thread()
last_restart_time = now last_restart_time = now
else: else:
+6 -2
View File
@@ -332,7 +332,9 @@ function PreviewVideoPlayer({
{t("noPreviewFoundFor", { cameraName: cameraName })} {t("noPreviewFoundFor", { cameraName: cameraName })}
</div> </div>
)} )}
{firstLoad && <Skeleton className="absolute aspect-video size-full" />} {firstLoad && (
<Skeleton className="absolute aspect-video size-full rounded-lg md:rounded-2xl" />
)}
</div> </div>
); );
} }
@@ -555,7 +557,9 @@ function PreviewFramesPlayer({
{t("noPreviewFoundFor", { cameraName: cameraName })} {t("noPreviewFoundFor", { cameraName: cameraName })}
</div> </div>
)} )}
{firstLoad && <Skeleton className="absolute aspect-video size-full" />} {firstLoad && (
<Skeleton className="absolute aspect-video size-full rounded-lg md:rounded-2xl" />
)}
</div> </div>
); );
} }