diff --git a/frigate/http.py b/frigate/http.py index f8d3e6325..57517f168 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -1,6 +1,7 @@ import base64 from datetime import datetime, timedelta import copy +import glob import logging import json import os @@ -62,6 +63,7 @@ def create_app( app.stats_tracking = stats_tracking app.detected_frames_processor = detected_frames_processor app.plus_api = plus_api + app.camera_error_image = None app.register_blueprint(bp) @@ -657,8 +659,20 @@ def latest_frame(camera_name): frame = current_app.detected_frames_processor.get_current_frame( camera_name, draw_options ) - if frame is None: - frame = np.zeros((720, 1280, 3), np.uint8) + + if frame is None or datetime.now().timestamp() > ( + current_app.detected_frames_processor.get_current_frame_time(camera_name) + + 10 + ): + if current_app.camera_error_image is None: + error_image = glob.glob("/opt/frigate/frigate/images/camera-error.jpg") + + if len(error_image) > 0: + current_app.camera_error_image = cv2.imread( + error_image[0], cv2.IMREAD_UNCHANGED + ) + + frame = current_app.camera_error_image height = int(request.args.get("h", str(frame.shape[0]))) width = int(height * frame.shape[1] / frame.shape[0]) diff --git a/frigate/birdseye.png b/frigate/images/birdseye.png similarity index 100% rename from frigate/birdseye.png rename to frigate/images/birdseye.png diff --git a/frigate/images/camera-error.jpg b/frigate/images/camera-error.jpg new file mode 100644 index 000000000..ace648fde Binary files /dev/null and b/frigate/images/camera-error.jpg differ diff --git a/frigate/object_processing.py b/frigate/object_processing.py index 4ea3b5e6c..752e2e788 100644 --- a/frigate/object_processing.py +++ b/frigate/object_processing.py @@ -882,6 +882,10 @@ class TrackedObjectProcessor(threading.Thread): def get_current_frame(self, camera, draw_options={}): return self.camera_states[camera].get_current_frame(draw_options) + def get_current_frame_time(self, camera) -> int: + """Returns the latest frame time for a given camera.""" + return self.camera_states[camera].current_frame_time + def run(self): while not self.stop_event.is_set(): try: diff --git a/frigate/output.py b/frigate/output.py index bb088ffff..865a8d367 100644 --- a/frigate/output.py +++ b/frigate/output.py @@ -7,7 +7,6 @@ import queue import signal import subprocess as sp import threading -from multiprocessing import shared_memory from wsgiref.simple_server import make_server import cv2 @@ -113,7 +112,7 @@ class BirdsEyeFrameManager: birdseye_logo = cv2.imread(custom_logo_files[0], cv2.IMREAD_UNCHANGED) if birdseye_logo is None: - logo_files = glob.glob("/opt/frigate/frigate/birdseye.png") + logo_files = glob.glob("/opt/frigate/frigate/images/birdseye.png") if len(logo_files) > 0: birdseye_logo = cv2.imread(logo_files[0], cv2.IMREAD_UNCHANGED) diff --git a/frigate/video.py b/frigate/video.py index bbb5dd866..21eed9dac 100755 --- a/frigate/video.py +++ b/frigate/video.py @@ -242,6 +242,7 @@ class CameraWatchdog(threading.Thread): now = datetime.datetime.now().timestamp() if not self.capture_thread.is_alive(): + self.camera_fps.value = 0 self.logger.error( f"Ffmpeg process crashed unexpectedly for {self.camera_name}." ) @@ -251,6 +252,7 @@ class CameraWatchdog(threading.Thread): self.logpipe.dump() self.start_ffmpeg_detect() elif now - self.capture_thread.current_frame.value > 20: + self.camera_fps.value = 0 self.logger.info( f"No frames received from {self.camera_name} in 20 seconds. Exiting ffmpeg..." )