tsightler / ring-mqtt

Ring devices to MQTT Bridge
MIT License
563 stars 101 forks source link

Live Video Streaming #238

Closed tsightler closed 2 years ago

tsightler commented 3 years ago

So the day has come where pigs are flying and the cows are on their way home. I've been asked about inclusion of live streaming in this addon for, well, since pretty much the day I started supporting cameras and, while I've always said never, I guess never might have been a little too long because I'm now considering inclusion of live video support in ring-mqtt.

Now, of course, it won't be via MQTT, rather it will use an RTSP streaming server (the exact technology is still under evaluation, likely it will be the node based rtsp-streaming-server package, or the external rtsp-simple-server) and it will require manual creation of camera entities in Home Assistant (although you can also use it without HA, for example, via VLC or any other media player able to play streams) because I can't figure out any method for an addon to automatically create non-MQTT based entities without some type of helper HA based integration (if there is a way, someone please let me know, but there's always the possibility of a helper integration in the future if this stuff works OK).

There will of course be limits, as Ring limits sessions to ~10 minutes, so it's not going to be a full time live streaming session, but I still think it will be a major step up from the existing solutions and at least everything will be integrated in a single place. I'm also hoping to implement a creative way to playback the prior X number of recorded videos, with X still to be determined.

I'm currently looking for testers that are interested in giving the camera live streaming support a try and reporting any issues or bugs. This will involve simply being willing to run the dev version, making the required manual changes to your HA configs, and a willingness/ability to collect and provide logs for troubleshooting any issues. I hope to push the first dev version with live streaming support in the next week or so.

jeffgraham-hub commented 3 years ago

I am willing to assist you by testing.

tsightler commented 2 years ago

Thanks @jeffgraham-hub. I made a lot of progress tonight and think I'm only one good night of hacking away from having something that could be tested, even if it's not the finished product, so hopefully I can find that free night sometime this week.

tekwreck commented 2 years ago

I'll be happy to test as well

tsightler commented 2 years ago

Just an update for those interested, I managed to get a little bit of time tonight and managed to get the first "working" addon where a camera produced a functional livestream in HA. I've run into a few challenges that will make testing using the branch feature somewhat more difficult since the current container does not open any outside ports so only HA itself can actually talk to it.

Also, I've unfortunately found that rtsp-simple-server, while it works pretty well in most cases, does have a tendency to crash quite easily when things go wrong. While I can easily spawn a new process, I also need to then reconfigure all paths in the server (I'm current creating paths dynamically per camera via the REST API so when the server crashes and restarts it loses all of the config). I need to see if I can figure out a way to handle this issue better. I may have to abandon rtsp-simple-server and try another approach.

jmacul2 commented 2 years ago

I'm neck deep in this and I think I got it dialed in with rtsp-simple-server now. I actually use RTMP for publishing and then RTSP for the source going out.

My config:

rtsp-simple-server.yml

ring:
    runOnDemand: /opt/mtools/index.mjs -acodec aac -vcodec copy -f flv rtmp://localhost/ring
    runOnDemandRestart: yes
    runOnDemandStartTimeout: 20s
    runOnDemandCloseAfter: 5s

index.mjs

import { dirname } from 'path';
import { fileURLToPath } from 'url';
import { readFile, writeFile } from 'fs/promises';
import ringClientApi from 'ring-client-api';

const CONFIG_PATH = process.env.CONFIG_PATH || '/opt/mtools/config.json';

async function updateSavedToken({ newRefreshToken, oldRefreshToken }) {
        console.log('Refresh Token Updated: ', newRefreshToken);
        if (!oldRefreshToken) return;
        const currentConfig = await readFile(CONFIG_PATH, 'utf8');
        const updatedConfig = currentConfig.replace(oldRefreshToken, newRefreshToken);
        await writeFile(CONFIG_PATH, updatedConfig);
}

const ffmpegArgs = {
        audio: [], video: [],
        output: process.argv.slice(2),
};

