From addfa2a32dc2f539eaedf95eb42addfa71a8f601 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Tue, 24 Nov 2020 08:09:16 -0600 Subject: [PATCH] manage events for unlisted cameras --- frigate/config.py | 8 +++++- frigate/events.py | 54 +++++++++++++++++++++++++++++++------ frigate/test/test_config.py | 1 - 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/frigate/config.py b/frigate/config.py index 362f0e7aa..d706bb7c5 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -251,6 +251,7 @@ class SaveClipsConfig(): self._max_seconds = config['max_seconds'] self._clips_dir = config['clips_dir'] self._cache_dir = config['cache_dir'] + self._retain = SaveClipsRetainConfig(config['retain'], config['retain']) @property def max_seconds(self): @@ -264,11 +265,16 @@ class SaveClipsConfig(): def cache_dir(self): return self._cache_dir + @property + def retain(self): + return self._retain + def to_dict(self): return { 'max_seconds': self.max_seconds, 'clips_dir': self.clips_dir, - 'cache_dir': self.cache_dir + 'cache_dir': self.cache_dir, + 'retain': self.retain.to_dict() } class FfmpegConfig(): diff --git a/frigate/events.py b/frigate/events.py index 1d469e5b8..27ca2a577 100644 --- a/frigate/events.py +++ b/frigate/events.py @@ -14,6 +14,8 @@ import psutil from frigate.config import FrigateConfig from frigate.models import Event +from peewee import fn + logger = logging.getLogger(__name__) class EventProcessor(threading.Thread): @@ -204,6 +206,48 @@ class EventCleanup(threading.Thread): logger.info(f"Exiting event cleanup...") break + # only expire events every 10 minutes, but check for stop events every 10 seconds + counter = counter + 1 + if counter < 60: + continue + counter = 0 + + camera_keys = list(self.config.cameras.keys()) + + # Expire events from unlisted cameras based on the global config + retain_config = self.config.save_clips.retain + + distinct_labels = (Event.select(Event.label) + .where(Event.camera.not_in(camera_keys)) + .distinct()) + + # loop over object types in db + for l in distinct_labels: + # get expiration time for this label + expire_days = retain_config.objects.get(l.label, retain_config.default) + expire_after = (datetime.datetime.now() - datetime.timedelta(days=expire_days)).timestamp() + # grab all events after specific time + expired_events = ( + Event.select() + .where(Event.camera.not_in(camera_keys), + Event.start_time < expire_after, + Event.label == l.label) + ) + # delete the grabbed clips from disk + for event in expired_events: + clip_name = f"{event.camera}-{event.id}" + clip = Path(f"{os.path.join(self.clips_dir, clip_name)}.mp4") + clip.unlink(missing_ok=True) + # delete the event for this type from the db + delete_query = ( + Event.delete() + .where(Event.camera.not_in(camera_keys), + Event.start_time < expire_after, + Event.label == l.label) + ) + delete_query.execute() + + # Expire events from cameras based on the camera config for name, camera in self.config.cameras.items(): retain_config = camera.save_clips.retain # get distinct objects in database for this camera @@ -215,11 +259,11 @@ class EventCleanup(threading.Thread): for l in distinct_labels: # get expiration time for this label expire_days = retain_config.objects.get(l.label, retain_config.default) - expire_after = datetime.datetime.now() - datetime.timedelta(days=expire_days) + expire_after = (datetime.datetime.now() - datetime.timedelta(days=expire_days)).timestamp() # grab all events after specific time expired_events = ( Event.select() - .where( Event.camera == name, + .where(Event.camera == name, Event.start_time < expire_after, Event.label == l.label) ) @@ -238,9 +282,3 @@ class EventCleanup(threading.Thread): delete_query.execute() time.sleep(10) - - # only expire events every 10 minutes, but check for stop events every 10 seconds - counter += 1 - if counter < 60: - continue - counter = 0 diff --git a/frigate/test/test_config.py b/frigate/test/test_config.py index 6e16411a7..6f33741c7 100644 --- a/frigate/test/test_config.py +++ b/frigate/test/test_config.py @@ -201,7 +201,6 @@ class TestConfig(TestCase): } } frigate_config = FrigateConfig(config=config) - print(json.dumps(frigate_config.to_dict(), indent=2)) assert(frigate_config.cameras['back'].save_clips.retain.objects['person'] == 30) if __name__ == '__main__':