Generic IP Camera rtsp setup without still_image_url

Hi, I have a door camera from Steinel (L620 CAM) which only provides an rtsp url and no still_image_url due to security reasons and to comply to GDPR (German data protection rights) because the still_image_url does not have password protection.

This of course breaks the Generic IP Camera platform which has the still_image_url as a required argument.

My actual solution is to use the ffmpeg platform im my camera.yaml file

  - platform: ffmpeg
    name: L620
    input: -rtsp_transport tcp -i rtsp://192.xxx.xxx.xxx/user=xxx&password=xxx&channel=1&stream=1.sdp

This now works for the still image part but I am not able to access the video stream in home assistant.

I assume that more and more ip cameras will skip the unprotected still_image_url an we need to come up with a general concept how to integrate generic ip cameras which only provide the rtsp url.

Does anyone already have some insights into this?

3 Likes

The way I resolved this was kind of a kludge, but it works. I actually deployed a small virtual machine running Zoneminder, and then fed the RTSP stream into that. Then, I enabled the Zoneminder integration in Home Assistant. That way my L620 showed up as a camera entity in HA without any further configuration.

I also found that the 0.sdp is the HD stream and 1.sdp is the SD stream. Was a bit miffed at first by the quality, until I noticed I had enterd 1.sdp instead of 0.sdp.

Hi Per,

I very much appreciate your comment. If there would be a docker based zone minder add-on ready to be installed with home assistant it would be perfect. My RPI 4 has lots of free Ressourcen to run this for just one camera

Hi, I came up with a workable solution for me. I just purchased a Amcrest ZenCam M1B this weekend and hadn’t done my homework :-). This camera does support rtsp but does not appear to provide a still image url, nor does it appear to provide any http or https endpoints that I’ve been able to find (please correct me if anyone comes across this and knows better). Here’s what I did to bring it into Home Assistant with still image and stream support:

  1. The machine and user running home assistant will need an ffmpeg binary.
  2. In configuration.yaml you’ll need the camera and a shell command:
camera:
  - platform: generic
    name: "ZenCam"
    still_image_url: https://hass_ip/local/images/zencam.jpg
    stream_source: rtsp://admin:[email protected]:554/cam/realmonitor?channel=1&subtype=0

shell_command:
  zencam_still: '/home/homeassistant/grab_zencam_frame.sh'

The shell command:

ffmpeg -y -loglevel fatal -rtsp_transport tcp -i rtsp://admin:[email protected]:554/cam/realmonitor?channel=1\&subtype=0 -frames:v 2 -r 1 -s 1280x720 /home/homeassistant/.homeassistant/www/images/zencam.jpg
exit 0

And finally an automation to update the still image every 5 seconds:

- id: '1613174844680'
  alias: Update ZenCam Still
  description: ''
  trigger:
  - platform: time_pattern
    seconds: /5
    hours: '*'
    minutes: '*'
  condition: []
  action:
  - service: shell_command.zencam_still
    data: {}
  mode: single

Some notes:
You’ll obviously have to change for your specific camera url and username/passwords, also I’ve simplified the filename, but since Home Assistant serves /local paths without authentication, it would probably be a good idea to add a bunch of random-ish characters to the still image name so it can’t be easily guessed by bots/hackers. I’m going to be using this particular camera in a location where I have no privacy concerns, but it should certainly be considered risky if you use this workaround. There are probably better ways to secure the image and I’m always open to hearing about them or any other ways to improve things :slight_smile:

2 Likes

@gonzotek Your solution is awesome, thank you so much!
Just as heads up for those who run hass.io in Docker container like me, it’s better not install ffmpeg via apk since it’ll disappear if the container restarts. I use some pre-compiled ffmpeg binary which can be easily found on google.

Thanks gonzotek
this is very much appreciated

regards
Chris

1 Like

newby question. where do you write the:

