Move recording management to separate process (#6248)

* Move recordings management to own process and ensure db multiprocess access

* remove reference to old threads

* Cleanup directory remover

* Mypy fixes

* Fix mypy

* Add support back for setting record via MQTT and WS

* Formatting

* Fix rebase issue
This commit is contained in:
Nicolas Mowen
2023-04-26 07:25:26 -06:00
committed by GitHub
parent 6dc82b6cef
commit e451f44ced
8 changed files with 402 additions and 294 deletions

View File

@@ -28,14 +28,14 @@ from frigate.object_processing import TrackedObjectProcessor
from frigate.output import output_frames
from frigate.plus import PlusApi
from frigate.ptz import OnvifController
from frigate.record import RecordingCleanup, RecordingMaintainer
from frigate.record.record import manage_recordings
from frigate.stats import StatsEmitter, stats_init
from frigate.storage import StorageMaintainer
from frigate.timeline import TimelineProcessor
from frigate.version import VERSION
from frigate.video import capture_camera, track_camera
from frigate.watchdog import FrigateWatchdog
from frigate.types import CameraMetricsTypes
from frigate.types import CameraMetricsTypes, RecordMetricsTypes
logger = logging.getLogger(__name__)
@@ -50,6 +50,7 @@ class FrigateApp:
self.log_queue: Queue = mp.Queue()
self.plus_api = PlusApi()
self.camera_metrics: dict[str, CameraMetricsTypes] = {}
self.record_metrics: dict[str, RecordMetricsTypes] = {}
def set_environment_vars(self) -> None:
for key, value in self.config.environment_vars.items():
@@ -109,6 +110,11 @@ class FrigateApp:
"capture_process": None,
"process": None,
}
self.record_metrics[camera_name] = {
"record_enabled": mp.Value(
"i", self.config.cameras[camera_name].record.enabled
)
}
def set_log_levels(self) -> None:
logging.getLogger().setLevel(self.config.logger.default.value.upper())
@@ -158,6 +164,20 @@ class FrigateApp:
migrate_db.close()
def init_recording_manager(self) -> None:
recording_process = mp.Process(
target=manage_recordings,
name="recording_manager",
args=(self.config, self.recordings_info_queue, self.record_metrics),
)
recording_process.daemon = True
self.recording_process = recording_process
recording_process.start()
logger.info(f"Recording process started: {recording_process.pid}")
def bind_database(self) -> None:
"""Bind db to the main process."""
# NOTE: all db accessing processes need to be created before the db can be bound to the main process
self.db = SqliteQueueDatabase(self.config.database.path)
models = [Event, Recordings, Timeline]
self.db.bind(models)
@@ -189,7 +209,11 @@ class FrigateApp:
comms.append(WebSocketClient(self.config))
self.dispatcher = Dispatcher(
self.config, self.onvif_controller, self.camera_metrics, comms
self.config,
self.onvif_controller,
self.camera_metrics,
self.record_metrics,
comms,
)
def start_detectors(self) -> None:
@@ -318,16 +342,6 @@ class FrigateApp:
self.event_cleanup = EventCleanup(self.config, self.stop_event)
self.event_cleanup.start()
def start_recording_maintainer(self) -> None:
self.recording_maintainer = RecordingMaintainer(
self.config, self.recordings_info_queue, self.stop_event
)
self.recording_maintainer.start()
def start_recording_cleanup(self) -> None:
self.recording_cleanup = RecordingCleanup(self.config, self.stop_event)
self.recording_cleanup.start()
def start_storage_maintainer(self) -> None:
self.storage_maintainer = StorageMaintainer(self.config, self.stop_event)
self.storage_maintainer.start()
@@ -390,6 +404,8 @@ class FrigateApp:
self.init_queues()
self.init_database()
self.init_onvif()
self.init_recording_manager()
self.bind_database()
self.init_dispatcher()
except Exception as e:
print(e)
@@ -406,8 +422,6 @@ class FrigateApp:
self.start_timeline_processor()
self.start_event_processor()
self.start_event_cleanup()
self.start_recording_maintainer()
self.start_recording_cleanup()
self.start_stats_emitter()
self.start_watchdog()
self.check_shm()
@@ -443,8 +457,6 @@ class FrigateApp:
self.detected_frames_processor.join()
self.event_processor.join()
self.event_cleanup.join()
self.recording_maintainer.join()
self.recording_cleanup.join()
self.stats_emitter.join()
self.frigate_watchdog.join()
self.db.stop()