async function main() {
        const { refreshToken, ffmpegPath } = JSON.parse(await readFile(CONFIG_PATH, 'utf8'));
        const ringApi = new ringClientApi.RingApi({ ffmpegPath, refreshToken });
        //ringApi.onRefreshTokenUpdated.subscribe(updateSavedToken);
        const [camera] = await ringApi.getCameras();
        const session = await camera.createSipSession({ skipFfmpegCheck: true });
        await session.start(ffmpegArgs);
}

// handle exit signals
for (const signal of ['SIGINT','SIGTERM','SIGQUIT']) {
        process.on(signal, () => {
                console.log(`Received ${signal}, exiting...`);
                process.exit();
        });
}

main();

RTSP simple server receives from index.mjs (ffmpeg) via RTMP and then will publish on both RTMP and RTSP. I was getting errors and crashes occasionally if I only used RTSP. Not sure why, but this setup seems pretty stable so far.

I also added MJPEG streaming on top of this so I could get the ring video to publish to a chromecast or google assistant on motion or a door ding.

The workflow is as follows:

motion --> home assistant media_play url service --> mjpeg url --> rtsp-simple-server --> index.mjs (ring-client-api)

All this happens in about 6 seconds after a ding or motion event.

Let me know if you have any questions, I'd be happy to help with MJPEG if you want to include it. I find that MJPEG is by far the fastest to send over the wire to a google chromecast or assistant. Its almost instantaneous.

Shout out to @gilliginsisland as most of this was his idea. https://github.com/jeroenterheerdt/ring-hassio/issues/51

tsightler commented 2 years ago

I'm trying to integrate rtsp-simple-server into the ring-mqtt addon but it's been a bit of a struggle due to the fact that I keep finding bugs and ways to crash it. I'm automatically registering cameras via the API, but found that the API isn't thread safe, which is a problem when there is a lot of cameras that register asynchronously, although I've worked around it in the code for now.

I've also found that onDemand publishing is easy to crash if you do something like start publishing without a client consuming the stream. It appears that rtsp-simple-server tries to kill the onDemand command 10 seconds later, even though there's no clients so the onDemand command never actually ran, so then the entire process crashes, which kills all streams. However, maybe that's similar to the issue you were seeing and I should try rtmp publishing. I'll give that a try.

I already use MJPEG in ring-mqtt even today for battery cameras when getting snapshot images, it starts a stream with a low frame rate MJPEG stream and I use pipe2jpg to grab full jpeg images directly from the stream and send them over MQTT, but of course that's maybe a single frame every few seconds due to MQTT.

I'm not really familiar with the media_play url service nor do I understand how an mjpeg url is being used by rtsp-simple-server in your case. Can you clarify that part a little bit.

The way it works right now is that a user configures a manual IP camera in Home Assistant with an RTSP URL pointing to RTSP server. During startup, ring-mqtt registers a path for each camera with rtsp-simple-server, and then when you click on the camera in Home Assistant, it connects to the rtsp URL which trigger rtsp-simple-server to run a node script which starts and monitors the stream status via MQTT. I used MQTT because I need the project to fit with the confines of the project, and I wanted people that leverage ring-mqtt with other things to be able to start streams, if they want (starting a stream always triggers a recoding so users might want to trigger a recording for events other than motion, but not necessarily watch it real-time, for example). Using MQTT also means that there is no extra communications path needed between rtsp-simple-server and ring-mqtt and it uses the existing Ring API.

Overall it's working pretty well, but I'm still working through all of the scenarios and trying to find crashes. I haven't worried too much about the publish format yet, although it can literally be anything FFMPEG supports, but I've been hesitant to do any transforming since many users leverage pretty low powered devices for HA and I have to consider the cases where a user has many cameras processing.

tsightler commented 2 years ago

Hi all, so if anyone wants to test the current state of video streaming in the addon I think it's in a state where it is working reasonably well, but there are some limitations since the container doesn't currently expose any ports to the outside world.

After switching to the dev branch everything should look basically the same as previously, however, if you click on any of your cameras you should see a new "Stream" entity (with a CCTV camera icon), where you can manually start/stop a stream, although this feature probably isn't that useful directly.

More importantly, if you select the Info sensor entity, you should see two new attributes, the "Stream Source" and the "Still Image URL". These URL are published here primarily to simplify configuration of the Home Assistant Generic Camera integration, while will have to be done manually if you want a camera entity in the Home Assistant UI.

