mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-01-07 00:06:57 +01:00
allow defining required zones for snapshots/clips/mqtt
This commit is contained in:
parent
9592d95599
commit
121ea37825
@ -139,6 +139,8 @@ clips:
|
||||
# Optional: Objects to save clips for. (default: all tracked objects)
|
||||
objects:
|
||||
- person
|
||||
# Optional: Restrict clips to objects that entered any of the listed zones (default: no required zones)
|
||||
required_zones: []
|
||||
# Optional: Camera override for retention settings (default: global values)
|
||||
retain:
|
||||
# Required: Default retention days (default: shown below)
|
||||
@ -166,6 +168,8 @@ snapshots:
|
||||
crop: False
|
||||
# Optional: height to resize the snapshot to (default: original size)
|
||||
height: 175
|
||||
# Optional: Restrict snapshots to objects that entered any of the listed zones (default: no required zones)
|
||||
required_zones: []
|
||||
# Optional: Camera override for retention settings (default: global values)
|
||||
retain:
|
||||
# Required: Default retention days (default: shown below)
|
||||
@ -226,12 +230,6 @@ cameras:
|
||||
# Optional: stream specific input args (default: inherit)
|
||||
input_args:
|
||||
|
||||
# Optional: camera specific global args (default: inherit)
|
||||
global_args:
|
||||
# Optional: camera specific hwaccel args (default: inherit)
|
||||
hwaccel_args:
|
||||
# Optional: camera specific input args (default: inherit)
|
||||
input_args:
|
||||
# Optional: camera specific output args (default: inherit)
|
||||
output_args:
|
||||
|
||||
@ -291,6 +289,8 @@ cameras:
|
||||
# Optional: Objects to save clips for. (default: all tracked objects)
|
||||
objects:
|
||||
- person
|
||||
# Optional: Restrict clips to objects that entered any of the listed zones (default: no required zones)
|
||||
required_zones: []
|
||||
# Optional: Camera override for retention settings (default: global values)
|
||||
retain:
|
||||
# Required: Default retention days (default: shown below)
|
||||
@ -324,6 +324,8 @@ cameras:
|
||||
crop: False
|
||||
# Optional: height to resize the snapshot to (default: original size)
|
||||
height: 175
|
||||
# Optional: Restrict snapshots to objects that entered any of the listed zones (default: no required zones)
|
||||
required_zones: []
|
||||
# Optional: Camera override for retention settings (default: global values)
|
||||
retain:
|
||||
# Required: Default retention days (default: shown below)
|
||||
@ -346,6 +348,8 @@ cameras:
|
||||
crop: True
|
||||
# Optional: height to resize the snapshot to (default: shown below)
|
||||
height: 270
|
||||
# Optional: Restrict mqtt messages to objects that entered any of the listed zones (default: no required zones)
|
||||
required_zones: []
|
||||
|
||||
# Optional: Camera level object filters config.
|
||||
objects:
|
||||
|
@ -198,6 +198,7 @@ CAMERAS_SCHEMA = vol.Schema(vol.All(
|
||||
vol.Optional('enabled', default=False): bool,
|
||||
vol.Optional('pre_capture', default=5): int,
|
||||
vol.Optional('post_capture', default=5): int,
|
||||
vol.Optional('required_zones', default=[]): [str],
|
||||
'objects': [str],
|
||||
vol.Optional('retain', default={}): RETAIN_SCHEMA,
|
||||
},
|
||||
@ -213,6 +214,7 @@ CAMERAS_SCHEMA = vol.Schema(vol.All(
|
||||
vol.Optional('timestamp', default=False): bool,
|
||||
vol.Optional('bounding_box', default=False): bool,
|
||||
vol.Optional('crop', default=False): bool,
|
||||
vol.Optional('required_zones', default=[]): [str],
|
||||
'height': int,
|
||||
vol.Optional('retain', default={}): RETAIN_SCHEMA,
|
||||
},
|
||||
@ -221,7 +223,8 @@ CAMERAS_SCHEMA = vol.Schema(vol.All(
|
||||
vol.Optional('timestamp', default=True): bool,
|
||||
vol.Optional('bounding_box', default=True): bool,
|
||||
vol.Optional('crop', default=True): bool,
|
||||
vol.Optional('height', default=270): int
|
||||
vol.Optional('height', default=270): int,
|
||||
vol.Optional('required_zones', default=[]): [str],
|
||||
},
|
||||
vol.Optional('objects', default={}): OBJECTS_SCHEMA,
|
||||
vol.Optional('motion', default={}): MOTION_SCHEMA,
|
||||
@ -570,6 +573,7 @@ class CameraSnapshotsConfig():
|
||||
self._crop = config['crop']
|
||||
self._height = config.get('height')
|
||||
self._retain = RetainConfig(global_config['snapshots']['retain'], config['retain'])
|
||||
self._required_zones = config['required_zones']
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
@ -594,6 +598,10 @@ class CameraSnapshotsConfig():
|
||||
@property
|
||||
def retain(self):
|
||||
return self._retain
|
||||
|
||||
@property
|
||||
def required_zones(self):
|
||||
return self._required_zones
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
@ -602,7 +610,8 @@ class CameraSnapshotsConfig():
|
||||
'bounding_box': self.bounding_box,
|
||||
'crop': self.crop,
|
||||
'height': self.height,
|
||||
'retain': self.retain.to_dict()
|
||||
'retain': self.retain.to_dict(),
|
||||
'required_zones': self.required_zones
|
||||
}
|
||||
|
||||
class CameraMqttConfig():
|
||||
@ -612,6 +621,7 @@ class CameraMqttConfig():
|
||||
self._bounding_box = config['bounding_box']
|
||||
self._crop = config['crop']
|
||||
self._height = config.get('height')
|
||||
self._required_zones = config['required_zones']
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
@ -633,13 +643,18 @@ class CameraMqttConfig():
|
||||
def height(self):
|
||||
return self._height
|
||||
|
||||
@property
|
||||
def required_zones(self):
|
||||
return self._required_zones
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'enabled': self.enabled,
|
||||
'timestamp': self.timestamp,
|
||||
'bounding_box': self.bounding_box,
|
||||
'crop': self.crop,
|
||||
'height': self.height
|
||||
'height': self.height,
|
||||
'required_zones': self.required_zones
|
||||
}
|
||||
|
||||
class CameraClipsConfig():
|
||||
@ -649,6 +664,7 @@ class CameraClipsConfig():
|
||||
self._post_capture = config['post_capture']
|
||||
self._objects = config.get('objects')
|
||||
self._retain = RetainConfig(global_config['clips']['retain'], config['retain'])
|
||||
self._required_zones = config['required_zones']
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
@ -670,13 +686,18 @@ class CameraClipsConfig():
|
||||
def retain(self):
|
||||
return self._retain
|
||||
|
||||
@property
|
||||
def required_zones(self):
|
||||
return self._required_zones
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'enabled': self.enabled,
|
||||
'pre_capture': self.pre_capture,
|
||||
'post_capture': self.post_capture,
|
||||
'objects': self.objects,
|
||||
'retain': self.retain.to_dict()
|
||||
'retain': self.retain.to_dict(),
|
||||
'required_zones': self.required_zones
|
||||
}
|
||||
|
||||
class CameraRtmpConfig():
|
||||
|
@ -31,6 +31,18 @@ class EventProcessor(threading.Thread):
|
||||
self.event_processed_queue = event_processed_queue
|
||||
self.events_in_process = {}
|
||||
self.stop_event = stop_event
|
||||
|
||||
def should_create_clip(self, camera, event_data):
|
||||
if event_data['false_positive']:
|
||||
return False
|
||||
|
||||
# if there are required zones and there is no overlap
|
||||
required_zones = self.config.cameras[camera].clips.required_zones
|
||||
if len(required_zones) > 0 and not set(event_data['entered_zones']) & set(required_zones):
|
||||
logger.debug(f"Not creating clip for {event_data['id']} because it did not enter required zones")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def refresh_cache(self):
|
||||
cached_files = os.listdir(CACHE_DIR)
|
||||
@ -193,7 +205,7 @@ class EventProcessor(threading.Thread):
|
||||
if event_type == 'end':
|
||||
clips_config = self.config.cameras[camera].clips
|
||||
|
||||
if not event_data['false_positive']:
|
||||
if self.should_create_clip(camera, event_data):
|
||||
clip_created = False
|
||||
if clips_config.enabled and (clips_config.objects is None or event_data['label'] in clips_config.objects):
|
||||
clip_created = self.create_clip(camera, event_data, clips_config.pre_capture, clips_config.post_capture)
|
||||
|
@ -454,7 +454,7 @@ class TrackedObjectProcessor(threading.Thread):
|
||||
message = { 'before': obj.previous, 'after': obj.to_dict(), 'type': 'end' }
|
||||
self.client.publish(f"{self.topic_prefix}/events", json.dumps(message), retain=False)
|
||||
# write snapshot to disk if enabled
|
||||
if snapshot_config.enabled:
|
||||
if snapshot_config.enabled and self.should_save_snapshot(camera, obj):
|
||||
jpg_bytes = obj.get_jpg_bytes(
|
||||
timestamp=snapshot_config.timestamp,
|
||||
bounding_box=snapshot_config.bounding_box,
|
||||
@ -468,7 +468,7 @@ class TrackedObjectProcessor(threading.Thread):
|
||||
|
||||
def snapshot(camera, obj: TrackedObject, current_frame_time):
|
||||
mqtt_config = self.config.cameras[camera].mqtt
|
||||
if mqtt_config.enabled:
|
||||
if mqtt_config.enabled and self.should_mqtt_snapshot(camera, obj):
|
||||
jpg_bytes = obj.get_jpg_bytes(
|
||||
timestamp=mqtt_config.timestamp,
|
||||
bounding_box=mqtt_config.bounding_box,
|
||||
@ -499,6 +499,24 @@ class TrackedObjectProcessor(threading.Thread):
|
||||
# }
|
||||
self.zone_data = defaultdict(lambda: defaultdict(lambda: {}))
|
||||
|
||||
def should_save_snapshot(self, camera, obj: TrackedObject):
|
||||
# if there are required zones and there is no overlap
|
||||
required_zones = self.config.cameras[camera].snapshots.required_zones
|
||||
if len(required_zones) > 0 and not obj.entered_zones & set(required_zones):
|
||||
logger.debug(f"Not creating snapshot for {obj.obj_data['id']} because it did not enter required zones")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def should_mqtt_snapshot(self, camera, obj: TrackedObject):
|
||||
# if there are required zones and there is no overlap
|
||||
required_zones = self.config.cameras[camera].mqtt.required_zones
|
||||
if len(required_zones) > 0 and not obj.entered_zones & set(required_zones):
|
||||
logger.debug(f"Not sending mqtt for {obj.obj_data['id']} because it did not enter required zones")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_best(self, camera, label):
|
||||
# TODO: need a lock here
|
||||
camera_state = self.camera_states[camera]
|
||||
|
Loading…
Reference in New Issue
Block a user