Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement Request: Ability to dynamically disable/enable individual cameras #1911

Open
nfrntrd opened this issue Oct 5, 2021 · 80 comments
Labels
enhancement New feature or request pinned

Comments

@nfrntrd
Copy link

nfrntrd commented Oct 5, 2021

Describe what you are trying to accomplish and why in non technical terms
I want to be able to dynamically enable/disable cameras defined in the config.yml so that I can ensure no data is flowing from camera to the frigate container when not in use. Right now when the switch to stop recording is turned off, the camera/ffmpeg/rtsp process still keeps gathering video data and continues to drop files into /tmp/cache. (Assume snapshot and detect is also off)
I want to be able to ensure no data is flowing between camera and frigate container when I don't need the camera to capture anything. The use case here is I don't want cameras doing anything when I'm home in the house. My cameras are wireless enabled and use power/wireless bandwidth. It becomes quite a bandwidth hog having multiple in the house to simply throw all that data away. The switch to turn them on then becomes important to turn on the camera with recordings when I'm away from the house (triggered by HA via security alarm.)

Describe the solution you'd like
I would like another frigate HA switch service call to be available per camera that will completely disable/enable the camera and stop/start the ffmpeg process when not needed in the container.

Describe alternatives you've considered
From another NVR type of solution (Zoneminder) I've used, the idea of starting/stopping ffmpeg is a part of the profile and callable to disable said cameras. (That's my alternative) :)
From a frigate standpoint already tried stopping recording switch to learn what I summarized above.

Additional context
None.

@tbrausch
Copy link

I would also really like to find a way to enable/disable particular cameras in frigate. I am trying to keep my CPU usage to a minimum and would like to enable/disable certain cameras based on time of day, presence detection, alarm activated, etc. Is it possible in a future release to stop the ffmpeg process for a camera if the detect, snapshot, and record switches are all turned off?

@NickM-27
Copy link
Collaborator

@tbrausch I have a PR up to add the ability to selectively toggle motion detection which will help with this. Completely disabling ffmpeg for a camera selectively would be much more complicated but I don't think impossible.

@crashnbernstein
Copy link

I would also really like to find a way to enable/disable particular cameras in frigate. I am trying to keep my CPU usage to a minimum and would like to enable/disable certain cameras based on time of day, presence detection, alarm activated, etc. Is it possible in a future release to stop the ffmpeg process for a camera if the detect, snapshot, and record switches are all turned off?

You could use MQTT, as shown here:
https://docs.frigate.video/integrations/mqtt

frigate/<camera_name>/detect/set#
Topic to turn detection for a camera on and off. Expected values are ON and OFF.

frigate/<camera_name>/detect/state#
Topic with current state of detection for a camera. Published values are ON and OFF.

frigate/<camera_name>/recordings/set#
Topic to turn recordings for a camera on and off. Expected values are ON and OFF.

@tbrausch
Copy link

tbrausch commented Apr 19, 2022 via email

@MickazNL
Copy link

+1

@tbrausch
Copy link

I see that the new 11.0 beta has included switches to enable/disable motion detection on a per camera basis. When detection, motion, and recording are turned off for a particular camera is the ffmpeg process for that camera terminated?

@NickM-27
Copy link
Collaborator

I see that the new 11.0 beta has included switches to enable/disable motion detection on a per camera basis. When detection, motion, and recording are turned off for a particular camera is the ffmpeg process for that camera terminated?

No, video will still be decoded and it will still be viewable in frigate / HA. This will come as a separate action in a future release

@tbrausch
Copy link

OK, thx!

@tbrausch
Copy link

tbrausch commented Jun 15, 2022

In case anyone is interested, thought I would share a simple workaround that I am currently using to get around this issue. Just to reiterate, I am running HA on a Celeron processor with 4 cameras and object detection at 1920x1080, 3FPS (my cameras do not support substreams). This takes a significant amount of CPU resources, so sometimes I want to disable 2 of the cameras while other times I want all 4 cameras active (when I am away, for example).

