From 5d0984998df93dc449985220a110352c12591061 Mon Sep 17 00:00:00 2001 From: zacho112 Date: Thu, 3 Jun 2021 18:50:55 +0200 Subject: [PATCH 01/71] Update detectors.md Include how to use the native Coral on the Coral Dev Board --- docs/docs/configuration/detectors.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/docs/configuration/detectors.md b/docs/docs/configuration/detectors.md index a7bbdab79..3ff3c9709 100644 --- a/docs/docs/configuration/detectors.md +++ b/docs/docs/configuration/detectors.md @@ -42,6 +42,15 @@ detectors: device: pci:1 ``` +Native Corals (Dev Board): + +```yaml +detectors: + coral: + type: edgetpu + device: '' +``` + Mixing Corals: ```yaml From 03e756dd27082ea665be03638a21e5d51ab7f895 Mon Sep 17 00:00:00 2001 From: zacho112 Date: Mon, 14 Jun 2021 19:31:09 +0200 Subject: [PATCH 02/71] Update detectors.md --- docs/docs/configuration/detectors.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/docs/configuration/detectors.md b/docs/docs/configuration/detectors.md index 3ff3c9709..58ec474ef 100644 --- a/docs/docs/configuration/detectors.md +++ b/docs/docs/configuration/detectors.md @@ -30,6 +30,15 @@ detectors: device: usb:1 ``` +Native Coral (Dev Board): + +```yaml +detectors: + coral: + type: edgetpu + device: '' +``` + Multiple PCIE/M.2 Corals: ```yaml @@ -42,15 +51,6 @@ detectors: device: pci:1 ``` -Native Corals (Dev Board): - -```yaml -detectors: - coral: - type: edgetpu - device: '' -``` - Mixing Corals: ```yaml From a4052a9fe5c5630abe234cc6156cff31acdd2e03 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Mon, 21 Jun 2021 17:00:50 +0200 Subject: [PATCH 03/71] Add ability to restart --- frigate/mqtt.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/frigate/mqtt.py b/frigate/mqtt.py index bc10e95c8..dddbf4767 100644 --- a/frigate/mqtt.py +++ b/frigate/mqtt.py @@ -13,6 +13,7 @@ from ws4py.server.wsgiutils import WebSocketWSGIApplication from ws4py.websocket import WebSocket from frigate.config import FrigateConfig +from frigate.util import restart_frigate logger = logging.getLogger(__name__) @@ -88,6 +89,14 @@ def create_mqtt_client(config: FrigateConfig, camera_metrics): state_topic = f"{message.topic[:-4]}/state" client.publish(state_topic, payload, retain=True) + def on_restart_command(client, userdata, message): + payload = message.payload.decode() + if payload == "container": + logger.warning(f"Restart container received via mqtt") + restart_frigate() + else: + logger.warning(f"Received unsupported value at {message.topic}: {payload}") + def on_connect(client, userdata, flags, rc): threading.current_thread().name = "mqtt" if rc != 0: @@ -125,6 +134,10 @@ def create_mqtt_client(config: FrigateConfig, camera_metrics): f"{mqtt_config.topic_prefix}/{name}/detect/set", on_detect_command ) + client.message_callback_add( + f"{mqtt_config.topic_prefix}/restart", on_restart_command + ) + if not mqtt_config.tls_ca_certs is None: if ( not mqtt_config.tls_client_cert is None From 11d8095cdd2598fc1486176faf1fba52c2c19b04 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Mon, 21 Jun 2021 17:03:33 +0200 Subject: [PATCH 04/71] Add ability to restart --- frigate/util.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frigate/util.py b/frigate/util.py index 0ae2848e9..b837edcf5 100755 --- a/frigate/util.py +++ b/frigate/util.py @@ -17,6 +17,7 @@ from typing import AnyStr import cv2 import matplotlib.pyplot as plt import numpy as np +import psutil logger = logging.getLogger(__name__) @@ -518,6 +519,13 @@ def clipped(obj, frame_shape): return False +def restart_frigate(): + for proc in psutil.process_iter(): + if proc.name().startswith("frigate.detector."): + psutil.Process(proc.pid).terminate() + return + + class EventsPerSecond: def __init__(self, max_events=1000): self._start = None From 3d28d8cee26889c9d2330e00742df502724dcb3b Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Mon, 21 Jun 2021 17:04:55 +0200 Subject: [PATCH 05/71] Add ability to restart --- web/src/icons/FrigateRestart.jsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 web/src/icons/FrigateRestart.jsx diff --git a/web/src/icons/FrigateRestart.jsx b/web/src/icons/FrigateRestart.jsx new file mode 100644 index 000000000..bb14e03b4 --- /dev/null +++ b/web/src/icons/FrigateRestart.jsx @@ -0,0 +1,13 @@ +import { h } from 'preact'; +import { memo } from 'preact/compat'; + +export function FrigateRestart({ className = '' }) { + return ( + + + + + ); +} + +export default memo(FrigateRestart); From a2d5754e4be91250f4354010e373fa979bc29203 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Mon, 21 Jun 2021 17:07:14 +0200 Subject: [PATCH 06/71] Add ability to restart --- web/src/api/mqtt.jsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/web/src/api/mqtt.jsx b/web/src/api/mqtt.jsx index 6268b3d62..e0413efdf 100644 --- a/web/src/api/mqtt.jsx +++ b/web/src/api/mqtt.jsx @@ -72,13 +72,14 @@ export function MqttProvider({ return {children}; } -export function useMqtt(watchTopic, publishTopic) { +export function useMqtt(watchTopic, publishTopic, defaultValue = null) { const { state, ws } = useContext(Mqtt); - const value = state[watchTopic] || { payload: null }; + const value = state[watchTopic] || { payload: defaultValue }; const send = useCallback( (payload) => { + payload = payload || defaultValue; ws.send( JSON.stringify({ topic: publishTopic || watchTopic, @@ -118,3 +119,12 @@ export function useSnapshotsState(camera) { } = useMqtt(`${camera}/snapshots/state`, `${camera}/snapshots/set`); return { payload, send, connected }; } + +export function useRestart() { + const { + value: { payload }, + send, + connected, + } = useMqtt(``, `restart`, "container"); + return { send, connected }; +} From 436b10a87bafaea2376a6629ab0f8c92ff4c2c4c Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Mon, 21 Jun 2021 17:11:09 +0200 Subject: [PATCH 07/71] Add ability to restart --- web/src/AppBar.jsx | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/web/src/AppBar.jsx b/web/src/AppBar.jsx index 6a3ff2a72..12da10cf6 100644 --- a/web/src/AppBar.jsx +++ b/web/src/AppBar.jsx @@ -5,12 +5,18 @@ import Menu, { MenuItem, MenuSeparator } from './components/Menu'; import AutoAwesomeIcon from './icons/AutoAwesome'; import LightModeIcon from './icons/LightMode'; import DarkModeIcon from './icons/DarkMode'; +import FrigateRestartIcon from './icons/FrigateRestart'; +import Dialog from './components/Dialog'; import { useDarkMode } from './context'; import { useCallback, useRef, useState } from 'preact/hooks'; +import { useRestart } from './api/mqtt'; export default function AppBar() { const [showMoreMenu, setShowMoreMenu] = useState(false); + const [showDialog, setShowDialog] = useState(false); + const [showDialogWait, setShowDialogWait] = useState(false); const { setDarkMode } = useDarkMode(); + const { send: sendRestart } = useRestart(); const handleSelectDarkMode = useCallback( (value, label) => { @@ -30,6 +36,21 @@ export default function AppBar() { setShowMoreMenu(false); }, [setShowMoreMenu]); + const handleClickRestartDialog = useCallback(() => { + setShowDialog(false); + setShowDialogWait(true); + sendRestart(); + }, [setShowDialog]); + + const handleDismissRestartDialog = () => { + setShowDialog(false); + }; + + const handleRestart = useCallback(() => { + setShowMoreMenu(false); + setShowDialog(true); + }); + return ( @@ -39,7 +60,26 @@ export default function AppBar() { + + + ) : null}, + {showDialog ? ( + + ) : null}, + {showDialogWait ? ( + ) : null} ); From c6e53d0ea82876f4759bacb75d31bef7e5d923d3 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Mon, 21 Jun 2021 17:36:22 +0200 Subject: [PATCH 08/71] Add ability to restart --- frigate/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frigate/util.py b/frigate/util.py index b837edcf5..f0fc9ad94 100755 --- a/frigate/util.py +++ b/frigate/util.py @@ -522,7 +522,7 @@ def clipped(obj, frame_shape): def restart_frigate(): for proc in psutil.process_iter(): if proc.name().startswith("frigate.detector."): - psutil.Process(proc.pid).terminate() + psutil.Process(proc.pid).terminate() return From fe2e32c84f9c42710e95e4c3544f350df62d2058 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Wed, 23 Jun 2021 09:34:08 +0200 Subject: [PATCH 09/71] Add ability to restart --- frigate/util.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/frigate/util.py b/frigate/util.py index f0fc9ad94..dae3845f2 100755 --- a/frigate/util.py +++ b/frigate/util.py @@ -17,7 +17,7 @@ from typing import AnyStr import cv2 import matplotlib.pyplot as plt import numpy as np -import psutil +import os logger = logging.getLogger(__name__) @@ -520,10 +520,7 @@ def clipped(obj, frame_shape): def restart_frigate(): - for proc in psutil.process_iter(): - if proc.name().startswith("frigate.detector."): - psutil.Process(proc.pid).terminate() - return + os.kill(os.getpid(), signal.SIGTERM) class EventsPerSecond: From 955d9e6ec213e59f964a4045c1dc43a18b0368f3 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Wed, 23 Jun 2021 14:38:38 +0200 Subject: [PATCH 10/71] Add ability to restart --- web/src/AppBar.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/AppBar.jsx b/web/src/AppBar.jsx index 12da10cf6..2083db421 100644 --- a/web/src/AppBar.jsx +++ b/web/src/AppBar.jsx @@ -49,7 +49,7 @@ export default function AppBar() { const handleRestart = useCallback(() => { setShowMoreMenu(false); setShowDialog(true); - }); + }, [setShowDialog]); return ( @@ -70,8 +70,8 @@ export default function AppBar() { title="Restart Frigate" text="Are you sure ?" actions={[ - { text: "Yes", color: "red", onClick: handleClickRestartDialog }, - { text: "Cancel", onClick: handleDismissRestartDialog }, + { text: 'Yes' color: 'red', onClick: handleClickRestartDialog }, + { text: 'Cancel', onClick: handleDismissRestartDialog }, ]} /> ) : null}, From 997148250658ee391ebb648a814b025e7d25fc26 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Wed, 23 Jun 2021 14:49:49 +0200 Subject: [PATCH 11/71] Add ability to restart --- web/src/api/mqtt.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/src/api/mqtt.jsx b/web/src/api/mqtt.jsx index e0413efdf..560f8dcce 100644 --- a/web/src/api/mqtt.jsx +++ b/web/src/api/mqtt.jsx @@ -122,9 +122,8 @@ export function useSnapshotsState(camera) { export function useRestart() { const { - value: { payload }, send, connected, - } = useMqtt(``, `restart`, "container"); + } = useMqtt('', 'restart', 'container'); return { send, connected }; } From 04c8b089a50dd596968ecd2139fe26a35f08cb5c Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Wed, 23 Jun 2021 14:50:53 +0200 Subject: [PATCH 12/71] Add ability to restart --- web/src/icons/FrigateRestart.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/icons/FrigateRestart.jsx b/web/src/icons/FrigateRestart.jsx index bb14e03b4..9240678c7 100644 --- a/web/src/icons/FrigateRestart.jsx +++ b/web/src/icons/FrigateRestart.jsx @@ -5,7 +5,7 @@ export function FrigateRestart({ className = '' }) { return ( - + ); } From e1b341788d585e27eab9bf1d7eda4127a8ff5ae2 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Wed, 23 Jun 2021 15:24:57 +0200 Subject: [PATCH 13/71] Add ability to restart --- web/src/AppBar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/AppBar.jsx b/web/src/AppBar.jsx index 2083db421..44b50ab9e 100644 --- a/web/src/AppBar.jsx +++ b/web/src/AppBar.jsx @@ -70,7 +70,7 @@ export default function AppBar() { title="Restart Frigate" text="Are you sure ?" actions={[ - { text: 'Yes' color: 'red', onClick: handleClickRestartDialog }, + { text: 'Yes', color: 'red', onClick: handleClickRestartDialog }, { text: 'Cancel', onClick: handleDismissRestartDialog }, ]} /> From f9add57ed4a9736bcd2d7b30072fa8bec8696073 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Wed, 23 Jun 2021 15:48:56 +0200 Subject: [PATCH 14/71] Add ability to restart I restored the original line as it can be misleading. --- web/src/api/mqtt.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/api/mqtt.jsx b/web/src/api/mqtt.jsx index 560f8dcce..29f6b1634 100644 --- a/web/src/api/mqtt.jsx +++ b/web/src/api/mqtt.jsx @@ -75,7 +75,7 @@ export function MqttProvider({ export function useMqtt(watchTopic, publishTopic, defaultValue = null) { const { state, ws } = useContext(Mqtt); - const value = state[watchTopic] || { payload: defaultValue }; + const value = state[watchTopic] || { payload: null }; const send = useCallback( (payload) => { From fd61ca20b009e6b890a169be97adcff2b7c6268d Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Thu, 24 Jun 2021 08:57:21 +0200 Subject: [PATCH 15/71] Add ability to restart disable warning --- web/src/api/mqtt.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/api/mqtt.jsx b/web/src/api/mqtt.jsx index 29f6b1634..734c55713 100644 --- a/web/src/api/mqtt.jsx +++ b/web/src/api/mqtt.jsx @@ -87,7 +87,7 @@ export function useMqtt(watchTopic, publishTopic, defaultValue = null) { }) ); }, - [ws, watchTopic, publishTopic] + [ws, watchTopic, publishTopic] // eslint-disable-line react-hooks/exhaustive-deps ); return { value, send, connected: state.__connected }; From 9ee2e776fac47c19dc1207f376b49e7194d1f9ba Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Thu, 24 Jun 2021 14:06:27 +0200 Subject: [PATCH 16/71] Add ability to restart --- web/src/AppBar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/AppBar.jsx b/web/src/AppBar.jsx index 44b50ab9e..fe277ced8 100644 --- a/web/src/AppBar.jsx +++ b/web/src/AppBar.jsx @@ -68,7 +68,7 @@ export default function AppBar() { Date: Thu, 24 Jun 2021 15:08:13 +0200 Subject: [PATCH 17/71] Add ability to restart --- web/src/AppBar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/AppBar.jsx b/web/src/AppBar.jsx index fe277ced8..d6812be4a 100644 --- a/web/src/AppBar.jsx +++ b/web/src/AppBar.jsx @@ -40,7 +40,7 @@ export default function AppBar() { setShowDialog(false); setShowDialogWait(true); sendRestart(); - }, [setShowDialog]); + }, [setShowDialog]); // eslint-disable-line react-hooks/exhaustive-deps const handleDismissRestartDialog = () => { setShowDialog(false); From f892a821f5f79e51ee33b89247d7bbb1a59890a1 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Tue, 6 Jul 2021 07:22:17 -0500 Subject: [PATCH 18/71] no need to worry about payload here --- frigate/mqtt.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/frigate/mqtt.py b/frigate/mqtt.py index dddbf4767..ee8aee6cb 100644 --- a/frigate/mqtt.py +++ b/frigate/mqtt.py @@ -90,12 +90,7 @@ def create_mqtt_client(config: FrigateConfig, camera_metrics): client.publish(state_topic, payload, retain=True) def on_restart_command(client, userdata, message): - payload = message.payload.decode() - if payload == "container": - logger.warning(f"Restart container received via mqtt") - restart_frigate() - else: - logger.warning(f"Received unsupported value at {message.topic}: {payload}") + restart_frigate() def on_connect(client, userdata, flags, rc): threading.current_thread().name = "mqtt" @@ -197,7 +192,7 @@ class MqttSocketRelay: json_message = json.loads(message.data.decode("utf-8")) json_message = { "topic": f"{self.topic_prefix}/{json_message['topic']}", - "payload": json_message["payload"], + "payload": json_message.get("payload"), "retain": json_message.get("retain", False), } except Exception as e: From 13c2c582adfee5cbaab23c54e683f78d6398036c Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Tue, 6 Jul 2021 07:22:48 -0500 Subject: [PATCH 19/71] remove default value changes --- web/src/api/mqtt.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/src/api/mqtt.jsx b/web/src/api/mqtt.jsx index 734c55713..b4b15d6fa 100644 --- a/web/src/api/mqtt.jsx +++ b/web/src/api/mqtt.jsx @@ -72,14 +72,13 @@ export function MqttProvider({ return {children}; } -export function useMqtt(watchTopic, publishTopic, defaultValue = null) { +export function useMqtt(watchTopic, publishTopic) { const { state, ws } = useContext(Mqtt); const value = state[watchTopic] || { payload: null }; const send = useCallback( (payload) => { - payload = payload || defaultValue; ws.send( JSON.stringify({ topic: publishTopic || watchTopic, @@ -87,7 +86,7 @@ export function useMqtt(watchTopic, publishTopic, defaultValue = null) { }) ); }, - [ws, watchTopic, publishTopic] // eslint-disable-line react-hooks/exhaustive-deps + [ws, watchTopic, publishTopic] ); return { value, send, connected: state.__connected }; @@ -122,8 +121,9 @@ export function useSnapshotsState(camera) { export function useRestart() { const { + value: { payload }, send, connected, - } = useMqtt('', 'restart', 'container'); - return { send, connected }; + } = useMqtt('restart', 'restart'); + return { payload, send, connected }; } From b1dfee2cf50f3a68172a2d8e3d4a3288b8cb45f9 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Tue, 6 Jul 2021 07:23:00 -0500 Subject: [PATCH 20/71] update docs --- docs/docs/usage/mqtt.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/docs/usage/mqtt.md b/docs/docs/usage/mqtt.md index 27712c124..e061292fa 100644 --- a/docs/docs/usage/mqtt.md +++ b/docs/docs/usage/mqtt.md @@ -11,6 +11,10 @@ Designed to be used as an availability topic with Home Assistant. Possible messa "online": published when frigate is running (on startup) "offline": published right before frigate stops +### `frigate/restart` + +Causes frigate to exit. Docker should be configured to automatically restart the container on exit. + ### `frigate//` Publishes the count of objects for the camera for use as a sensor in Home Assistant. From 3876b00088c132c288dbfe61b96c6b944c48bafd Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Tue, 6 Jul 2021 07:34:39 -0500 Subject: [PATCH 21/71] useCallback here too --- web/src/AppBar.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/AppBar.jsx b/web/src/AppBar.jsx index d6812be4a..8a8183e00 100644 --- a/web/src/AppBar.jsx +++ b/web/src/AppBar.jsx @@ -42,9 +42,9 @@ export default function AppBar() { sendRestart(); }, [setShowDialog]); // eslint-disable-line react-hooks/exhaustive-deps - const handleDismissRestartDialog = () => { + const handleDismissRestartDialog = useCallback(() => { setShowDialog(false); - }; + }, [setShowDialog]); const handleRestart = useCallback(() => { setShowMoreMenu(false); From da2492413f87cfefdfc2b9d1ea6bee5b214a77e9 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Wed, 7 Jul 2021 07:02:36 -0500 Subject: [PATCH 22/71] publish on zone change (fixes #1310) --- frigate/object_processing.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/frigate/object_processing.py b/frigate/object_processing.py index 706d04328..372db8ef7 100644 --- a/frigate/object_processing.py +++ b/frigate/object_processing.py @@ -107,6 +107,7 @@ class TrackedObject: def update(self, current_frame_time, obj_data): significant_update = False + zone_change = False self.obj_data.update(obj_data) # if the object is not in the current frame, add a 0.0 to the score history if self.obj_data["frame_time"] != current_frame_time: @@ -152,10 +153,10 @@ class TrackedObject: # if the zones changed, signal an update if not self.false_positive and set(self.current_zones) != set(current_zones): - significant_update = True + zone_change = True self.current_zones = current_zones - return significant_update + return (significant_update, zone_change) def to_dict(self, include_thumbnail: bool = False): snapshot_time = ( @@ -451,7 +452,9 @@ class CameraState: for id in updated_ids: updated_obj = tracked_objects[id] - significant_update = updated_obj.update(frame_time, current_detections[id]) + significant_update, zone_change = updated_obj.update( + frame_time, current_detections[id] + ) if significant_update: # ensure this frame is stored in the cache @@ -464,11 +467,12 @@ class CameraState: updated_obj.last_updated = frame_time # if it has been more than 5 seconds since the last publish - # and the last update is greater than the last publish + # and the last update is greater than the last publish or + # the object has changed zones if ( frame_time - updated_obj.last_published > 5 and updated_obj.last_updated > updated_obj.last_published - ): + ) or zone_change: # call event handlers for c in self.callbacks["update"]: c(self.name, updated_obj, frame_time) From f4aa02cc19c303b0006c8b06feac4f9bb4ed7ae1 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Wed, 7 Jul 2021 07:31:42 -0500 Subject: [PATCH 23/71] allow specific objects to be listed for a zone (fixes #1123) --- docs/docs/configuration/cameras.md | 6 ++++++ frigate/config.py | 4 ++++ frigate/object_processing.py | 3 +++ 3 files changed, 13 insertions(+) diff --git a/docs/docs/configuration/cameras.md b/docs/docs/configuration/cameras.md index e22912105..273be9b7e 100644 --- a/docs/docs/configuration/cameras.md +++ b/docs/docs/configuration/cameras.md @@ -93,6 +93,9 @@ zones: # Required: List of x,y coordinates to define the polygon of the zone. # NOTE: Coordinates can be generated at https://www.image-map.net/ coordinates: 545,1077,747,939,788,805 + # Optional: List of objects that can trigger this zone (default: all tracked objects) + objects: + - person # Optional: Zone level object filters. # NOTE: The global and camera filters are applied upstream. filters: @@ -312,6 +315,9 @@ cameras: # Required: List of x,y coordinates to define the polygon of the zone. # NOTE: Coordinates can be generated at https://www.image-map.net/ coordinates: 545,1077,747,939,788,805 + # Optional: List of objects that can trigger this zone (default: all tracked objects) + objects: + - person # Optional: Zone level object filters. # NOTE: The global and camera filters are applied upstream. filters: diff --git a/frigate/config.py b/frigate/config.py index 55b421fcd..48df20ea7 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -185,6 +185,10 @@ class ZoneConfig(BaseModel): coordinates: Union[str, List[str]] = Field( title="Coordinates polygon for the defined zone." ) + objects: List[str] = Field( + default_factory=list, + title="List of objects that can trigger the zone.", + ) _color: Optional[Tuple[int, int, int]] = PrivateAttr() _contour: np.ndarray = PrivateAttr() diff --git a/frigate/object_processing.py b/frigate/object_processing.py index 372db8ef7..660f74d87 100644 --- a/frigate/object_processing.py +++ b/frigate/object_processing.py @@ -143,6 +143,9 @@ class TrackedObject: bottom_center = (self.obj_data["centroid"][0], self.obj_data["box"][3]) # check each zone for name, zone in self.camera_config.zones.items(): + # if the zone is not for this object type, skip + if len(zone.objects) > 0 and not self.obj_data["label"] in zone.objects: + continue contour = zone.contour # check if the object is in the zone if cv2.pointPolygonTest(contour, bottom_center, False) >= 0: From f26f7b8d3f61edab184e9350ba7bc995fbea4595 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Wed, 7 Jul 2021 07:32:13 -0500 Subject: [PATCH 24/71] make default motion a little more sensitive --- docs/docs/configuration/advanced.md | 4 ++-- frigate/config.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/docs/configuration/advanced.md b/docs/docs/configuration/advanced.md index 1db060e36..74d8d222f 100644 --- a/docs/docs/configuration/advanced.md +++ b/docs/docs/configuration/advanced.md @@ -16,7 +16,7 @@ motion: # Increasing this value will make motion detection less sensitive and decreasing it will make motion detection more sensitive. # The value should be between 1 and 255. threshold: 25 - # Optional: Minimum size in pixels in the resized motion image that counts as motion (default: ~0.4% of the motion frame area) + # Optional: Minimum size in pixels in the resized motion image that counts as motion (default: ~0.17% of the motion frame area) # Increasing this value will prevent smaller areas of motion from being detected. Decreasing will make motion detection more sensitive to smaller # moving objects. contour_area: 100 @@ -29,7 +29,7 @@ motion: # Low values will cause things like moving shadows to be detected as motion for longer. # https://www.geeksforgeeks.org/background-subtraction-in-an-image-using-concept-of-running-average/ frame_alpha: 0.2 - # Optional: Height of the resized motion frame (default: 1/6th of the original frame height, but no less than 120) + # Optional: Height of the resized motion frame (default: 1/6th of the original frame height, but no less than 180) # This operates as an efficient blur alternative. Higher values will result in more granular motion detection at the expense of higher CPU usage. # Lower values result in less CPU, but small changes may not register as motion. frame_height: 180 diff --git a/frigate/config.py b/frigate/config.py index 48df20ea7..7a19ae25b 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -99,11 +99,13 @@ class RuntimeMotionConfig(MotionConfig): frame_shape = config.get("frame_shape", (1, 1)) if "frame_height" not in config: - config["frame_height"] = max(frame_shape[0] // 6, 120) + config["frame_height"] = max(frame_shape[0] // 6, 180) if "contour_area" not in config: frame_width = frame_shape[1] * config["frame_height"] / frame_shape[0] - config["contour_area"] = config["frame_height"] * frame_width * 0.003912363 + config["contour_area"] = ( + config["frame_height"] * frame_width * 0.00173611111 + ) mask = config.get("mask", "") config["raw_mask"] = mask From a3853af47ab950877b142aeec4937fb70d273652 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Wed, 7 Jul 2021 22:01:59 -0500 Subject: [PATCH 25/71] fix test --- frigate/test/test_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frigate/test/test_config.py b/frigate/test/test_config.py index 6a91a2814..0625e2c28 100644 --- a/frigate/test/test_config.py +++ b/frigate/test/test_config.py @@ -501,7 +501,7 @@ class TestConfig(unittest.TestCase): assert config == frigate_config.dict(exclude_unset=True) runtime_config = frigate_config.runtime_config - assert round(runtime_config.cameras["back"].motion.contour_area) == 225 + assert round(runtime_config.cameras["back"].motion.contour_area) == 99 if __name__ == "__main__": From 92aa16c556cb5f39508e6ab802e1fad5f939a398 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Wed, 7 Jul 2021 22:57:19 -0500 Subject: [PATCH 26/71] add labelmap customization to the config (fixes #507) --- docs/docs/configuration/advanced.md | 7 +++ docs/docs/configuration/objects.mdx | 17 ++---- frigate/app.py | 1 + frigate/config.py | 17 ++++++ frigate/edgetpu.py | 2 +- frigate/test/test_config.py | 80 +++++++++++++++++++++++++++++ frigate/video.py | 3 +- 7 files changed, 111 insertions(+), 16 deletions(-) diff --git a/docs/docs/configuration/advanced.md b/docs/docs/configuration/advanced.md index 74d8d222f..14dcb73de 100644 --- a/docs/docs/configuration/advanced.md +++ b/docs/docs/configuration/advanced.md @@ -110,10 +110,17 @@ detectors: ### `model` +If using a custom model, the width and height will need to be specified. + +The labelmap can be customized to your needs. A common reason to do this is to combine multiple object types that are easily confused when you don't need to be as granular such as car/truck. By default, truck is renamed to car because they are often confused. You cannot add new object types, but you can change the names of existing objects in the model. + ```yaml model: # Required: height of the trained model height: 320 # Required: width of the trained model width: 320 + # Optional: labelmap overrides + labelmap: + 7: car ``` diff --git a/docs/docs/configuration/objects.mdx b/docs/docs/configuration/objects.mdx index 3e95f9e83..a8608c286 100644 --- a/docs/docs/configuration/objects.mdx +++ b/docs/docs/configuration/objects.mdx @@ -4,13 +4,13 @@ title: Default available objects sidebar_label: Available objects --- -import labels from '../../../labelmap.txt'; +import labels from "../../../labelmap.txt"; By default, Frigate includes the following object models from the Google Coral test data.
    - {labels.split('\n').map((label) => ( -
  • {label.replace(/^\d+\s+/, '')}
  • + {labels.split("\n").map((label) => ( +
  • {label.replace(/^\d+\s+/, "")}
  • ))}
@@ -23,14 +23,3 @@ Models for both CPU and EdgeTPU (Coral) are bundled in the image. You can use yo - Labels: `/labelmap.txt` You also need to update the model width/height in the config if they differ from the defaults. - -### Customizing the Labelmap - -The labelmap can be customized to your needs. A common reason to do this is to combine multiple object types that are easily confused when you don't need to be as granular such as car/truck. You must retain the same number of labels, but you can change the names. To change: - -- Download the [COCO labelmap](https://dl.google.com/coral/canned_models/coco_labels.txt) -- Modify the label names as desired. For example, change `7 truck` to `7 car` -- Mount the new file at `/labelmap.txt` in the container with an additional volume - ``` - -v ./config/labelmap.txt:/labelmap.txt - ``` diff --git a/frigate/app.py b/frigate/app.py index 1d3d7bda5..b76c8146d 100644 --- a/frigate/app.py +++ b/frigate/app.py @@ -259,6 +259,7 @@ class FrigateApp: name, config, model_shape, + self.config.model.merged_labelmap, self.detection_queue, self.detection_out_events[name], self.detected_frames_queue, diff --git a/frigate/config.py b/frigate/config.py index 7a19ae25b..7e3426a34 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -13,6 +13,7 @@ from pydantic.fields import PrivateAttr import yaml from frigate.const import BASE_DIR, RECORD_DIR, CACHE_DIR +from frigate.edgetpu import load_labels from frigate.util import create_mask, deep_merge logger = logging.getLogger(__name__) @@ -615,6 +616,22 @@ class DatabaseConfig(BaseModel): class ModelConfig(BaseModel): width: int = Field(default=320, title="Object detection model input width.") height: int = Field(default=320, title="Object detection model input height.") + labelmap: Dict[int, str] = Field( + default_factory=dict, title="Labelmap customization." + ) + _merged_labelmap: Optional[Dict[int, str]] = PrivateAttr() + + @property + def merged_labelmap(self) -> Dict[int, str]: + return self._merged_labelmap + + def __init__(self, **config): + super().__init__(**config) + + self._merged_labelmap = { + **load_labels("/labelmap.txt"), + **config.get("labelmap", {}), + } class LogLevelEnum(str, Enum): diff --git a/frigate/edgetpu.py b/frigate/edgetpu.py index 2ffd8c198..b426e40a6 100644 --- a/frigate/edgetpu.py +++ b/frigate/edgetpu.py @@ -231,7 +231,7 @@ class EdgeTPUProcess: class RemoteObjectDetector: def __init__(self, name, labels, detection_queue, event, model_shape): - self.labels = load_labels(labels) + self.labels = labels self.name = name self.fps = EventsPerSecond() self.detection_queue = detection_queue diff --git a/frigate/test/test_config.py b/frigate/test/test_config.py index 0625e2c28..af1c8a593 100644 --- a/frigate/test/test_config.py +++ b/frigate/test/test_config.py @@ -503,6 +503,86 @@ class TestConfig(unittest.TestCase): runtime_config = frigate_config.runtime_config assert round(runtime_config.cameras["back"].motion.contour_area) == 99 + def test_merge_labelmap(self): + + config = { + "mqtt": {"host": "mqtt"}, + "model": {"labelmap": {7: "truck"}}, + "cameras": { + "back": { + "ffmpeg": { + "inputs": [ + { + "path": "rtsp://10.0.0.1:554/video", + "roles": ["detect"], + }, + ] + }, + "height": 1080, + "width": 1920, + } + }, + } + + frigate_config = FrigateConfig(**config) + assert config == frigate_config.dict(exclude_unset=True) + + runtime_config = frigate_config.runtime_config + assert runtime_config.model.merged_labelmap[7] == "truck" + + def test_default_labelmap_empty(self): + + config = { + "mqtt": {"host": "mqtt"}, + "cameras": { + "back": { + "ffmpeg": { + "inputs": [ + { + "path": "rtsp://10.0.0.1:554/video", + "roles": ["detect"], + }, + ] + }, + "height": 1080, + "width": 1920, + } + }, + } + + frigate_config = FrigateConfig(**config) + assert config == frigate_config.dict(exclude_unset=True) + + runtime_config = frigate_config.runtime_config + assert runtime_config.model.merged_labelmap[0] == "person" + + def test_default_labelmap(self): + + config = { + "mqtt": {"host": "mqtt"}, + "model": {"width": 320, "height": 320}, + "cameras": { + "back": { + "ffmpeg": { + "inputs": [ + { + "path": "rtsp://10.0.0.1:554/video", + "roles": ["detect"], + }, + ] + }, + "height": 1080, + "width": 1920, + } + }, + } + + frigate_config = FrigateConfig(**config) + assert config == frigate_config.dict(exclude_unset=True) + + runtime_config = frigate_config.runtime_config + assert runtime_config.model.merged_labelmap[0] == "person" + if __name__ == "__main__": unittest.main(verbosity=2) diff --git a/frigate/video.py b/frigate/video.py index 23897dabd..7285dc0e5 100755 --- a/frigate/video.py +++ b/frigate/video.py @@ -318,6 +318,7 @@ def track_camera( name, config: CameraConfig, model_shape, + labelmap, detection_queue, result_connection, detected_objects_queue, @@ -344,7 +345,7 @@ def track_camera( motion_detector = MotionDetector(frame_shape, config.motion) object_detector = RemoteObjectDetector( - name, "/labelmap.txt", detection_queue, result_connection, model_shape + name, labelmap, detection_queue, result_connection, model_shape ) object_tracker = ObjectTracker(config.detect) From 4fa6fa20011b661faee1f3eb8f41a8c31d4883db Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Fri, 9 Jul 2021 06:39:57 -0500 Subject: [PATCH 27/71] revert ffmpeg version --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 7b4d4b314..66429c3c3 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ nginx_frigate: docker buildx build --push --platform linux/arm/v7,linux/arm64/v8,linux/amd64 --tag blakeblackshear/frigate-nginx:1.0.0 --file docker/Dockerfile.nginx . amd64_frigate: version web - docker build --no-cache --tag frigate-base --build-arg ARCH=amd64 --build-arg FFMPEG_VERSION=1.2.0 --build-arg WHEELS_VERSION=1.0.3 --build-arg NGINX_VERSION=1.0.0 --file docker/Dockerfile.base . + docker build --no-cache --tag frigate-base --build-arg ARCH=amd64 --build-arg FFMPEG_VERSION=1.1.0 --build-arg WHEELS_VERSION=1.0.3 --build-arg NGINX_VERSION=1.0.0 --file docker/Dockerfile.base . docker build --no-cache --tag frigate --file docker/Dockerfile.amd64 . amd64_all: amd64_wheels amd64_ffmpeg amd64_frigate @@ -30,7 +30,7 @@ amd64nvidia_ffmpeg: docker build --no-cache --pull --tag blakeblackshear/frigate-ffmpeg:1.2.0-amd64nvidia --file docker/Dockerfile.ffmpeg.amd64nvidia . amd64nvidia_frigate: version web - docker build --no-cache --tag frigate-base --build-arg ARCH=amd64nvidia --build-arg FFMPEG_VERSION=1.2.0 --build-arg WHEELS_VERSION=1.0.3 --build-arg NGINX_VERSION=1.0.0 --file docker/Dockerfile.base . + docker build --no-cache --tag frigate-base --build-arg ARCH=amd64nvidia --build-arg FFMPEG_VERSION=1.0.0 --build-arg WHEELS_VERSION=1.0.3 --build-arg NGINX_VERSION=1.0.0 --file docker/Dockerfile.base . docker build --no-cache --tag frigate --file docker/Dockerfile.amd64nvidia . amd64nvidia_all: amd64nvidia_wheels amd64nvidia_ffmpeg amd64nvidia_frigate @@ -42,7 +42,7 @@ aarch64_ffmpeg: docker build --no-cache --pull --tag blakeblackshear/frigate-ffmpeg:1.2.0-aarch64 --file docker/Dockerfile.ffmpeg.aarch64 . aarch64_frigate: version web - docker build --no-cache --tag frigate-base --build-arg ARCH=aarch64 --build-arg FFMPEG_VERSION=1.2.0 --build-arg WHEELS_VERSION=1.0.3 --build-arg NGINX_VERSION=1.0.0 --file docker/Dockerfile.base . + docker build --no-cache --tag frigate-base --build-arg ARCH=aarch64 --build-arg FFMPEG_VERSION=1.0.0 --build-arg WHEELS_VERSION=1.0.3 --build-arg NGINX_VERSION=1.0.0 --file docker/Dockerfile.base . docker build --no-cache --tag frigate --file docker/Dockerfile.aarch64 . armv7_all: armv7_wheels armv7_ffmpeg armv7_frigate @@ -54,7 +54,7 @@ armv7_ffmpeg: docker build --no-cache --pull --tag blakeblackshear/frigate-ffmpeg:1.2.0-armv7 --file docker/Dockerfile.ffmpeg.armv7 . armv7_frigate: version web - docker build --no-cache --tag frigate-base --build-arg ARCH=armv7 --build-arg FFMPEG_VERSION=1.2.0 --build-arg WHEELS_VERSION=1.0.3 --build-arg NGINX_VERSION=1.0.0 --file docker/Dockerfile.base . + docker build --no-cache --tag frigate-base --build-arg ARCH=armv7 --build-arg FFMPEG_VERSION=1.0.0 --build-arg WHEELS_VERSION=1.0.3 --build-arg NGINX_VERSION=1.0.0 --file docker/Dockerfile.base . docker build --no-cache --tag frigate --file docker/Dockerfile.armv7 . armv7_all: armv7_wheels armv7_ffmpeg armv7_frigate From 1a3567c5d0674e4ce60e93c395892c611bc8348b Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Fri, 9 Jul 2021 07:20:16 -0500 Subject: [PATCH 28/71] arch specific s6-overlay --- docker/Dockerfile.aarch64 | 32 +++++++++++++++++++------------ docker/Dockerfile.amd64 | 10 +++++++++- docker/Dockerfile.amd64nvidia | 14 +++++++++++--- docker/Dockerfile.armv7 | 36 +++++++++++++++++++++-------------- docker/Dockerfile.base | 8 -------- 5 files changed, 62 insertions(+), 38 deletions(-) diff --git a/docker/Dockerfile.aarch64 b/docker/Dockerfile.aarch64 index 5ce548f2d..ba7995521 100644 --- a/docker/Dockerfile.aarch64 +++ b/docker/Dockerfile.aarch64 @@ -5,18 +5,26 @@ ENV DEBIAN_FRONTEND=noninteractive # Install packages for apt repo RUN apt-get -qq update \ && apt-get -qq install --no-install-recommends -y \ - # ffmpeg runtime dependencies - libgomp1 \ - # runtime dependencies - libopenexr24 \ - libgstreamer1.0-0 \ - libgstreamer-plugins-base1.0-0 \ - libopenblas-base \ - libjpeg-turbo8 \ - libpng16-16 \ - libtiff5 \ - libdc1394-22 \ + # ffmpeg runtime dependencies + libgomp1 \ + # runtime dependencies + libopenexr24 \ + libgstreamer1.0-0 \ + libgstreamer-plugins-base1.0-0 \ + libopenblas-base \ + libjpeg-turbo8 \ + libpng16-16 \ + libtiff5 \ + libdc1394-22 \ ## Tensorflow lite && pip3 install https://github.com/google-coral/pycoral/releases/download/release-frogfish/tflite_runtime-2.5.0-cp38-cp38-linux_aarch64.whl \ && rm -rf /var/lib/apt/lists/* \ - && (apt-get autoremove -y; apt-get autoclean -y) \ No newline at end of file + && (apt-get autoremove -y; apt-get autoclean -y) + +# s6-overlay +ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-aarch64-installer /tmp/ +RUN chmod +x /tmp/s6-overlay-aarch64-installer && /tmp/s6-overlay-aarch64-installer / + +ENTRYPOINT ["/init"] + +CMD ["python3", "-u", "-m", "frigate"] \ No newline at end of file diff --git a/docker/Dockerfile.amd64 b/docker/Dockerfile.amd64 index cb02aaaa3..2f4a432d2 100644 --- a/docker/Dockerfile.amd64 +++ b/docker/Dockerfile.amd64 @@ -21,4 +21,12 @@ RUN apt-get -qq update \ && python3.8 -m pip install tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \ && rm tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \ && rm -rf /var/lib/apt/lists/* \ - && (apt-get autoremove -y; apt-get autoclean -y) \ No newline at end of file + && (apt-get autoremove -y; apt-get autoclean -y) + +# s6-overlay +ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64-installer /tmp/ +RUN chmod +x /tmp/s6-overlay-amd64-installer && /tmp/s6-overlay-amd64-installer / + +ENTRYPOINT ["/init"] + +CMD ["python3", "-u", "-m", "frigate"] \ No newline at end of file diff --git a/docker/Dockerfile.amd64nvidia b/docker/Dockerfile.amd64nvidia index 8714f70ad..1db9e94d8 100644 --- a/docker/Dockerfile.amd64nvidia +++ b/docker/Dockerfile.amd64nvidia @@ -4,9 +4,9 @@ LABEL maintainer "blakeb@blakeshome.com" # Install packages for apt repo RUN apt-get -qq update \ && apt-get -qq install --no-install-recommends -y \ - # ffmpeg dependencies - libgomp1 \ - ## Tensorflow lite + # ffmpeg dependencies + libgomp1 \ + ## Tensorflow lite && wget -q https://github.com/google-coral/pycoral/releases/download/release-frogfish/tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \ && python3.8 -m pip install tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \ && rm tflite_runtime-2.5.0-cp38-cp38-linux_x86_64.whl \ @@ -45,3 +45,11 @@ ENV LD_LIBRARY_PATH /usr/local/nvidia/lib:/usr/local/nvidia/lib64 ENV NVIDIA_VISIBLE_DEVICES all ENV NVIDIA_DRIVER_CAPABILITIES compute,utility,video ENV NVIDIA_REQUIRE_CUDA "cuda>=11.1 brand=tesla,driver>=418,driver<419 brand=tesla,driver>=440,driver<441 brand=tesla,driver>=450,driver<451" + +# s6-overlay +ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64-installer /tmp/ +RUN chmod +x /tmp/s6-overlay-amd64-installer && /tmp/s6-overlay-amd64-installer / + +ENTRYPOINT ["/init"] + +CMD ["python3", "-u", "-m", "frigate"] \ No newline at end of file diff --git a/docker/Dockerfile.armv7 b/docker/Dockerfile.armv7 index 2e50cd22c..a1c360813 100644 --- a/docker/Dockerfile.armv7 +++ b/docker/Dockerfile.armv7 @@ -5,20 +5,28 @@ ENV DEBIAN_FRONTEND=noninteractive # Install packages for apt repo RUN apt-get -qq update \ && apt-get -qq install --no-install-recommends -y \ - # ffmpeg runtime dependencies - libgomp1 \ - # runtime dependencies - libopenexr24 \ - libgstreamer1.0-0 \ - libgstreamer-plugins-base1.0-0 \ - libopenblas-base \ - libjpeg-turbo8 \ - libpng16-16 \ - libtiff5 \ - libdc1394-22 \ - libaom0 \ - libx265-179 \ + # ffmpeg runtime dependencies + libgomp1 \ + # runtime dependencies + libopenexr24 \ + libgstreamer1.0-0 \ + libgstreamer-plugins-base1.0-0 \ + libopenblas-base \ + libjpeg-turbo8 \ + libpng16-16 \ + libtiff5 \ + libdc1394-22 \ + libaom0 \ + libx265-179 \ ## Tensorflow lite && pip3 install https://github.com/google-coral/pycoral/releases/download/release-frogfish/tflite_runtime-2.5.0-cp38-cp38-linux_armv7l.whl \ && rm -rf /var/lib/apt/lists/* \ - && (apt-get autoremove -y; apt-get autoclean -y) \ No newline at end of file + && (apt-get autoremove -y; apt-get autoclean -y) + +# s6-overlay +ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-armhf-installer /tmp/ +RUN chmod +x /tmp/s6-overlay-armhf-installer && /tmp/s6-overlay-armhf-installer / + +ENTRYPOINT ["/init"] + +CMD ["python3", "-u", "-m", "frigate"] \ No newline at end of file diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base index f80e3c8f8..1b9e1d144 100644 --- a/docker/Dockerfile.base +++ b/docker/Dockerfile.base @@ -10,10 +10,6 @@ FROM frigate-web as web FROM ubuntu:20.04 LABEL maintainer "blakeb@blakeshome.com" -# s6-overlay -ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.1/s6-overlay-amd64-installer /tmp/ -RUN chmod +x /tmp/s6-overlay-amd64-installer && /tmp/s6-overlay-amd64-installer / - COPY --from=ffmpeg /usr/local /usr/local/ COPY --from=wheels /wheels/. /wheels/ @@ -57,7 +53,3 @@ COPY docker/rootfs/ / EXPOSE 5000 EXPOSE 1935 - -ENTRYPOINT ["/init"] - -CMD ["python3", "-u", "-m", "frigate"] From ebee204ca06c51b8e7a82b68453c2ecfb226db61 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Fri, 9 Jul 2021 20:21:35 -0500 Subject: [PATCH 29/71] ensure default args propogate --- frigate/config.py | 12 ------------ frigate/test/test_config.py | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/frigate/config.py b/frigate/config.py index 7e3426a34..a39cdf134 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -347,18 +347,6 @@ class CameraInput(BaseModel): class CameraFfmpegConfig(FfmpegConfig): inputs: List[CameraInput] = Field(title="Camera inputs.") - global_args: Union[str, List[str]] = Field( - default_factory=list, title="FFmpeg global arguments." - ) - hwaccel_args: Union[str, List[str]] = Field( - default_factory=list, title="FFmpeg hardware acceleration arguments." - ) - input_args: Union[str, List[str]] = Field( - default_factory=list, title="FFmpeg input arguments." - ) - output_args: FfmpegOutputArgsConfig = Field( - default_factory=FfmpegOutputArgsConfig, title="FFmpeg output arguments." - ) @validator("inputs") def validate_roles(cls, v): diff --git a/frigate/test/test_config.py b/frigate/test/test_config.py index af1c8a593..23f3499d3 100644 --- a/frigate/test/test_config.py +++ b/frigate/test/test_config.py @@ -197,6 +197,32 @@ class TestConfig(unittest.TestCase): assert len(back_camera.objects.filters["dog"].raw_mask) == 2 assert len(back_camera.objects.filters["person"].raw_mask) == 1 + def test_default_input_args(self): + + config = { + "mqtt": {"host": "mqtt"}, + "cameras": { + "back": { + "ffmpeg": { + "inputs": [ + { + "path": "rtsp://10.0.0.1:554/video", + "roles": ["detect"], + }, + ] + }, + "height": 1080, + "width": 1920, + } + }, + } + + frigate_config = FrigateConfig(**config) + assert config == frigate_config.dict(exclude_unset=True) + + runtime_config = frigate_config.runtime_config + assert "-rtsp_transport" in runtime_config.cameras["back"].ffmpeg_cmds[0]["cmd"] + def test_ffmpeg_params_global(self): config = { "ffmpeg": {"input_args": "-re"}, From 6b26fc753ec5d63b5eb359c7cf5d6620308e0745 Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Fri, 9 Jul 2021 20:22:11 -0500 Subject: [PATCH 30/71] include ffmpeg_cmds in config endpoint --- frigate/http.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/frigate/http.py b/frigate/http.py index 2f3a15221..55b04ce75 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -277,7 +277,16 @@ def events(): @bp.route("/config") def config(): - return jsonify(current_app.frigate_config.dict()) + config = current_app.frigate_config.dict() + + # add in the ffmpeg_cmds + for camera_name, camera in current_app.frigate_config.cameras.items(): + camera_dict = config["cameras"][camera_name] + camera_dict["ffmpeg_cmds"] = camera.ffmpeg_cmds + for cmd in camera_dict["ffmpeg_cmds"]: + cmd["cmd"] = " ".join(cmd["cmd"]) + + return jsonify(config) @bp.route("/config/schema") From 50f0c05e690816c9bf66b0f2eb0692850f183b1b Mon Sep 17 00:00:00 2001 From: Blake Blackshear Date: Tue, 13 Jul 2021 08:51:15 -0500 Subject: [PATCH 31/71] fix motion mask overlay --- frigate/object_processing.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frigate/object_processing.py b/frigate/object_processing.py index 660f74d87..999b67e6e 100644 --- a/frigate/object_processing.py +++ b/frigate/object_processing.py @@ -322,7 +322,9 @@ def zone_filtered(obj: TrackedObject, object_config): # Maintains the state of a camera class CameraState: - def __init__(self, name, config, frame_manager): + def __init__( + self, name, config: FrigateConfig, frame_manager: SharedMemoryFrameManager + ): self.name = name self.config = config self.camera_config = config.cameras[name] @@ -396,7 +398,7 @@ class CameraState: cv2.drawContours(frame_copy, [zone.contour], -1, zone.color, thickness) if draw_options.get("mask"): - mask_overlay = np.where(self.camera_config.motion_mask == [0]) + mask_overlay = np.where(self.camera_config.motion.mask == [0]) frame_copy[mask_overlay] = [0, 0, 0] if draw_options.get("motion_boxes"): From 4449bc52929791e75fb782b694e5b891652aa589 Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Wed, 14 Jul 2021 15:32:19 +0200 Subject: [PATCH 32/71] add tabbed buttons component --- web/src/components/ButtonsTabbed.jsx | 29 ++++++++++++++++++++++++++++ web/src/routes/Camera.jsx | 12 ++---------- 2 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 web/src/components/ButtonsTabbed.jsx diff --git a/web/src/components/ButtonsTabbed.jsx b/web/src/components/ButtonsTabbed.jsx new file mode 100644 index 000000000..2a42155e5 --- /dev/null +++ b/web/src/components/ButtonsTabbed.jsx @@ -0,0 +1,29 @@ +import { h } from 'preact'; +import { useCallback } from 'preact/hooks'; + +export default function ButtonsTabbed({ titles = [], viewMode, setViewMode }) { + const className = 'text-gray-600 py-0 px-4 block hover:text-gray-500'; + + const handleClick = useCallback((i) => { + setViewMode(titles[i]); + }, [viewMode]); // eslint-disable-line react-hooks/exhaustive-deps + + return ( + + ); +} diff --git a/web/src/routes/Camera.jsx b/web/src/routes/Camera.jsx index 7f5527df4..133841500 100644 --- a/web/src/routes/Camera.jsx +++ b/web/src/routes/Camera.jsx @@ -7,6 +7,7 @@ import Heading from '../components/Heading'; import Link from '../components/Link'; import SettingsIcon from '../icons/Settings'; import Switch from '../components/Switch'; +import ButtonsTabbed from '../components/ButtonsTabbed'; import { usePersistence } from '../context'; import { useCallback, useMemo, useState } from 'preact/hooks'; import { useApiHost, useConfig } from '../api'; @@ -112,16 +113,7 @@ export default function Camera({ camera }) { return (
{camera} -
- -
+ {player} From 16ef432228dc3703a2d183edaec12a125010922d Mon Sep 17 00:00:00 2001 From: ElMoribond Date: Fri, 16 Jul 2021 10:51:21 +0200 Subject: [PATCH 33/71] add tabbed buttons component --- web/src/components/ButtonsTabbed.jsx | 38 +++++++++++++++++----------- web/src/routes/Camera.jsx | 2 +- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/web/src/components/ButtonsTabbed.jsx b/web/src/components/ButtonsTabbed.jsx index 2a42155e5..ba68cf409 100644 --- a/web/src/components/ButtonsTabbed.jsx +++ b/web/src/components/ButtonsTabbed.jsx @@ -1,26 +1,34 @@ import { h } from 'preact'; -import { useCallback } from 'preact/hooks'; +import { useCallback, useState } from 'preact/hooks'; -export default function ButtonsTabbed({ titles = [], viewMode, setViewMode }) { - const className = 'text-gray-600 py-0 px-4 block hover:text-gray-500'; +export default function ButtonsTabbed({ + viewModes = [''], + setViewMode = null, + setHeader = null, + headers = [''], + className = 'text-gray-600 py-0 px-4 block hover:text-gray-500', + selectedClassName = `${className} focus:outline-none border-b-2 font-medium border-gray-500` +}) { + const [selected, setSelected] = useState(0); + const captitalize = (str) => { return (`${str.charAt(0).toUpperCase()}${str.slice(1)}`); }; + + const getHeader = useCallback((i) => { + return (headers.length === viewModes.length ? headers[i] : captitalize(viewModes[i])); + }, [headers, viewModes]); const handleClick = useCallback((i) => { - setViewMode(titles[i]); - }, [viewMode]); // eslint-disable-line react-hooks/exhaustive-deps + setSelected(i); + setViewMode && setViewMode(viewModes[i]); + setHeader && setHeader(getHeader(i)); + }, [setViewMode, setHeader, setSelected, viewModes, getHeader]); + setHeader && setHeader(getHeader(selected)); return (