The streaming URL will connect to the local rtsp-simple-server and start an on-demand stream any time the camera entity is opened or the camera service is used to play or record a video. The still image URL is an example URL that can be used so that the camera entity will get it's still image from the snapshot camera so you get consistently updating still images as well.

To add a live camera entity simple add something like this to your configuration.yaml (the below is a sample based on my setup with some of the data changed):

camera:
  - platform: generic
    name: Front Porch Camera
    still_image_url: http://localhost:8123{{ states.camera.front_porch_snapshot.attributes.entity_picture }}
    stream_source: rtsp://172.30.33.11:8554/3ab4538c8192_live

Once you add this and reload your configuration, you should see a new camera in devices. Simple add this camera to your dashboard using a picture glance card and that should be all that is required. The still image will be based on images from the snapshot camera entity, while clicking the image will start/open a livestream. You might also need to tweak the still image URL if you are using SSL or have changed the default port, or if you've customized your entity names or renamed devices. Right now I'm not querying the API for this info, but it's something I've been thinking about.

Note that you can also choose to make opening the dashboard immediately start a livestream, by selecting "live" vs "auto" , however, note that Ring does not allow livestreams to last longer than 10 minutes and this will also cause a recording to start every time the dashboard is opened. The same with using the "preload" screen.

Currently, the streams will not restart automatically after a timeout because I need to a) respect Ring's current limits or else they might choose to block this app completely, b) be careful not to run the battery dead for those with battery powered cameras.