ffmpeg -y -loglevel fatal -rtsp_transport tcp -i rtsp://admin:[email protected]:554/cam/realmonitor?channel=1\&subtype=0 -frames:v 2 -r 1 -s 1280x720 /home/homeassistant/.homeassistant/www/images/zencam.jpg
exit 0

It needs to be in an executable file accessible to the homeassistant user of the OS; I placed mine in the user’s home directory in my raspbian venv install:

shell_command:
  zencam_still: '/home/homeassistant/grab_zencam_frame.sh'

This might not be the correct location for other install types(docker, supervised, Home Assistant OS). It would probably work to use the config directory(this is where configuration.yaml and other important files are stored, be very careful about working in it) or a subdirectory in it. You also need to set the proper permissions on the file (executable by the same user under which the main home assistant process runs).

If it can help someone, I did it that way on my system:

shell_command:
  webcam_still_cmd1: 'ffmpeg -y -loglevel fatal -rtsp_transport tcp -i rtsp://admin:[email protected]/live -frames:v 2 -r 1 -s 1280x720 www/garage.jpg'
  webcam_still_cmd2: 'ffmpeg -y -loglevel fatal -rtsp_transport tcp -i rtsp://admin:[email protected]/live -frames:v 2 -r 1 -s 1280x720 www/backyard.jpg'
  webcam_still_cmd3: 'ffmpeg -y -loglevel fatal -rtsp_transport tcp -i rtsp://admin:[email protected]/live -frames:v 2 -r 1 -s 1280x720 www/driveway.jpg'

FYI if you have some generic IP-CAM-100, the still image url is:
http://192.xxx.xxx.xxx/?action=snapshot

STEP-BY-STEP SOLUTION

For all who also struggle on this, took me now 4 hours to get a solution for HOME ASSISTANT SUPERVISED (no docker, no HA-OS, …)

ffmpge musst be installed

sudo apt-get install ffmpeg

create a script directory

sudo mkdir /usr/share/hassio/homeassistant/script

create a script in the directory

sudo nano /usr/share/hassio/homeassistant/script/update_cam_still_image.sh

past the following code to the script (replace the variables , with your values. Also replace the output filename (still_image.jpg) with one you like. Note: The output directory is a relativ path to Home Assistant config folder, so it starts with www/images/ (don’t know why they made this so confusing… absolut paths would be better, but they choose this solution)

/usr/bin/ffmpeg -y -loglevel fatal -rtsp_transport tcp -i rtsp://<user>:<password>@<camera-url> -frames:v 2 -r 1 -s 1280x720 www/images/still_image.jpg

make the shell script executable

sudo chmod +x /usr/share/hassio/homeassistant/script/update_cam_still_image.sh

create a images directory

sudo mkdir /usr/share/hassio/homeassistant/www/images

create a shell script yaml file. (I do my config in separate files)

sudo nano /usr/share/hassio/homeassistant/shell_command.yaml

past this code to the yaml file. (NOTE there are empty spaces before first char! It is also very confusing, that the path is relativ to /usr/share/hassio/homeassistant. Don’t know why they choose the way not to use absolut paths.)

     cam_still: /config/script/update_cam_still_image.sh

edit configuration.yaml and add the following (can be done by UI or if you prefer also using nano)

shell_command: !include shell_command.yaml

restart homeassistant (can be done from the UI)

create an automation to update the image every 5 seconds. This can also be done by UI. Create a new automation.

Select “Time pattern” as trigger.

Hours: *
Minutes: *
Seconds: /5

As Action use “Call a service” and select the “shell_command.cam_still”

OR if you prefer, here is the yaml script for the automation:

alias: Camera Update Still
description: 
  Runs a shell script, which updates the still image for the camera and saves it to
   /usr/share/hassio/homeassistant/www/images/

  The picture can be used in a generic camera using the following URL
  http://localhost/local/images/still_image.jpg
trigger:
  - platform: time_pattern
    seconds: /5
    hours: "*"
    minutes: "*"
condition: []
action:
  - service: shell_command.cam_still
    data: {}
mode: single