Amcrest IP Camera Component Enhancements - PTZ control and audio streaming

Ok. The main difference is now the lock is only used to serialize snapshot commands. Prior to that it was being used to serialize all commands (well, except for audio.) Some extensive testing I did today seems to imply that only the snapshot commands need to be serialized.

BTW, I have these two models:

IP3M-943W
IP2M-841W

They’re both relatively new. One of the problems I’ll have with trying to make this work for everyone is I have no way to test with all the various models and firmware versions out there.

I have two of the same models: IP2M-841 (B and W). Adding your new components in didn’t appear to stop the errors on the log as they’re still coming. Also, RTSP was working in your previous update (looking at the files, I copied them over on 2/26), but now using your newest ones looks like RTSP stopped working. Not trying to pile on any issues or anything, but just wanted to report my usage if it’s at all helpful

I didn’t expect the latest changes to impact that.

So, I’ve never had any luck getting mjpeg or rtsp working. On the RPi3 I just assumed it was due to no native ffmpeg implementation. But I recently tried on an x86 VM running Linux Mint and I couldn’t get it working there either. Would you mind sharing your amcrest and ffmpeg config?

You say you copied them on 2/26. Do you know when? I made quite a few check-ins that day, the last being a little after 5 PM CST. It would be nice to know if it was just the last two check-ins (from today) was the cause, or if it was something earlier.

Also, you may have said, but what version of HA are you on?

No worries. In fact I’m indebted to you. Like I said, there’s no way I can test every combination, so the more feedback the better! :slight_smile:

Hi @pnbruckner ,

I’ve been using your custom Amcrest code (from last December) on a remote HA location still running Hassio 85. It has been working fine, including using RTSP in high res on a RPi3 The models I have are IP2M-841 and IP2M-851. The config is:

amcrest:
  - host: 192.168.xxx.xxx
    name: "LakeCam"
    username: user1
    password: !secret ipc_pw
    resolution: high
    stream_source: rtsp
    port: 80
    sensors:
       - ptz_preset
       - sdcard

Although RTSP works, it is not at all streaming well. That is mostly due to the remote location only having at best a 1Mbps uplink. The images update very slowly when viewed remotely, so no real practical advantage over snapshot.cgi’s I guess. I’m just pointing out that RTSP does actually work on an RPi3 running Hassio which has all the ffmpeg dependencies built-in.

I have been following the progress in merging your component in this thread. I sure hope it succeeds!

Yes, this refreshes my memory. It’s been a while since I tried to use RTSP on the RPi3.

The first problem I ran into was that I’m not using the standard RTSP port on my cameras. This is due to how the cameras work with some other apps, and the fact that I wanted to be able to access them from outside my LAN. If I port forwarded the standard ports to different external ports, these other apps wouldn’t work, because they would be told (by the camera) to use the standard RTSP port (because it didn’t know about the port forwarding), and then the app running outside the LAN would use the wrong port. So I had to configure each camera to use a different set of ports, and then these were forwarded as is.

The next problem was that the amcrest package had no provisions to specify a non-standard RTSP port number. I solved this problem by modifying the amcrest package to use a hard-coded port number for RTSP (as a temporary work-around.) Then it would at least work.

Yes, this was the next problem. I attributed it to the RPi3 ffmpeg install that was not optimized to use hardware acceleration. When I looked into how to get that to work on an RPi3, it appeared to be way more work than I was willing to attempt at the time.

So, due to these issues, I gave up and just stuck with snaphot streaming mode.

Yeah, the ffmpeg docs do say you have to roll your own to get HW acceleration on RPi3. What isn’t clear to me is if the devs have already done this for Hassio on RPi3 or not. They just say “For Hassio, the requirements have already been fulfilled”.

There was a 2 year old H.264 video feature request (with 21 votes) that indicated that the ffmpeg component was converting to the inefficient MJPEG stream for displaying on the front-end. I’m not sure that’s still the case.

Looking at the ffmpeg source now, and it is being actively supported by @awarecan and was updated a month ago to fix a ffmpeg v4 streaming issue.

In any event, attempting to get live streaming from multiple cameras on an RPi3 with or without HW acceleration over a less than 1Mbit uplink is pointless, and wasn’t really my objective for security monitoring anyway.

FWIW, I was talking about the ffmpeg program, not the HA ffmpeg component (which uses the ffmpeg program) or the ffmpeg camera platform (which uses the other two.) :slight_smile:

@GaryOkie FYI: a stream component is in develop, https://github.com/home-assistant/home-assistant/pull/21473

1 Like

Thanks @awarecan for making me aware! :+1:

This new video stream component sounds fantastic, especially being able to stream not only across any major browser, but to Chromecast devices as well. Wow, that will sure be useful!

Just have to hope that Dahua and Amcrest components are now, or will be soon, compatible. I can assist with testing and will follow this PR.

FYI, some fixes and improvements have already been added to the PyPI amcrest package and released as version 1.2.4. Also PR #21664 has been submitted that bumps the package version accordingly, and adds a thread lock to the camera_image method (which calls the amcrest package’s snapshot command) of the AmcrestCam class in homeassistant/components/amcrest/camera.py.

Assuming that gets accepted I’ll work on another incremental, small change.

EDIT: PR #21664 has been accepted and merged.

2 Likes

That’s great news (and great work!). I can see from all the back and forth that it hasn’t been easy. I could not tell though if merge will make it into version 89.0, including being available as a Hassio Amcrest 1.2.4 add-on. Do you know?

Well, first, even though the PR was accepted and merged, there’s now a suggestion for further changes. Not sure how that will go.

But, assuming this does eventually get fully merged, I have no idea if/when it will make it into an actual HA release. Also, if it does make a HA release, it will be part of the standard product, so there won’t be a need for an add-on or a custom component. Of course, I’ve only submitted a small part of all the enhancements I’ve made to the component so far. There’s no way to predict if they’ll accept all, or even any, of the PRs I still plan to submit with additional incremental improvements. So, in the mean time, at least I’m still using my custom component. :slight_smile:

1 Like

So far two PRs (21664 & 21720) have been submitted and accepted into HA’s dev branch. They serialize snapshot commands using a lock. They also bump the amcrest package to version 1.2.5. Together these changes should fix issues I believe have been around quite some time when using snapshot as the stream_source, which is the default.

Note that version 1.2.4 of the amcrest package was removed from pypi.org since it had a potential threading issue with requests.Session. If you happen to have an interim version of my custom amcrest HA component that points at 1.2.4, you should update to the latest.

These changes did not make the 0.89 release. If/when they make a HA release, I’ll post an update here.

UPDATE: Looks like the PRs made it into 0.90.0b0.

I’ve also updated my github repo accordingly.

The next HA PR I’m thinking of working on is to add the binary_sensor and at least deprecate the motion detector sensor, since the binary_sensor takes its place. I’m also thinking of removing the following attributes from the sensor components:

Build Date
Version
Serial Number

and adding comparable ones to the camera component.

If anyone has a preference as to whether that should be the next change submitted or something else, please let me know.

2 Likes

Thanks very much for the 1.2.5 update notice. I had only very recently changed from using rtsp to snapshot to see if there would be any performance improvement over a slow ISP/WAN connection, but I really can’t tell much difference.

Do you save video to an sdcard in your Amcrest cameras created from motion triggers? If so, what app or technique do you use to retrieve them for a specific alert?

The change from 1.2.3 to 1.2.5 in the amcrest package really only had to do with error handling. If the maximum number of retries was exceeded on a command transfer, the old version would not raise an exception but, e.g., the returned snapshot would just be empty.

The improvements in the snapshot handling were done in the HA amcrest component. If you’re using my latest custom component (just checked in), then you should have those changes. Or, if you’re using the standard component, you can get the updates from HA’s dev branch. These make sure that multiple threads attempting to get a snapshot from the camera don’t step on each other’s toes, resulting in errors that can slow things down. There can be (at least) three threads – the “thumbnail” picture on the frontend, the full picture in the “window” that appears “above” the thumbnail when you click on it, and a call to the camera.snapshot service, say in an automation.

I used to use motion detection in the cameras, and I had them set up to send an e-mail to me when motion was detected, strictly outside of HA. Inside HA I did use the binary_sensor to do other things when the cameras detected motion.

But now I use PIR sensors for motion detection, because it was just too difficult to get the camera motion detection to work well in all situations. So to get the snapshots now I came up with a combination of things, resulting in local_file cameras displaying the latest snapshot from each camera.

Here is part of the implementation from a package file:

camera:
  - platform: local_file
    name: LR IPC Last Motion
    file_path: /home/homeassistant/.homeassistant/snapshots/lr_ipc_motion_last.jpg
  - platform: local_file
    name: HF IPC Last Motion
    file_path: /home/homeassistant/.homeassistant/snapshots/hf_ipc_motion_last.jpg

shell_command:
  update_snaps: python3 /home/homeassistant/.homeassistant/update_snaps.py

automation:
  - alias: Foyer Snapshot
    trigger:
      - platform: numeric_state
        entity_id: sensor.foyer_burglar
        above: 0
    condition:
      - condition: template
        value_template: >
          {{ states('camera.lr_ipc') in ('streaming', 'recording') }}
    action:
      - wait_template: "{{ is_state('script.snap', 'off') }}"
      - service: script.snap
        data:
          camera: lr

  - alias: House Front Snapshot
    trigger:
      - platform: state
        entity_id: binary_sensor.hf_motion
        to: 'on'
    action:
      - wait_template: "{{ is_state('script.snap', 'off') }}"
      - service: script.snap
        data:
          camera: hf

script:
  snap:
    sequence:
      - service: camera.snapshot
        data_template:
          entity_id: camera.{{ camera }}_ipc
          filename: >
            /home/homeassistant/.homeassistant/snapshots/{{
              camera
            }}_ipc_motion_{{
              utcnow().strftime('%Y%m%d_%H%M%S')
            }}.jpg
      - service: shell_command.update_snaps

And here’s update_snaps.py:

#!/usr/bin/env python3

from glob import glob
import os


MAX_SNAPS = 25
SNAPS_DIR = '/home/homeassistant/.homeassistant/snapshots'
SNAPS = [('lr_ipc_motion_[0-9]*.jpg', 'lr_ipc_motion_last.jpg'),
         ('hf_ipc_motion_[0-9]*.jpg', 'hf_ipc_motion_last.jpg')]


for snap in SNAPS:
    snap_list = sorted(glob(os.path.join(SNAPS_DIR, snap[0])))
    snap_link = os.path.join(SNAPS_DIR, snap[1])
    try:
        os.remove(snap_link)
    except:
        pass
    if snap_list:
        os.symlink(snap_list[-1], snap_link)
        for f in snap_list[:-MAX_SNAPS]:
            os.remove(f)
    else:
        os.symlink('no_image.jpg', snap_link)

I’m in the process of updating this script so I can scroll through the available snapshots for each camera with buttons in the frontend, but that’s not ready for prime time yet. :slight_smile:

EDIT: I changed the file name timestamp from local time to UTC. It wasn’t an issue when going to DST, but it would have been later this year when coming from DST!

@pnbruckner great work so far!! you should expect to see both PR’s in the next beta that gets cut on Wednesday. Basically anything merged into dev before the first beta is cut will make it into that release, if the beta was already cut then the code change will be in the next release.

If you are submitting a code change that is a direct fix to an issue introduced by a previous code change (in master) you can comment in the new PR to include it in the next hot fix. They are pretty good about getting those fixes out :slight_smile:

Personally I am in favor of switching the sensor to a binary_sensor and also removing the build version etc…

Looking forward to the continued improvement!!

1 Like

Thanks for all the clarifications @pnbruckner - that was quite helpful.

I also appreciate the detail in how you are handling motion events. You’ve given me quite a bit to chew on. I was not familiar with this local_file camera platform at all.

Thanks!

1 Like

FYI, I’m done updating my custom amcrest component to be compatible with the latest & greatest (which is discussed a bit more above.) I’ve just now made a few more minor changes and updated custom_components.json so it can be installed via custom_updater. The “element” name is “amcrest”, and that’s all you need to install via custom_updater – that one install will load all the files into custom_components/amcrest. This requires the use of HA version 0.86 or later.

3 Likes

Thanks for this Phil!!

Hi all! (@danny, sorry for stealing your topic! :blush:)

I released a new version of the amcrest pypi.org package (1.3.0) that adds some commands that used to be in my custom component. It also fixes (or hopefully fixes) a bug related to retrieving storage usage information when no SD card is present (or possibly when it’s not formatted as well.) I’m getting ready to submit I’ve submitted the next batch of changes to HA’s amcrest component (see PR #22418), and I’ve updated my custom component accordingly as well. The updated custom component is available via my PR #122 if anyone would like to try it out before I release it.

1 Like