Note that, even when using on-demand streams, Home Assistant keeps an active connection to the streaming server for 5 minutes after you close the live video, this can potentially lead to missed events (Ring cameras won't alert on motion events while the stream is active) and also work against battery life. I'm not really sure how to deal with this, my current thought is the have the streams time out on the server side in whatever the recording lifetime is set to, and then present a control to allow uses to change the timeout up to the maximum.

Also, I know I will get asked about auto-restarting the streams. While I can't keep people from building automations to do this, I don't plan to enable this in the plugin natively unless Ring finally delivers on 24x7 streaming which they keep saying is "being worked on".

Another thing to keep in mind is that all streams for Ring go to the cloud, so bandwidth is a big issue if you have a lot of cameras streaming and you are viewing them in Home Assistant. Basically, data has to go from the camera to Ring servers, then back down to the Home Assistant server, then back to wherever you are viewing.

Anyway, if anyone wants to test, I'd be interested in success/fail reports. I current have seven cameras and it's working quite well for me so far. This is probably not the final release though, but I just felt it was finally at a stage that could be tested.

stephywephy88 commented 2 years ago

I can test today - but I just deleted your dev repo during some cleanup. What is it again?

tsightler commented 2 years ago

Assuming you are using the addon or docker container install, you can just use the BRANCH feature. For the addon the branch config option is set by default to "addon" which uses the code in the docker image, but you can simple set it to "dev" and the addon will pull down the current dev version during startup, no need for a separate addon. To revert back to the standard build just change the config option back to "addon" and restart.

For the standard docker version, just set BRANCH="dev" (or add it to docker compose) for the same behavior.

jmacul2 commented 2 years ago

I'm not really familiar with the media_play url service nor do I understand how an mjpeg url is being used by rtsp-simple-server in your case. Can you clarify that part a little bit.

I've experimented with a few ways of doing it from writing my own in python/flask, but I finally settled on https://github.com/blueimp/mjpeg-server, also written in Go. This one is nice, because just like rtsp-simple-server, it has an option for on demand MJPEG.

I also use hardware acceleration on my box so I am able to host 6 cameras with around 10% cpu utilization.

here is an example of my bash script that calls mjpeg-server:

#!/bin/bash

url="rtsp://localhost:8554/$1"
port="900$1"

/opt/mtools/mjpeg-server -a :$port -- ffmpeg -loglevel error -fflags nobuffer -err_detect aggressive -fflags discardcorrupt -use_wallclock_as_timestamps 1 -c:v h264_cuvid -resize 1024x578 -r 3 -rtsp_transport udp -i $url -r 3 -c:v mjpeg_qsv -g 20 -force_key_frames 'expr:gte(t,n_forced*2)' -global_quality 70 -f mpjpeg -q 2 -

I am using this for a bunch of wyze cams that I use as outdoor surveillance as well as my ring doorbell cam.

So essentially when you hit http://server:port it fires on demand mjpeg which calls on demand rtsp-simple-server which calls from the api, etc.

I then can use a home assistant automation to check for your mqtt motion or ding event from the binary sensor and call the media_play service to my nest (google) hub to show the mjpeg video on screen for 10-20 seconds.


alias: Ring Ding Google Hub
trigger:
  - platform: state
    entity_id: binary_sensor.front_door_ding
    from: 'off'
    to: 'on'
action:
  - service: media_player.play_media
    target:
      entity_id: media_player.kitchen_display
    data:
      media_content_type: image/jpeg
      media_content_id: http://<server>:<port>
  - delay:
      hours: 0
      minutes: 0
      seconds: 20
      milliseconds: 0
  - service: media_player.turn_off
    target:
      entity_id: media_player.kitchen_display
mode: single

It shows on screen for 20 seconds and then shuts off. My goal was to mimic that nest doorbell as close as possible. I've tested this and it takes about 6-7 seconds to show up. I wish it were quicker, but I haven't found anything as fast as this. Other solutions take 15-20 seconds.

The reason I use MJPEG to cast to the Nest display instead of just the RTSP stream is that casting MJPEG is almost instant. There is near zero lag on the cast device to show MJPEG. An RTSP video takes an additional 5-6 seconds to queue and buffer.

tsightler commented 2 years ago

@jmacul2 Thanks for the added detail, that all makes sense.

Interestingly, I've noticed very recently that Ring has added live streaming directly to their web app and it is very fast and doesn't have much buffering (I hear cars outside the window at nearly the same time I'm hearing them in the video). I'm wondering if this is their new direction for video vs the old SIP based approach, it might be far easier to integrate with and I've just wasted a bunch of time and effort.

I'm not yet sure how they are presenting the stream, but it's low-latency, high quality, supports audio, even two way audio.

tsightler commented 2 years ago

So it appears that the web based live streaming works only with Chrome and Edge browsers, at least, that's what they suggest using when I try it with Firefox and I don't have access to Safari to test it out. It does appear to still create video recordings, and it does "timeout" after ~12 minutes, but seems to just immediately restart. Perhaps this is how they plan to deliver their "forever" 24x7 streaming they've been promising, and perhaps why they are discontinuing the Windows native app.

tsightler commented 2 years ago

OK, more poking at the web based streaming I think it's just using WebRTC and includes a TCP session in the SDP that uses port 443. I think this is the reason it is so much faster establishing the connection than ring-client-api because the actual call to start the video returns the SDP info immediately and the browser almost immediately starts the connection, while ring-client-api sends the API call to start the live video, but then has to wait for the "on demand" ding to return the SIP info, which it then uses to to build the SDP and establish the stream via SIP negotiation using STUN to open UDP ports, etc. In the end that's a lot of moving parts compared to just immediately establishing a connection over TCP 443.

However, the stream itself doesn't appear to be different so maybe in the future the API could just be modified to use the REST call and then stream over TCP.

tsightler commented 2 years ago

Actually, even the browser based will still use UDP if it's available (I was testing ona network where this was restricted, whoops). So really it's just the faster method to get the SDP info that makes the difference I guess.

stephywephy88 commented 2 years ago

I’m still fussing with my still image URL (I use Nabu Casa) and my pi is not happy getting 6 rtsp streams, so besides some understandable load delays and stream freezes, I’ve not had major issues. One quirk I noticed is that I can hear road noise from my doorbell when that dashboard is open: 1) when I’m not even viewing the stream and 2) sometimes after the picture element card was opened, muted, and closed. Muting seems to work only sometimes - I could still hear the road noise after exiting the stream/card. However, there’s less noise happening at my other cameras so not sure if it’s unique to my doorbell (Pro). I’ve been using the snapshots in picture cards but this is a nice addition!

(Sorry if my terminology is off - I’m just a hobbyist)

tsightler commented 2 years ago

