rroller / dahua

Dahua Camera and Doorbell Home Assistant Integration
MIT License
382 stars 73 forks source link

ability to download recorded videos #97

Open blademckain opened 2 years ago

blademckain commented 2 years ago

Is your feature request related to a problem? Please describe. At the moment there is no home assistant integration that can interact with the dahua camera to view the recorded videos. It would certainly be innovative to have a quick and easy way to access recorded videos

Describe the solution you'd like Using API 4.11.13 Download Media File between Times you can download the videos

Additional context a working example here https://mlog.club/article/3576624

rroller commented 2 years ago

Thanks for the example. Do you know of an example Home Assistant integration that allows you to download files? I'm not sure I've seen anything like that before (or to show video clips). One problematic thing is that the native files that Dahua produce are .dav files. DAV is a modified mp4 format and it's not going to play without a conversion. I most likely won't be able to support this but will keep an eye out if I think it can be done easily.

GaryOkie commented 2 years ago

I've just confirmed the ability to download MP4 files from the Amcrest AD410 doorbell SD-Card.

You can capture "NewFile" events from the camera, where the data contains the filename.
"File": " \/mnt\/sd\/2021-10-04\/001\/dav\/10\/10.56.56-10.57.44[M][0@0][0].mp4 "

(Note that there will also be a newfile event for the snapshot, same format as above, but .jpg extension)

To download this file, remove all the backslashes from the filename and issue this command: http://admin:password@ip/cgi-bin/RPC_Loadfile/mnt/sd/2021-10-04/001/dav/10/10.56.56-10.57.44[M][0@0][0].mp4

There is a general purpose HASS Downloader integration. I tried to use this downloader service to issue the above http command but it failed with a 401 (authentication) error. My guess is that it only tries basic authentication and doesn't retry with digest.

BTW - I have an old Dahua NVR that has been updated with the latest firmware and it provides a new option to download files in MP4 format. It may be converting DAV to MP4 on the fly, but I will do some testing to see.

It might be possible to create a shell command to run "curl --digest -u admin:password/http://...etc" and pass the parsed filename to it. Or we could look at the downloader code and see what it would take for a PR to use digest.

BTW - I would like to have the ability to stream recorded files directly from the camera SD-Card or NVR rather than download them. This command should allow it:

rtsp://admin:password@\<ip>:554/mnt/sd/2021-10-04/001/dav/10/10.56.56-10.57.44[M][0@0][0].mp4

But when I tested this using VLC network stream, it ignored the file and just streamed the live video with no errors. Weird.

EDIT: quick look at downloader source - it's simply using: req = requests.get(url, stream=True, timeout=10)

To support Digest, it would need an option such as: requests.get(url, auth=HTTPDigestAuth('user', 'pass'), stream=True, timeout=10)

But in order to provide new options like this, someone has to also write the new UI config flow to add them.

EDIT 2: Feature Request submitted... https://community.home-assistant.io/t/downloader-integration-lacks-authentication-options/344244

GaryOkie commented 2 years ago

Other than my AD410 doorbell, none of my Dahua cameras have an SD-Card as they record only on the NVR. Unfortunately, I discovered that there is no "NewFile" event raised when a motion event occurs and the video is recorded to the NVR. This seems to only occur if an SD_Card is installed.

So if the OP wants to be able to download video from the SD-Card and not the NVR, there is a way forward that should not require any changes to the Dahua integration.

GaryOkie commented 2 years ago

More discovery... the DAV files recorded on the Dahua NVR are from the constant stream of each camera channel. The recordings are written as individual hour-long DAV files. If you use the NVR Backup to USB drive facility, you will see these hour-long recordings which can be saved as DAV (or MP4 in the newer firmware).