Workaround:
I created 2 shell commands which simply copy two different frigate configuration files to the default file frigate.yaml. I then have two scripts called frigate2 and frigate4 that call the appropriate shell command and then restart frigate. Not elegant, but works perfectly.

frigate4:
  alias: Restart Frigate with 4 Active Cameras
  sequence:  
  - service: shell_command.frigate4
  - service: hassio.addon_restart
    data:
      addon: "ccab4aaf_frigate-beta"
shell_command:
  frigate2: cp /config/frigate-2.yaml /config/frigate.yaml
  frigate4: cp /config/frigate-4.yaml /config/frigate.yaml

@chatziko
Copy link

+1, the abilitity to enable/disable cameras is hugely useful (it is very common for several cameras to be used only at night or when away).

Even better: ideally, frigate could automatically switch off its input sources when not used. Each camera can have multiple inputs for different roles (record, detect, rtmp). When each role is inactive, the corresponding input is not needed, so it should be switched off to save bandwidth/cpu. If no role is active, then the camera should not consume any resources at all.

@chatziko
Copy link

Building on the workaround of @tbrausch for disabling cameras, instead of completely removing a camera from the confg, it's possible to give it a "dummy" input like the one below. black.mp4 is a dummy mp4 containing a few minutes of a black 2x2 frame at 1 fps.

With this config, ffmpeg takes ~1% CPU on my rpi4, and of course consumes no bandwidth. The advantage is that the camera is still visible in the UI, we can browse events/recordings, etc.

cameras:
  my_camera:
    ffmpeg:
      inputs:
        - input_args: "-re -stream_loop -1 -fflags +genpts"
          path: "/config/black.mp4"
          roles:
          - rtmp
          - record
          - detect
    detect:
      width: 2
      height: 2
      fps: 1
      enabled: False
    record:
      enabled: False

@tbrausch
Copy link

Great idea - can you upload your black.mp4 file and I will give it a try?

@chatziko
Copy link

Sure: https://user-images.githubusercontent.com/362089/178692766-3a394ad7-e027-48cb-b2c3-1c6d7be2370e.mp4