@stephywephy88 Thanks for testing, glad to hear it is working. Don't know what I could do about any of the UI issues as those are 100% handled by HA, but I haven't noticed that behavior in my own setup unless I set the glance card for "Live", which then is somewhat expected I guess.

The still image URL should be fairly easy to figure out, if you go to Devices, select the camera and then click the Snapshot entity, you could see the Home Assistant entity ID. For example, for my front porch camera it s camera.front_porch_snapshot. Basically, we just create a value template that extracts the entity_picture attribute from that device. This is an automatically generated URL that allows you to access the snapshot via the HA API so the URL would be something like:

http://<hostname_or_IP_of_ha_instance>{{ states.<entity_id>.attributes.entity_picture }}

So if you normally access you HA instance via https://my.homeassistant.com and you camera's entity ID is "camera.front_porch_snapshot", then the URL would be:

https://my.homeassistant.com{{ states.camera.front_porch_snapshot.attributes.entity_picture }}

One common mistake is that people put a / between the domain and the value template, but the entity_picture attribute already starts with a /.

You can also view the current entity_picture attribute by going to Developer Tools and selecting the camera snapshot entity, you'll see the entity_picture attribute. You can just copy and paste this and play around with it until it works in the browser, but be aware that the token actually changes every 5 minutes which is why you need to use the value template so that it stays updated with the current value. You can also use a generated long lived token.

jeffgraham-hub commented 2 years ago

I just got it up and running in the 30 minutes but everything appears to working as it should. The snapshots are updating and live video streaming works on all cameras. I will continue to poke around and let you know if I find any issues. I can confirm that the https example you provided works for me.

https://xxxxx.duckdns.org:8123{{ states.camera.front_door_camera_snapshot.attributes.entity_picture }}

tsightler commented 2 years ago

Really, you should be able to just use "localhost" for the hostname as the API actually runs on HA itself so the traffic should never leave the box.

jeffgraham-hub commented 2 years ago

I tried localhost and it doesn't work for me.

https://localhost:8123{{ states.camera.front_door_camera_snapshot.attributes.entity_picture }}

I just tried it again and this is the error that I get in HA . Error getting new camera image from Front Door Camera Test: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'localhost'.

jeffgraham-hub commented 2 years ago

Ok I got localhost to work by adding verify_ssl: false.

- platform: generic
    name: Front Door Camera Test
    still_image_url: https://localhost:8123{{ states.camera.front_door_camera_snapshot.attributes.entity_picture }}
    stream_source: rtsp://172.30.33.5:8554/xxxxxxxxxxxx_live
    verify_ssl: false
tsightler commented 2 years ago

Ah, good one with the verify_ssl. I actually have a valid certificate on my instance, but something for me to keep in mind. Perhaps I can event check for it. I've been considering making a link in the web console that you can click and get a sample configuration that you can just copy and paste.

tsightler commented 2 years ago

In the latest push I've switched the on-demand script from a javascript running under node to just a simple bash script that uses mosquitto_sub. This speeds up the initial connection by a second or two and significantly cuts down the memory requirements when there are multiple concurrent live streams. Previously the addon would easily use 30% of the available memory on my 1GB dev system with just 5 simultaneous live streams, now it uses 10-11%.

I can't do a whole lot about the CPU usage because most of it is the node process itself dealing with the incoming stream as the ring-client-api processes the incoming stream in node and sends it to ffmpeg via a pipe. I'm currently investigating if I can figure out how to get FFMPEG to connect to the stream directly which should cut out a significant amount of overhead and hopefully make the stream a little more stable and lower the CPU a ton. It seems to me that it should be possible as I think most of the processing in ring-client-api is for adding the ability for return audio, which I don't really care about right now, but I'm still working on understanding the code.

tekwreck commented 2 years ago

Found this issue switching to dev branch

image

tsightler commented 2 years ago

@tekwreck What platform are you on? Also, will probably need full logs as this issue is likely to be caused due to failure during install of rtsp-simple-server as I believe ENOENT is basically, no such file or directory.

tsightler commented 2 years ago

Actually, @tekwreck are you using the Docker image or did you just manually pull the dev branch from Github?

tekwreck commented 2 years ago

I am using Docker containers running on an unraid server.

