Camera Service To Stop Recording

It is not a silly question. You are the only silly one around here

We need this feature.
My case is that I want to start recording on alarm pending state and stop it when alarm is disarmed or after some timeout e.g. 20 minutes (it should record entire potential break in)

1 Like

Yes, it’s a must to have this feature.

I’m intrested too.

I’m intrested too.

same for me. This would help me implement a more custom object detection system.

Stop recording command for camera would be useful, the only way I found to control this is to use the
lookback feature of the camera intergration

So detect motion > start a timer > wait until no motion > stop timer (then calc the seconds of the timer)

For the camera record, I set the seconds of the timer for the lookback and duration. Seems to work fine and the recordings are correct length in regard to the time i see motion in the recordings.

But command to stop recording would be much simpler,

I just tested this with one of my cameras. In case people are unaware, the camera.record service is not done asynchronously. So lets say you have a script/automation which has a camera.record step for 30 seconds as step 1 and then 5 other actions after. The script/automation is going to sit in step 1 for 30 seconds until the recording has completed, only then will it move on to the 5 other actions.

Given this behavior my first thought was what if I just stop the script before the recording has completed using script.turn_off? That seems to mostly work. My script said to record 30 seconds of camera footage and then pop a persistent notification. I stopped the script almost immediately after starting it and ended up with a 10 second recording instead of a 30 second one and no notification. So it wasn’t instantly stopped but close enough. Kind of makes sense, stream is continuously working so it probably can only check for and process an external signal like that periodically.

Which means I think you can do this in HA today with a small tweak. Instead of including camera.record steps in your automations and scripts directly, create one script per camera like this:

record_example_camera:
  alias: Record from example camera
  variables:
    camera_id: camera.example
  <<: &stoppable-camera-script
    fields:
      filename:
        name: Filename
        description: Template of a Filename. Variable is entity_id. Must be mp4.
        required: true
        example: "/media/example_camera.mp4"
        default: "/media/example_camera.mp4"
        selector:
          text:
      duration:
        name: Duration
        description: Target recording length.
        example: 30
        default: 30
        selector:
          number:
            min: 30
            max: 3600
        lookback:
        name: Lookback
        description: Target lookback period to include in addition to duration. Only available if there is currently an active HLS stream.
        example: 30
        selector:
          number:
            min: 30
            max: 300
    sequence:
      if: "{{ lookback is not defined }}"
      then:
        service: camera.record
        data: &record-data
          entity_id: camera.example
          filename: "{{ filename }}"
          duration: "{{ duration | default(30) }}"
      else:
        service: camera.record
        data:
          <<: *record-data
          lookback: "{{ lookback }}"
record_example_camera_2:
  alias: Record from example camera 2
  variables:
    camera_id: camera.example_2
  <<: *stoppable-camera-script
record_example_camera_3:
  alias: Record from example camera 3
  variables:
    camera_id: camera.example_3
  <<: *stoppable-camera-script
...

The script has exactly the same inputs as the camera.record service except it doesn’t accept a target, that is hard-coded per script. I kept it as close to the original service by design. However if you want to enforce a strict pattern on filename then feel free to remove that input and have the script set it (like maybe /media/{{ camera_id }}_{{ now().strftime("%Y-%m-%dT%H:%M:%S") }}.mp4 for example). Or if you want to be able to use a higher duration/lookback from the GUI, change those selectors up.

Since all these scripts are basically identical I used YAML anchors to show how you could keep from repeating yourself a ton. If you don’t know what those are, this can help, scroll to node anchors. However those will only work in YAML only automations (i.e. ones which are not in your automations.yaml file). If you use the GUI editor you’ll need to just copy and paste the fields and sequence sections to each one.

Anyway once you have these scripts then simply replace all calls to camera.record with a call to the appropriate script. And when you want to stop recording then call script.turn_off on the script for the camera you want to stop recording for.

As an added bonus, scripts don’t have to be run synchronously. You can choose whether you want to wait for them to complete or not depending on how you call them. Which means with this script approach you can do your recording in the background and not have the automation sit and wait for it to finish.

2 Likes

there’s no hyperlink in your post :wink:

Weird. It looked like this for me:

But I guess it wasn’t actually a link. Seems I forgot the https:// at the front and it doesn’t like that. Anyway fixed now.

1 Like

@CentralCommand are you able to share the entire yaml with the stop script code? Could be really useful, Thanks!