(It was created with ffmpeg -stream_loop -1 -i black.png black.mp4 where black.png is 2x2 black image. I tried directly using black.png as an input but frigate didn't like it.)

@sshort1955
Copy link

Brilliant chatziko. With my 4 cameras the "black" yml version runs @ 1.8% while running during the day

@chatziko
Copy link

Nice! You can also try this version, I remember I made some change that made it faster to decode (although 1.8% seems already pretty optimal)

https://user-images.githubusercontent.com/362089/181588415-04444470-551a-45da-b048-da82614a2acb.mp4

@samgundel
Copy link

samgundel commented Aug 19, 2022

I really liked the idea of replacing the config and getting rid of the cameras. Nevertheless I am running Home Assistant on VirtualBox VDI and Frigate via docker-compose on the host.

What I end up doing was the following:

  • listening via mqtt on my host for a message to swap the files
  • swap the files via home assistant automation
  • restart frigate via mqtt

On Host

#!/usr/bin/python3
import paho.mqtt.client as mqtt
import shutil

HOST = "192.168.X.X"
USER = "frigate_swapper"
PASSWORD = "ABC"

CLIENT = "FrigateSwapper"
PORT = 1883
TOPIC = "frigate/swapper/config"
TARGET_CONFIG = "config.yaml"

config = {
    "2" : "two-cameras.yaml",
    "4" : "all-cameras.yaml"
}

def on_message(client, userdata, message):
    payload = str(message.payload.decode("utf-8"))
    print("Payload %s received" % payload)
    if payload in config:
        shutil.copyfile(config[payload], TARGET_CONFIG)
    else:
        print("config %s not found for frigate" % payload)

client = mqtt.Client(CLIENT)
client.on_message=on_message

print("connecting to Home Assistant MQTT Broker")
client.username_pw_set(USER, PASSWORD)
client.connect(HOST, PORT)
client.on_message=on_message

print("subscribing to topic %s" % TOPIC)
client.subscribe(TOPIC)
client.loop_forever()

On Home Assistant

alias: Frigate - Enable Only Day Cameras
trigger:
  - platform: time
    at: "07:00:00"
condition: []
action:
  - service: mqtt.publish
    data:
      topic: frigate/swapper/config
      payload: "2"
  - delay:
      hours: 0
      minutes: 0
      seconds: 1
      milliseconds: 0
  - service: mqtt.publish
    data:
      topic: frigate/restart
mode: single

@vakilando
Copy link

Hello together,
first: thank you @tbrausch and @chatziko - great idea!
I'm also replacing the frigate config.yaml to get rid of the indoor cameras when I'm at home and I'm using the black.mp4 from @chatziko.
I do this via a home assistant presence automation because I don't want my indoor cams on when I'm at home.

It works like a charm....but I still have some little problems:

  • Frigate's birdseye almost always shows just a white picture when cameras are "deactivated"
  • Frigate's Camera view shows the "deactivated" cameras as black squares (1:1 and not an 16:9)
  • the Frigate Card (https://github.com/dermotduffy/frigate-hass-card) doesn't work anymore with "deactivated" cameras

See the pictures to better unsderstand what I mean:

Frigate's birdseye
fg-be
Frigate's Camera
fg-square
Frigate Card in Home Assistant
fg-cust-card

Does anybody have the same problems?

@NickM-27
Copy link
Collaborator

Frigate's Camera view shows the "deactivated" cameras as black squares (1:1 and not an 16:9)

The filler video will be to be cropped to fit the same aspect ratio as your actual camera

@Redsandro
Copy link
Contributor

Redsandro commented Jan 5, 2023

@NickM-27 FYI the "Describe the solution you'd like" in this issue is really quite different from #4897. I think it's worth mentioning that the issue you just closed as a duplicate is specifically about turning on/off camera logs by plugging/unplugging them. Not through external software such as HA as discussed in this issue.

@krojew
Copy link

krojew commented Jul 5, 2024

Just stumbled upon the same use case - frigate eats a lot of resources when a camera is not needed, but there's no way to turn it off.

@PilaScat
Copy link

Any news on this? Maybe for Frigate 0.14?

@NickM-27
Copy link
Collaborator

Frigate 0.14 is already in beta, maybe 0.15 but it's hard to say at this point

@danishru
Copy link

In Frigate 0.14 there is a mention of enable\disable each camera, but it can't be done without restarting Frigate addon, as it is done for detection and recording. Maybe there is another way to turn off camera without restarting?

@NickM-27
Copy link
Collaborator

if there was, this would be closed

@Minims
Copy link

Minims commented Sep 16, 2024

In Frigate 0.14 there is a mention of enable\disable each camera, but it can't be done without restarting Frigate addon, as it is done for detection and recording. Maybe there is another way to turn off camera without restarting?

is there another way than edit the yaml file and set false to true the camera ?

@joshuisken
Copy link

joshuisken commented Sep 26, 2024

I automatically switch camera's on/off based on people present and night/day time. Filling up the logs and burning needles energy.
When a camera goes offline this is detected and the ffmpeg process is restarted after a configurable retry-interval.

A suggestion: could you initiate a retry via a MQTT message for each camera, additional to the retry-interval? That allows for a (very) long retry-interval and still a fast wake-up.

Additionally: consider to provide the state (online/offline/...) of each camera via MQTT.

@miketyson666
Copy link

@halsafar could you please share your python script 😊?

@halsafar
Copy link

Hey @miketyson666 - A few steps to make this work. This also assumes you have Frigate working with MQTT. If you do not have Frigate connected to an MQTT server then you can manually reboot it using a shell script.

In Home Assistant configuration.yaml:

shell_command: !include shell_commands.yaml

In Home Assistant shell_commands.yaml I have:

frigate_camera_mod: "python /config/shell_commands/frigate_mod.py {{ arguments }}"

Here is the python script itself frigate_mod.py located in Home Assistant /config/shell_commands/frigate_mod.py:

#!/usr/bin/env python
import argparse
import sys
import yaml

parser = argparse.ArgumentParser()

parser.add_argument('--update-camera-state',
                    action='append',
                    help='Update camera states in the form of camera_name:True or camera_name:False',
                    required=True)
parser.add_argument('--frigate-conf-file',
                    help='Location of Frigate config.yml file',
                    default='/frigate/config.yml',
                    required=False)

args = parser.parse_args()

# Load Frigate Config
print(f'Loading Frigate Config: {args.frigate_conf_file}')
with open(args.frigate_conf_file, 'r') as file:
    frigate_config = yaml.safe_load(file)

for camera_state in args.update_camera_state:
    camera_state_split = camera_state.split(':')
    if len(camera_state_split) != 2:
        print(f'Invalid state {camera_state}')
        continue

    if camera_state_split[0] in frigate_config['cameras']:
        print(f'Updating camera [{camera_state_split[0]}] to [{camera_state_split[1]}]')
        frigate_config['cameras'][camera_state_split[0]]['enabled'] = camera_state_split[1].lower() == 'true'
    else:
        print(f'Unable to find camera [{camera_state_split[0]}], could not update...')

# Save Frigate Config
print(f'Saving Frigate Config: {args.frigate_conf_file}')
with open(args.frigate_conf_file, 'w') as file:
    yaml.dump(frigate_config, file, sort_keys=False)

Restart/Reload Home Assistant.

Now in a Home Assistant Automation you can do something like this:
image

Finally you need to reboot Frigate which can be done via MQTT:
image

Good luck!

@Minims
Copy link

Minims commented Oct 15, 2024

thanks @halsafar , it seems working great :-)

@miketyson666
Copy link

Hey @miketyson666 - A few steps to make this work. This also assumes you have Frigate working with MQTT. If you do not have Frigate connected to an MQTT server then you can manually reboot it using a shell script.
Thanks @halsafar !

@kevzz01
Copy link

kevzz01 commented Nov 14, 2024

Hey @miketyson666 - A few steps to make this work. This also assumes you have Frigate working with MQTT. If you do not have Frigate connected to an MQTT server then you can manually reboot it using a shell script.

In Home Assistant configuration.yaml:

shell_command: !include shell_commands.yaml

In Home Assistant shell_commands.yaml I have:

frigate_camera_mod: "python /config/shell_commands/frigate_mod.py {{ arguments }}"

Here is the python script itself frigate_mod.py located in Home Assistant /config/shell_commands/frigate_mod.py:

#!/usr/bin/env python
import argparse
import sys
import yaml

parser = argparse.ArgumentParser()

parser.add_argument('--update-camera-state',
                    action='append',
                    help='Update camera states in the form of camera_name:True or camera_name:False',
                    required=True)
parser.add_argument('--frigate-conf-file',
                    help='Location of Frigate config.yml file',
                    default='/frigate/config.yml',
                    required=False)

args = parser.parse_args()

# Load Frigate Config
print(f'Loading Frigate Config: {args.frigate_conf_file}')
with open(args.frigate_conf_file, 'r') as file:
    frigate_config = yaml.safe_load(file)

for camera_state in args.update_camera_state:
    camera_state_split = camera_state.split(':')
    if len(camera_state_split) != 2:
        print(f'Invalid state {camera_state}')
        continue

    if camera_state_split[0] in frigate_config['cameras']:
        print(f'Updating camera [{camera_state_split[0]}] to [{camera_state_split[1]}]')
        frigate_config['cameras'][camera_state_split[0]]['enabled'] = camera_state_split[1].lower() == 'true'
    else:
        print(f'Unable to find camera [{camera_state_split[0]}], could not update...')

# Save Frigate Config
print(f'Saving Frigate Config: {args.frigate_conf_file}')
with open(args.frigate_conf_file, 'w') as file:
    yaml.dump(frigate_config, file, sort_keys=False)

Restart/Reload Home Assistant.

Now in a Home Assistant Automation you can do something like this: image

Finally you need to reboot Frigate which can be done via MQTT: image

Good luck!

Would this work if I have Frigate and HA on a separate LXC container in Proxmox?

@halsafar
Copy link

Hey @kevzz01 - In my setup I have Frigate and HA in separate Docker containers. The only requirement is that the HA script can read/write the Frigate config.yaml file. This can be achieved in several ways (mount inside HA for example). I then use MQTT (mosquitto, another container) to manage the reboot (Frigate supports rebooting via MQTT). So you should be able to achieve similar in Proxmox as long as HA can access the Frigate config.yaml file.

@rmi1974
Copy link

rmi1974 commented Nov 14, 2024

My dockerized frigate runs on a different physical host machine. I have a homelab setup with multiple servers, each running several dozen docker containers. It's not a too uncommon setup. Putting HA and frigate on the same host or remote mounting folders (and bind mount them into containers) for this "dynamic" yaml workaround is not an option for me.

Like many others I'm waiting as well since a long time for a proper solution implemented in frigate. It's a pity that such an essential feature wasn't foreseen in the original design.

@halsafar
Copy link

Yah it would be much better if Frigate offered this as a core feature. I really think MQTT enable/disable cameras is the way to go.

@menkej
Copy link
Contributor

menkej commented Dec 9, 2024

MQTT enable/disable cameras is the way to go.

Now I also came up with this use case that I wanted to use an old webcam just temporarily for the time we are away. I know about enabling/disabling via config file but really expected that it's also already available via MQTT. So I support this Idea!

@ImNoahDev
Copy link

+1 for this

@MaxRower
Copy link

Still waiting for this feature!

@derjoerg
Copy link

+1 for this

I also have - especially indoor - cameras, which are only on while I'm away and otherwise they are POE switched-off and I want to get rid of all the error-messages.

As frigate and HA are running on different machines in my setup I combined the workarounds from @kevzz01 and @samgundel

On the frigate-host I created a camera_handling.py script in /config:

#!/usr/bin/python3

import logging
import sys

import paho.mqtt.client as mqtt
import yaml

HOST = "192.168.x.y"
PORT = 1883
USER = "MQTT_USER"
PASSWORD = "MQTT_PASSWORD"

CLIENT = "FrigateSwapper"
TOPIC = [("frigate/swapper/config", 0), ("frigate/swapper/exit", 0)]

CONFIG_FILE = "/config/config.yml"

FIRST_RECONNECT_DELAY = 1
RECONNECT_RATE = 2
MAX_RECONNECT_COUNT = 12
MAX_RECONNECT_DELAY = 60


def on_connect(client, userdata, flags, rc, properties):
    if rc == 0 and client.is_connected():
        logging.info('Connected to MQTT Broker!')
        client.subscribe(TOPIC)
    else:
        logging.info(f'Failed to connect, return code {rc}')

def on_disconnect(client, userdata, rc, properties):
    logging.info(f'Disconnected with result code: {rc}')
    reconnect_count, reconnect_delay = 0, FIRST_RECONNECT_DELAY

    while reconnect_count < MAX_RECONNECT_COUNT:
        logging.info(f'Reconnecting in {reconnect_delay} seconds...')
        time.sleep(reconnect_delay)

        try:
            client.reconnect()
            logging.info('Reconnected successfully!')
            return
        except Exception as err:
            logging.error(f'{err}. Reconnect failed. Retrying...')

        reconnect_delay *= RECONNECT_RATE
        reconnect_delay = min(reconnect_delay, MAX_RECONNECT_DELAY)
        reconnect_count += 1

    logging.info(f'Reconnect failed after {reconnect_count} attempts. Exiting...')

def on_message(client, userdata, message):
    payload = str(message.payload.decode("utf-8"))

    if message.topic == "frigate/swapper/exit" and payload == "yes":
        logging.info('EXIT')
        sys.exit()
    else:
        restart = False
        logging.info(f'Payload {payload} received')
        camera_states = payload.split(' ')

        if len(camera_states) > 0:
            with open(CONFIG_FILE, 'r') as file:
                frigate_config = yaml.safe_load(file)

            for camera_state in camera_states:
                logging.info(camera_state)
                camera_state_split = camera_state.split(':')

                if len(camera_state_split) != 2:
                    logging.info(f'Invalid state {camera_state}')
                    continue

                camera = camera_state_split[0]
                state = camera_state_split[1].lower() != 'false'

                if camera in frigate_config['cameras']:

                    if 'enabled' in frigate_config['cameras'][camera]:
                        current_state = frigate_config['cameras'][camera]['enabled']

                        if current_state is state:
                            logging.info(f'Update of camera[{camera}] to [{state}] not necessary')
                            continue

                    logging.info(f'Updating camera [{camera}] to [{state}]')
                    frigate_config['cameras'][camera]['enabled'] = state
                    restart = True
                else:
                    logging.info(f'Unable to find camera[{camera}], could not update...')

        if restart:
            logging.info(f'Saving Frigate Config: {CONFIG_FILE}')
            with open(CONFIG_FILE, 'w') as file:
                yaml.dump(frigate_config, file, sort_keys=False)

            logging.info('Restart of Frigate necessary')
            client.publish('frigate/restart')

def connect_mqtt():
    client = mqtt.Client(client_id=CLIENT, callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
    client.username_pw_set(USER, PASSWORD)
    client.on_connect = on_connect
    client.on_message=on_message
    client.connect(HOST, PORT, keepalive=120)
    client.on_disconnect = on_disconnect
    return client

def run():
    logging.basicConfig(format='%(asctime)s - %(levelname)s: %(message)s', level=logging.DEBUG)
    client = connect_mqtt()
    client.loop_forever()

if __name__ == '__main__':
    run()

This script also handles the restart of frigate, IF necessary.

I made this script executable and added to the crontab of user root
@reboot /config/camera_handling.py

In HA, when I'm away, I execute first the POE switch-on, wait a minute to let the camera become available and then execute the following action:

action: mqtt.publish
data:
  topic: frigate/swapper/config
  payload: hallway:true

(it is also possible to modify several cameras with one action, just add each camera to the payload, separated by a blank space, e.g. payload: hallway:false basement:true)

When I return I execute first the action below and then the POE switch-off:

action: mqtt.publish
data:
  topic: frigate/swapper/config
  payload: hallway:false

@zandhaas
Copy link

+10 for a switch in frigate to be able to disable / enable a camera dynamicaly

@filipefumaux
Copy link

Another +1 here. I have a camera in the baby room I want to turn off from time to time without having errors in the logs

@ludditus-RPI
Copy link

ludditus-RPI commented Feb 7, 2025

Definitely would love this. I use scenes in HA/Node red to toggle my indoor cameras off (via Sonoff mini-Usb plugs) when we're inside/awake. It would be nice to avoid filling the the frigate logs with ffmpeg errors and I could signal the app when to ignore a missing video stream.

@KennethLavrsen
Copy link

This is also a feature I really would appreciate. I run only 2 cameras out of 6 when I am home which is 60% of the time. I can see a significant drop in power consumption when I turn off the 4 cameras. It is annoying having to script swapping config files and restarting frigate.

@miketyson666
Copy link

Yes, please, please add this feature. Restarting every time after applying a script to disable cameras is a pain! Being able to disable cameras on the fly will be a real must!

@Sasq2002
Copy link

Yet another vote for, we need this on a privacy perspective for the internal cameras

@NickM-27
Copy link
Collaborator

There is no need to continue to advocate for this feature, it is pinned and will be implemented

@miketyson666
Copy link

Thanks !! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request pinned
Projects
None yet
Development

No branches or pull requests