I also started an RTSP simple server using docker as well (aler9/rtsp-simple-server)

tsightler commented 2 years ago

You don't need a separate container with rtsp-simple-server because the script will automatically download one (well, once this code moves to production, it will just be in the Docker image by default).

However, right now the code to do all of this is only in the run-addon.sh script so it doesn't work for straight Docker installs because, when not running as an addon, it uses a different startup script inside the container (the Docker image detects if it's running as the addon or not). I'll need to move the code that does that to the Docker startup script.

This is a little bit unusual because the branch feature was never really designed to do anything but clone a new version from github, not pull in a bunch of extra dependencies and binaries, etc. so I'm really pushing the limits with some extra scripting to do things that will all just be in the base Docker image in the future. All try to update the standard Docker script soon.

tekwreck commented 2 years ago

I'm actually only running HA Core in an image and I don't have the addons support which require the full OS install, unless i am missing something.

tsightler commented 2 years ago

Yes, that is correct, addons are only for the full OS install, well, any "supervised" install I guess.

Is your HA Core instance also running on the Unraid server? Are you use a Docker compose file (I don't know anything about how Unraid support Docker).

tekwreck commented 2 years ago

Yes so I have unraid running on a Dell PowerEdge Server.

Unraid comes with a WebGUI that allows an easy GUI interface for creating/managing Docker images - image

I have a docker images for various stuff on my home server, for the sake of this configuration I am using

tsightler/ring-mqtt spants/mqtt homeassistant/home-assistant

I have the MQTT integration enabled which connects to my MQTT docker container which that gets data from ring-mqtt

tekwreck commented 2 years ago

I should probably just create a VM with HA OS on it at the direction I am going with this.

tsightler commented 2 years ago

I can easily move the commands into the generic Docker startup script, I just hadn't done it because I'm testing either locally on my dev box, or with the addon, and once it's in production it doesn't really matter. It's literally just copying and pasting some lines.

tsightler commented 2 years ago

Ah, now I remember why I didn't do that. There is a bug in the branch feature that doesn't allow me to pull down extra packages because it only runs the update script from the existing, production version of the code and never executes anything that is downloaded except for the new version of the ring-mqtt.js script itself. For the addon I was able to work around this because it has its own, separate startup script that pulls all of the configuration options from HA using bashio, so I was able to perform the extra steps in this interim script since that is run from the downloaded version.

Oh well, unfortunately, that means that testing the dev branch is limited to the addon for the time being. Sorry about that. I can think of a hackish way to get around it by making ring-mqtt.js itself run the update script, but it's probably not worth it as I was already thinking I need to publish a "beta" version of the addon and a new container for this feature anyway. Either that or just bite the bullet and let this thing loose to the general public in a few days as it seems to be working quite well for me at this point.

tekwreck commented 2 years ago

i am in the process of setting up HA OS right now :-)

tekwreck commented 2 years ago

I got it working via the addon, however after I added a second camera the entire thing wouldn't load. I'll have to dig more into the logs later.

tsightler commented 2 years ago

To be fair the dev branch is in a massive state of flux so if you restart the addon you may get a working or broken version at any minute. I'm currently having to make major changes to the startup scripts as I'm moving the entire startup to use the s6 supervision suite. Hopefully it will stable out over the next couple of days.

tekwreck commented 2 years ago

it turned out to be a typo on my part, it's working atm. a little delayed but working

tsightler commented 2 years ago

Unfortunately the delay is largely due to Home Assistant due to it's use of HLS for the stream in the UI vs leveraging RTSP directly. Even though they've tuned HLS for minimal latency it still adds ~3-4 seconds on top of the 2 seconds or so that spinning the stream through ring-client-api and RTSP server cause. I mean, that's way better than the 10 second or so it's known for, but still it's not a great option for anything that is trying to be real-time.

In the final version you'll be able to connect to the RTSP server directly via an external player like VLC, which will cut the latency down to about 2 seconds or so based on my testing. I'm still hopeful to maybe get that down in the future by bypassing ring-client-api completely and just having ffmpeg connect directly to RTSP server, but right now it's just a theory in my head. However, it won't help at all with the HA portion of the latency.

tsightler commented 2 years ago

