mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-08-13 13:47:36 +02:00
fix conflicts
This commit is contained in:
parent
ab3e70b4db
commit
5842a3cace
@ -95,6 +95,9 @@ automation:
|
|||||||
caption: A person was detected.
|
caption: A person was detected.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Disabling Detection
|
||||||
|
You can disable or enable detection via mqtt by publishing to `topic_prefix/detection` then you want to send a payload of either 'enable' or 'disable'.
|
||||||
|
|
||||||
## Tips
|
## Tips
|
||||||
- Lower the framerate of the video feed on the camera to reduce the CPU usage for capturing the feed
|
- Lower the framerate of the video feed on the camera to reduce the CPU usage for capturing the feed
|
||||||
|
|
||||||
@ -111,7 +114,7 @@ automation:
|
|||||||
- [ ] See if motion detection is even worth running
|
- [ ] See if motion detection is even worth running
|
||||||
- [ ] Scan for people across entire image rather than specfic regions
|
- [ ] Scan for people across entire image rather than specfic regions
|
||||||
- [ ] Dynamically resize detection area and follow people
|
- [ ] Dynamically resize detection area and follow people
|
||||||
- [ ] Add ability to turn detection on and off via MQTT
|
- [x] Add ability to turn detection on and off via MQTT
|
||||||
- [ ] Output movie clips of people for notifications, etc.
|
- [ ] Output movie clips of people for notifications, etc.
|
||||||
- [ ] Integrate with homeassistant push camera
|
- [ ] Integrate with homeassistant push camera
|
||||||
- [ ] Merge bounding boxes that span multiple regions
|
- [ ] Merge bounding boxes that span multiple regions
|
||||||
|
@ -9,6 +9,8 @@ import paho.mqtt.client as mqtt
|
|||||||
from frigate.video import Camera
|
from frigate.video import Camera
|
||||||
from frigate.object_detection import PreppedQueueProcessor
|
from frigate.object_detection import PreppedQueueProcessor
|
||||||
|
|
||||||
|
from frigate.mqtt import MqttObjectConsumer
|
||||||
|
|
||||||
with open('/config/config.yml') as f:
|
with open('/config/config.yml') as f:
|
||||||
CONFIG = yaml.safe_load(f)
|
CONFIG = yaml.safe_load(f)
|
||||||
|
|
||||||
@ -62,13 +64,25 @@ def main():
|
|||||||
print ("Unable to connect to MQTT: Connection refused. Error code: " + str(rc))
|
print ("Unable to connect to MQTT: Connection refused. Error code: " + str(rc))
|
||||||
# publish a message to signal that the service is running
|
# publish a message to signal that the service is running
|
||||||
client.publish(MQTT_TOPIC_PREFIX+'/available', 'online', retain=True)
|
client.publish(MQTT_TOPIC_PREFIX+'/available', 'online', retain=True)
|
||||||
|
|
||||||
|
# start a thread to listen for responses over mqtt
|
||||||
|
listen_queue = queue.Queue(10) # since we are listening for messages shouldn't need a very large queue
|
||||||
|
def on_message(client, obj, msg):
|
||||||
|
if msg.topic.startswith(MQTT_TOPIC_PREFIX):
|
||||||
|
payload = str(msg.payload.decode("utf-8"))
|
||||||
|
listen_queue.put({
|
||||||
|
'topic': msg.topic,
|
||||||
|
'payload': payload
|
||||||
|
})
|
||||||
client = mqtt.Client(client_id=MQTT_CLIENT_ID)
|
client = mqtt.Client(client_id=MQTT_CLIENT_ID)
|
||||||
client.on_connect = on_connect
|
client.on_connect = on_connect
|
||||||
|
client.on_message = on_message
|
||||||
client.will_set(MQTT_TOPIC_PREFIX+'/available', payload='offline', qos=1, retain=True)
|
client.will_set(MQTT_TOPIC_PREFIX+'/available', payload='offline', qos=1, retain=True)
|
||||||
if not MQTT_USER is None:
|
if not MQTT_USER is None:
|
||||||
client.username_pw_set(MQTT_USER, password=MQTT_PASS)
|
client.username_pw_set(MQTT_USER, password=MQTT_PASS)
|
||||||
client.connect(MQTT_HOST, MQTT_PORT, 60)
|
client.connect(MQTT_HOST, MQTT_PORT, 60)
|
||||||
client.loop_start()
|
client.loop_start()
|
||||||
|
client.subscribe("frigate/detection")
|
||||||
|
|
||||||
# Queue for prepped frames, max size set to (number of cameras * 5)
|
# Queue for prepped frames, max size set to (number of cameras * 5)
|
||||||
max_queue_size = len(CONFIG['cameras'].items())*5
|
max_queue_size = len(CONFIG['cameras'].items())*5
|
||||||
@ -78,6 +92,9 @@ def main():
|
|||||||
for name, config in CONFIG['cameras'].items():
|
for name, config in CONFIG['cameras'].items():
|
||||||
cameras[name] = Camera(name, FFMPEG_DEFAULT_CONFIG, GLOBAL_OBJECT_CONFIG, config, prepped_frame_queue, client, MQTT_TOPIC_PREFIX)
|
cameras[name] = Camera(name, FFMPEG_DEFAULT_CONFIG, GLOBAL_OBJECT_CONFIG, config, prepped_frame_queue, client, MQTT_TOPIC_PREFIX)
|
||||||
|
|
||||||
|
mqtt_listener = MqttObjectConsumer(client, MQTT_TOPIC_PREFIX, listen_queue, cameras.values())
|
||||||
|
mqtt_listener.start()
|
||||||
|
|
||||||
prepped_queue_processor = PreppedQueueProcessor(
|
prepped_queue_processor = PreppedQueueProcessor(
|
||||||
cameras,
|
cameras,
|
||||||
prepped_frame_queue
|
prepped_frame_queue
|
||||||
|
@ -2,6 +2,7 @@ import json
|
|||||||
import cv2
|
import cv2
|
||||||
import threading
|
import threading
|
||||||
from collections import Counter, defaultdict
|
from collections import Counter, defaultdict
|
||||||
|
import subprocess as sp
|
||||||
|
|
||||||
class MqttObjectPublisher(threading.Thread):
|
class MqttObjectPublisher(threading.Thread):
|
||||||
def __init__(self, client, topic_prefix, objects_parsed, detected_objects, best_frames):
|
def __init__(self, client, topic_prefix, objects_parsed, detected_objects, best_frames):
|
||||||
@ -45,3 +46,27 @@ class MqttObjectPublisher(threading.Thread):
|
|||||||
for obj_name in expired_objects:
|
for obj_name in expired_objects:
|
||||||
current_object_status[obj_name] = 'OFF'
|
current_object_status[obj_name] = 'OFF'
|
||||||
self.client.publish(self.topic_prefix+'/'+obj_name, 'OFF', retain=False)
|
self.client.publish(self.topic_prefix+'/'+obj_name, 'OFF', retain=False)
|
||||||
|
|
||||||
|
class MqttObjectConsumer(threading.Thread):
|
||||||
|
def __init__(self, client, topic_prefix, listen_queue, cameras):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.client = client
|
||||||
|
self.topic_prefix = topic_prefix
|
||||||
|
self.listen_queue = listen_queue
|
||||||
|
self.cameras = cameras
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while True:
|
||||||
|
# Now we want to see if there are more messages and then process them
|
||||||
|
item = self.listen_queue.get()
|
||||||
|
topic = item['topic']
|
||||||
|
payload = item['payload']
|
||||||
|
if topic == ("%s/detection" % self.topic_prefix):
|
||||||
|
if payload == 'enable':
|
||||||
|
for camera in self.cameras:
|
||||||
|
camera.start_or_restart_capture()
|
||||||
|
elif payload == 'disable':
|
||||||
|
for camera in self.cameras:
|
||||||
|
camera.disable_capture()
|
||||||
|
camera.watchdog.disable = True
|
||||||
|
camera.watchdog = None
|
||||||
|
@ -8,6 +8,7 @@ import multiprocessing as mp
|
|||||||
import subprocess as sp
|
import subprocess as sp
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
import queue
|
||||||
from . util import tonumpyarray, draw_box_with_label
|
from . util import tonumpyarray, draw_box_with_label
|
||||||
from . object_detection import FramePrepper
|
from . object_detection import FramePrepper
|
||||||
from . objects import ObjectCleaner, BestFrames
|
from . objects import ObjectCleaner, BestFrames
|
||||||
@ -64,10 +65,11 @@ class CameraWatchdog(threading.Thread):
|
|||||||
def __init__(self, camera):
|
def __init__(self, camera):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.camera = camera
|
self.camera = camera
|
||||||
|
self.disable = False
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
while True:
|
while not self.disable:
|
||||||
# wait a bit before checking
|
# wait a bit before checking
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
|
||||||
@ -206,9 +208,10 @@ class Camera:
|
|||||||
self.mask = np.zeros((self.frame_shape[0], self.frame_shape[1], 1), np.uint8)
|
self.mask = np.zeros((self.frame_shape[0], self.frame_shape[1], 1), np.uint8)
|
||||||
self.mask[:] = 255
|
self.mask[:] = 255
|
||||||
|
|
||||||
|
def disable_capture(self):
|
||||||
def start_or_restart_capture(self):
|
if self.ffmpeg_process is None:
|
||||||
if not self.ffmpeg_process is None:
|
print("Attempted to disable capture but was already disabled")
|
||||||
|
else:
|
||||||
print("Terminating the existing ffmpeg process...")
|
print("Terminating the existing ffmpeg process...")
|
||||||
self.ffmpeg_process.terminate()
|
self.ffmpeg_process.terminate()
|
||||||
try:
|
try:
|
||||||
@ -224,6 +227,10 @@ class Camera:
|
|||||||
self.ffmpeg_process = None
|
self.ffmpeg_process = None
|
||||||
self.capture_thread = None
|
self.capture_thread = None
|
||||||
|
|
||||||
|
def start_or_restart_capture(self):
|
||||||
|
if not self.ffmpeg_process is None:
|
||||||
|
self.disable_capture()
|
||||||
|
|
||||||
# create the process to capture frames from the input stream and store in a shared array
|
# create the process to capture frames from the input stream and store in a shared array
|
||||||
print("Creating a new ffmpeg process...")
|
print("Creating a new ffmpeg process...")
|
||||||
self.start_ffmpeg()
|
self.start_ffmpeg()
|
||||||
@ -233,6 +240,9 @@ class Camera:
|
|||||||
print("Starting a new capture thread...")
|
print("Starting a new capture thread...")
|
||||||
self.capture_thread.start()
|
self.capture_thread.start()
|
||||||
|
|
||||||
|
if self.watchdog == None:
|
||||||
|
self.watchdog = CameraWatchdog(self)
|
||||||
|
|
||||||
def start_ffmpeg(self):
|
def start_ffmpeg(self):
|
||||||
ffmpeg_cmd = (['ffmpeg'] +
|
ffmpeg_cmd = (['ffmpeg'] +
|
||||||
self.ffmpeg_global_args +
|
self.ffmpeg_global_args +
|
||||||
|
Loading…
Reference in New Issue
Block a user