Here is an example of the NVR filepath/name created: `FilePath=/mnt/dvr/2021-10-04/4/dav/09/0/3/438066/09.00.02-10.00.02[R][0@0][0].dav

You can search the NVR for available files, but it's tricky since it takes 3 separate commands which require a session object id that is temporary...

<nvr_ip>/cgi-bin/mediaFileFind.cgi?action=factory.create returns (valid only for a minute)

<nvr_ip>/cgi-bin/mediaFileFind.cgi?action=findFile&object=<object_id>&condition.Channel=5&condition.StartTime=2021-10-4%2010:00:00%20&condition.EndTime=2021-10-4%2012:00:00

<nvr_ip>/cgi-bin/mediaFileFind.cgi?action=findNextFile&object=<object_id>

items[0].VideoStream=Main
items[0].Channel=4
items[0].Type=dav
items[0].StartTime=2021-10-04 09:00:02
items[0].EndTime=2021-10-04 10:00:02
items[0].Disk=3
items[0].Partition=3
items[0].Cluster=438066
items[0].FilePath=/mnt/dvr/2021-10-04/4/dav/09/0/3/438066/09.00.02-10.00.02[R][0@0][0].dav
items[0].Length=953417728
items[0].Flags[0]=Timing
items[0].CutLength=530432

I was not successful using the http RPC_Loadfile command to directly download this file. It immediately fails with a "file incomplete" error. Not that I wanted a huge hour long DAV file that would have to be converted and extracted by the desired time slice.

Bottom line - a facility to download recorded videos from the NVR would be very complicated and unwieldly in my view. Just not worth it. On the other hand, accessing them from the camera's SD-Card is much simpler given the specific filename obtained from the "NewFile" event.

blademckain commented 2 years ago

Hi guys, I report the configuration I used to solve this problem (if it were integrated in this component it would be fantastic, but I know it's complicated)

Prerequisite: u have to enable ffmpeg in your configuration.yaml

  1. Automation for video download
    
    input_text:
    last_recorded_video:
    name: Last Recorded Video
    max: 255
    last_snapshot_camera:
    name: Last SnapShot Camera
    max: 255

shell_command: download_recorded_dav: "curl --digest --user {{tvcc_user}}:{{tvcc_pass}} -o /config/www/tmp/last_recorded.dav -g {{tvcc_url}}" download_snapshot_camera: "curl --digest --user {{tvcc_user}}:{{tvcc_pass}} -o /config/www/tmp/last_snapshot.jpg -g {{tvcc_url}}" convert_recorded_dav: "bash /config/www/tmp/convertdav.sh"

- alias: "Rilevazione video registrato - Telecamere"
  mode: queued
  variables:
    tvcc_user: !secret tvcc_user
    tvcc_pass: !secret tvcc_pass
  trigger:
     - platform: event
       event_type: dahua_event_received
       event_data:
          Code: NewFile
          action: Pulse
  condition:
    # Only trigger the alarm if it's armed
    condition: or
    conditions:
      - condition: state
        entity_id: alarm_control_panel.alarm
        state: armed_home
      - condition: state
        entity_id: alarm_control_panel.alarm
        state: armed_night
      - condition: state
        entity_id: alarm_control_panel.alarm
        state: armed_away
      - condition: state
        entity_id: alarm_control_panel.alarm
        state: triggered
  action:
    - choose:
        - conditions: "{{ '.dav' in trigger.event.data.data.File }}"
          sequence: 
            - service: input_text.set_value
              data_template:
                entity_id: input_text.last_recorded_video
                value: >
                  {% if trigger.event.data.name == 'TVCC2' %}
                  {% set tvcc_ip = '192.168.x.44' %}
                  {% elif trigger.event.data.name == 'TVCC4' %}
                  {% set tvcc_ip = '192.168.x.42' %}
                  {% elif trigger.event.data.name == 'TVCC5' %}
                  {% set tvcc_ip = '192.168.x.41' %}
                  {% endif %}
                  {{ 'http://'~tvcc_ip~'/cgi-bin/RPC_Loadfile/'~trigger.event.data.data.File }}
            - service: shell_command.download_recorded_dav
              data_template:
                tvcc_user: "{{tvcc_user}}"
                tvcc_pass: "{{tvcc_pass}}"
                tvcc_url: "{{ states('input_text.last_recorded_video') }}"
            - service: shell_command.convert_recorded_dav
        - conditions: "{{ '.jpg' in trigger.event.data.data.File }}"
          sequence:
            - service: input_text.set_value
              data_template:
                entity_id: input_text.last_snapshot_camera
                value: >
                  {% if trigger.event.data.name == 'TVCC2' %}
                  {% set tvcc_ip = '192.168.x.44' %}
                  {% elif trigger.event.data.name == 'TVCC4' %}
                  {% set tvcc_ip = '192.168.x.42' %}
                  {% elif trigger.event.data.name == 'TVCC5' %}
                  {% set tvcc_ip = '192.168.x.41' %}
                  {% endif %}
                  {{ 'http://'~tvcc_ip~'/cgi-bin/RPC_Loadfile/'~trigger.event.data.data.File }}
            - service: shell_command.download_snapshot_camera
              data_template:
                tvcc_user: "{{tvcc_user}}"
                tvcc_pass: "{{tvcc_pass}}"
                tvcc_url: "{{ states('input_text.last_snapshot_camera') }}"
      default: []

2. Bash script "convertdav.sh" for convert video

!/bin/bash

ffmpeg -y -i /config/www/tmp/last_recorded.dav -c copy -max_muxing_queue_size 9999 /config/www/tmp/last_recorded.mp4 2> /config/www/tmp/last_recorded.log

rroller commented 2 years ago

@blademckain that's really cool. And yes, it's pretty complicated to build into the integration. Will keep this open for now and I'll think about it some more.

tunip commented 2 years ago

Have you already been able to think about it a little :-)?

junalmeida commented 2 years ago

@rroller Not sure if this helps but the native Nest integration can show recent video recordings on media source page of home assistant.

image

Xbox integration does that as well for my recorded game clips.

augustodinizl commented 1 year ago

@rroller Not sure if this helps but the native Nest integration can show recent video recordings on media source page of home assistant.

image

Xbox integration does that as well for my recorded game clips.

Tapo integration algo does that: https://github.com/JurajNyiri/HomeAssistant-Tapo-Control

augustodinizl commented 1 year ago

Thanks for the example. Do you know of an example Home Assistant integration that allows you to download files? I'm not sure I've seen anything like that before (or to show video clips). One problematic thing is that the native files that Dahua produce are .dav files. DAV is a modified mp4 format and it's not going to play without a conversion. I most likely won't be able to support this but will keep an eye out if I think it can be done easily.

@rroller , i've already used that one (https://github.com/arthar360/TaniDVR ) with a rtsp mini server to stream the video from a old dahua/intelbras DVR into home assistant, maybe it helps

thedeadliestcatch commented 1 year ago

This would be pretty useful to retrieve the associated file with the last event when possible, as camera snapshots will inevitably lag.

dehooge commented 7 months ago

Hey @blademckain is your solution still working? Trying to copy your automation but I can get it working. Probably something easy I'm missing but I'm an idiot at these things. I get this error in logs, what did I miss to set up?

Template variable error: 'dict object' has no attribute 'event' when rendering '{{ '.dav' in trigger.event.data.data.File }}' Template variable error: 'dict object' has no attribute 'event' when rendering '{{ '.jpg' in trigger.event.data.data.File }}'

Edit: ok so stupid as I said. The problem is of course (?) I don't get the NewFile event from the cameras. How do you get this? I get VideoMotion and so on but no NewFile

augustodinizl commented 7 months ago

Thanks for the example. Do you know of an example Home Assistant integration that allows you to download files? I'm not sure I've seen anything like that before (or to show video clips). One problematic thing is that the native files that Dahua produce are .dav files. DAV is a modified mp4 format and it's not going to play without a conversion. I most likely won't be able to support this but will keep an eye out if I think it can be done easily.

in the https://github.com/arthar360/TaniDVR repo, are a plugin that converts dhav to mkv video, maybe it helps even better