Actually, I just realized that 1 second of that ~2 seconds latency when using VLC is caused by the fact that VLC buffers 1 second by default when playing a network stream so when I cut that to zero seconds of buffering I was only about 1 second delay, which isn't too bad considering that it has to hop from camera, across internet to Ring servers, back across Internet to ring-client-api in addon, to FFMPEG, to RTSP server to VLC. However, I know it can be faster because it's still delayed vs the in-browser viewing of the stream on Ring.com.

I think most of the remaining delay, that's not caused by HA, is probably in ring-client-api because it is processing the RTP stream in node itself, which is fast for an interpreted language, but not really the greatest tool for processing video streams. I'm really hopeful I can bypass that in a future version but for now it's just about getting it working reliably and clearly understanding the process.

tsightler commented 2 years ago

One way you can minimize the delay and still use the Home Assistant Lovelace UI is to install the excellent WebRTC addon, then add the custom webrtc card that uses the entity (or just add the RTSP URL directly to the camera. This gets the latency down to about 1 second for me, it's nearly identical to watching the stream in the Ring app on my phone, but still about 1/2 second behind the web base live view. Still I think that's acceptable. It also supports the ability to cast the video via Chromecast, which is really nice.

They one bad part of this approach right now is that you lose audio, because the WebRTC card only supports G.711 A-law/µ-law codecs directly while Home Assistant's generic camera support only appears to support AAC/MP3.

tsightler commented 2 years ago

Pushed a small update that streams both AAC and the native µ-law PCM audio stream to the RTSP server so that clients can select their preferred audio stream. This seems to work, I get audio in the Home Assistant native Lovelace UI camera card, and audio in the WebRTC card as well, with the latter offering much lower latency and the ability to cast the video although there are a few downsides, like no snapshot previews, etc. Still, it's nice to have options for a low-latency view that is easy to configure directly in Lovelace.

I also played around with Motioneye and it works as well, but it doesn't seem to be a good choice for a stream that is on-demand as it's designed more for full time streaming.

tekwreck commented 2 years ago

So I have implemented the current setup with my TileBoard I am using with HA and can use TYPE.CAMERA and TYPE_CAMERA_STREAM properly now. I have snapshot on the camera type and the rtsp stream on the camera_stream using 4 cameras without any issues other than the known delay.

tsightler commented 2 years ago

Thanks all for the testing! It's likely that the current dev branch will no longer work as I'm currently in the process of cleaning it up and preparing for the release. I've decided to try to release still missing a few features, but it's a pain keeping all of these hacks for the dev branch working so pusing a minimal feature release with just live streaming will make it easier for me to add the remaining video features.

tekwreck commented 2 years ago

The addon had auto-update enabled and broke it as you mentioned, switched back to the main branch hopefully we'll see a rollout soon!

tsightler commented 2 years ago

Auto-update in the addon shouldn't really matter as there have been no updates pushed for the addon, but maybe something else caused it to restart. When the branch feature is enabled it basically pulls the latest branch every time the container restarts. It's meant more as a way for users to temporarily test dev/latest branches and be able to easily revert without having to install other addons, etc.

I expect to release in the next day or two, the documentation is mostly done and I've cleaned up all the hackish stuff for the most part. I'm still tracking down one or two stubborn bugs, but overall I'm pretty happy with where it's at right now.

tsightler commented 2 years ago

4.8.0 has been released with video streaming enabled. I have tested this stuff a tone over of the last 72 hours and it has worked very well with only a few very minor glitches so hopefully it will be usable for others. I still have the following updates to implement:

tekwreck commented 2 years ago

Should the addon via HA be working again after a restart using the master branch?

Stop/Starting & Restarting all show it's still on 4.7.3

tsightler commented 2 years ago

Then you will need to update it to the latest version.

tsightler commented 2 years ago

To be more clear, I can't control when your HA instance decides to check for updates, but you can. If you go to the Add-on Store tab in the UI and click the three vertical dots in the upper right corner you can select the "Reload" option which will force an immediate check of all repositories. Then go back to the addon and it should show an update available and Changelog. I don't really know how often HA checks for updates on its own.

tekwreck commented 2 years ago

That reload did the trick, thank you for helping with that - image