Save previews when restarting (#10261)

This commit is contained in:
Nicolas Mowen 2024-03-05 12:56:38 -07:00 committed by GitHub
parent a174d0000f
commit 7be2923d2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 7 deletions

View File

@ -2,6 +2,8 @@
import logging
import multiprocessing as mp
import os
import shutil
import signal
import threading
from typing import Optional
@ -18,6 +20,7 @@ from ws4py.server.wsgiutils import WebSocketWSGIApplication
from frigate.comms.detections_updater import DetectionSubscriber, DetectionTypeEnum
from frigate.comms.ws import WebSocket
from frigate.config import FrigateConfig
from frigate.const import CACHE_DIR, CLIPS_DIR
from frigate.output.birdseye import Birdseye
from frigate.output.camera import JsmpegCamera
from frigate.output.preview import PreviewRecorder
@ -61,6 +64,8 @@ def output_frames(
birdseye: Optional[Birdseye] = None
preview_recorders: dict[str, PreviewRecorder] = {}
move_preview_frames("cache")
for camera, cam_config in config.cameras.items():
if not cam_config.enabled:
continue
@ -151,6 +156,8 @@ def output_frames(
for preview in preview_recorders.values():
preview.stop()
move_preview_frames("clips")
if birdseye is not None:
birdseye.stop()
@ -160,3 +167,16 @@ def output_frames(
websocket_server.shutdown()
websocket_thread.join()
logger.info("exiting output process...")
def move_preview_frames(loc: str):
preview_holdover = os.path.join(CLIPS_DIR, "preview_restart_cache")
preview_cache = os.path.join(CACHE_DIR, "preview_frames")
if loc == "clips":
shutil.move(preview_cache, preview_holdover)
elif loc == "cache":
if not os.path.exists(preview_holdover):
return
shutil.move(preview_holdover, preview_cache)

View File

@ -3,7 +3,6 @@
import datetime
import logging
import os
import shutil
import subprocess as sp
import threading
from pathlib import Path
@ -26,6 +25,7 @@ from frigate.util.image import copy_yuv_to_position, get_yuv_crop
logger = logging.getLogger(__name__)
FOLDER_PREVIEW_FRAMES = "preview_frames"
PREVIEW_CACHE_DIR = os.path.join(CACHE_DIR, FOLDER_PREVIEW_FRAMES)
PREVIEW_SEGMENT_DURATION = 3600 # one hour
# important to have lower keyframe to maintain scrubbing performance
PREVIEW_KEYFRAME_INTERVAL = 60
@ -163,11 +163,37 @@ class PreviewRecorder:
.timestamp()
)
Path(os.path.join(CACHE_DIR, "preview_frames")).mkdir(exist_ok=True)
Path(PREVIEW_CACHE_DIR).mkdir(exist_ok=True)
Path(os.path.join(CLIPS_DIR, f"previews/{config.name}")).mkdir(
parents=True, exist_ok=True
)
# check for existing items in cache
start_ts = (
datetime.datetime.now()
.replace(minute=0, second=0, microsecond=0)
.timestamp()
)
file_start = f"preview_{config.name}"
start_file = f"{file_start}-{start_ts}.jpg"
for file in sorted(os.listdir(os.path.join(CACHE_DIR, FOLDER_PREVIEW_FRAMES))):
if not file.startswith(file_start):
continue
if file < start_file:
os.unlink(os.path.join(PREVIEW_CACHE_DIR, file))
continue
ts = float(file.split("-")[1][:-4])
if self.start_time == 0:
self.start_time = ts
self.last_output_time = ts
self.output_frames.append(ts)
def should_write_frame(
self,
current_tracked_objects: list[dict[str, any]],
@ -269,11 +295,6 @@ class PreviewRecorder:
self.write_frame_to_cache(frame_time, frame)
def stop(self) -> None:
try:
shutil.rmtree(os.path.join(CACHE_DIR, FOLDER_PREVIEW_FRAMES))
except FileNotFoundError:
pass
self.requestor.stop()