mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-26 19:06:11 +01:00
Save previews when restarting (#10261)
This commit is contained in:
parent
a174d0000f
commit
7be2923d2d
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
import threading
|
import threading
|
||||||
from typing import Optional
|
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.detections_updater import DetectionSubscriber, DetectionTypeEnum
|
||||||
from frigate.comms.ws import WebSocket
|
from frigate.comms.ws import WebSocket
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import FrigateConfig
|
||||||
|
from frigate.const import CACHE_DIR, CLIPS_DIR
|
||||||
from frigate.output.birdseye import Birdseye
|
from frigate.output.birdseye import Birdseye
|
||||||
from frigate.output.camera import JsmpegCamera
|
from frigate.output.camera import JsmpegCamera
|
||||||
from frigate.output.preview import PreviewRecorder
|
from frigate.output.preview import PreviewRecorder
|
||||||
@ -61,6 +64,8 @@ def output_frames(
|
|||||||
birdseye: Optional[Birdseye] = None
|
birdseye: Optional[Birdseye] = None
|
||||||
preview_recorders: dict[str, PreviewRecorder] = {}
|
preview_recorders: dict[str, PreviewRecorder] = {}
|
||||||
|
|
||||||
|
move_preview_frames("cache")
|
||||||
|
|
||||||
for camera, cam_config in config.cameras.items():
|
for camera, cam_config in config.cameras.items():
|
||||||
if not cam_config.enabled:
|
if not cam_config.enabled:
|
||||||
continue
|
continue
|
||||||
@ -151,6 +156,8 @@ def output_frames(
|
|||||||
for preview in preview_recorders.values():
|
for preview in preview_recorders.values():
|
||||||
preview.stop()
|
preview.stop()
|
||||||
|
|
||||||
|
move_preview_frames("clips")
|
||||||
|
|
||||||
if birdseye is not None:
|
if birdseye is not None:
|
||||||
birdseye.stop()
|
birdseye.stop()
|
||||||
|
|
||||||
@ -160,3 +167,16 @@ def output_frames(
|
|||||||
websocket_server.shutdown()
|
websocket_server.shutdown()
|
||||||
websocket_thread.join()
|
websocket_thread.join()
|
||||||
logger.info("exiting output process...")
|
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)
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import subprocess as sp
|
import subprocess as sp
|
||||||
import threading
|
import threading
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -26,6 +25,7 @@ from frigate.util.image import copy_yuv_to_position, get_yuv_crop
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
FOLDER_PREVIEW_FRAMES = "preview_frames"
|
FOLDER_PREVIEW_FRAMES = "preview_frames"
|
||||||
|
PREVIEW_CACHE_DIR = os.path.join(CACHE_DIR, FOLDER_PREVIEW_FRAMES)
|
||||||
PREVIEW_SEGMENT_DURATION = 3600 # one hour
|
PREVIEW_SEGMENT_DURATION = 3600 # one hour
|
||||||
# important to have lower keyframe to maintain scrubbing performance
|
# important to have lower keyframe to maintain scrubbing performance
|
||||||
PREVIEW_KEYFRAME_INTERVAL = 60
|
PREVIEW_KEYFRAME_INTERVAL = 60
|
||||||
@ -163,11 +163,37 @@ class PreviewRecorder:
|
|||||||
.timestamp()
|
.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(
|
Path(os.path.join(CLIPS_DIR, f"previews/{config.name}")).mkdir(
|
||||||
parents=True, exist_ok=True
|
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(
|
def should_write_frame(
|
||||||
self,
|
self,
|
||||||
current_tracked_objects: list[dict[str, any]],
|
current_tracked_objects: list[dict[str, any]],
|
||||||
@ -269,11 +295,6 @@ class PreviewRecorder:
|
|||||||
self.write_frame_to_cache(frame_time, frame)
|
self.write_frame_to_cache(frame_time, frame)
|
||||||
|
|
||||||
def stop(self) -> None:
|
def stop(self) -> None:
|
||||||
try:
|
|
||||||
shutil.rmtree(os.path.join(CACHE_DIR, FOLDER_PREVIEW_FRAMES))
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.requestor.stop()
|
self.requestor.stop()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user