ring-hassio
ring-hassio copied to clipboard
Improvement to add-on with on demand configuration
I saw your add-on and thought it can be improved using a setup that I have on my home assistant server.
It uses https://github.com/aler9/rtsp-simple-server which is an awesome golang based rtsp server / client in combination with https://github.com/dgreif/ring.
It supports on demand automatically and only uses one ring stream no matter how many clients connect, and by not using HLS and using only rtsp it avoids the 10 second minimum lag that HLS has.
My nodejs script that calls dgreif/ring forwards all its arguments to ffmpeg and looks like this
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 || '/etc/ring-ffmpeg.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();
The script can be easily adapted to take in refreshToken from the environment instead of a file.
Then in rtsp-simple-server I take advantage of an option where it can launch on demand only when someone actually tries to request an rtsp stream and it will stop streaming as soon as all clients disconnect, it will also duplicate the stream if multiple connections are made, and so only one connection will be made to ring even if many connections are made to rtsp-simple-server. My config looks like this:
rtspDisable: no
protocols: [tcp]
rtspAddress: 127.0.0.1:8554
rtmpDisable: yes
hlsDisable: no
hlsAddress: 127.0.0.1:8888
hlsSegmentCount: 4
hlsSegmentDuration: 2s
paths:
all:
fallback:
disablePublisherOverride: no
ring:
source: record
runOnDemand: /usr/local/lib/ring-ffmpeg/index.mjs -acodec aac -vcodec copy -f rtsp rtsp://localhost:$RTSP_PORT/$RTSP_PATH
runOnDemandRestart: yes
runOnDemandStartTimeout: 20s
runOnDemandCloseAfter: 5s
The key part is that when using runOnDemand
rtsp-simple-server will do the work of running the binary and closing it when home assistant disconnects, and it will dynamically open a port and tell the node script what port to send out to.
Combining these two items we can have a true on demand rtsp stream very easily.
Hey - this is really cool!
How does it work with more than one Ring camera? 👀
The sample code I wrote doesn’t do more than one camera in its current form but it should be trivial to add that ability. rtsp-simple-server allows multiple paths so u can add the camera as the first parameter and change the node script to take the camera number as the first argument and then use that to pull the corresponding camera.
Hey, very cool!
can you explain how you configured your environment to use this with homeassistant?
Thanks!
Hi, in this fork of ring-hassio i have implemented your script with the newest version of rtsp-simple-server.
@patsch9 Thats awesome. I use home assistant core so I couldn't make changes to the add-on and test it. Happy you implemented it!
I saw the update to rtsp-simple-server and I noticed that the yaml file for the configuration supports regex paths, so it should be possible to support multiple cameras with one path definition, something like ~ring([0-9]+)
and then use that path to know which camera to stream.
Also for home assistant configuration I use the ffmpeg platform which doesn't require a still_image_url
since the live stream doesn't have snapshot feature
@gilliginsisland do you have also the problem that when you access the livestream there are no ding or motion events on other devices also home assistant? When i cancel the stream than the events are shown.
I dont actually know that answer, I only use it for the stick up cam and I dont use the regular integration. I only use it as an on demand camera. But from what I googled it seems that when a live stream is active that there is no motion or ding events, and that there doesn't seem to be a way to fix that.
ok, that's exactly my level of knowledge. It's a shame for Amazon that the connection to external services is so poorly represented. Thanks for your input and feel free to edit some things in my forked repo :-)
Yeah I agree.
A $20 camera on amazon has PTZ and a local RTSP stream that doesn't require workarounds to get into home assistant. But a $150 camera can come without PTZ and without RTSP and u need to pay a subscription to get recording which only last 30 seconds and isnt always on.
I only have a ring because I got the stick up cam for free when I signed up for Verizon Fios lol
@gilliginsisland Thank you for sharing this. I'm the maintainer of ring-mqtt as well as the ring-mqtt addon. which is quite popular with Home Assistant users. I've had numerous request to add livestreaming to the addon but, as the current integration is based on MQTT, it's not really built for livestreaming, although I do support other camera functions and also have support for snapshots based on interval and motion.
I had looked at this script previously, but I wasn't too excited with the HLS implementation and didn't really have time to dig into RTSP support. However, due to continued requests, I've been seriously considering integrating streaming into the addon to provide a single addon with all Ring functionality and had been researching rtsp simple server, so seeing a working example is great.
One question, how reliable have you found this setup? My experience with livestreams using ring-client-api has been a little spotty, and my big concern is the support issues it would open up due to this so I'm curious what your experience has been.
Just FYI for folks here, not trying to take users away from this project, but I've implemented streaming support in ring-mqtt using a concept similar to the one posted in this thread (rtsp-simple-server, but using ring-mqtt to trigger stream start/stops). It supports mulitple cameras, external viewers on-demand, ability to manually start a stream/record session, etc. There's a few more features to come, like playback of past recorded videos, but so far it seems pretty usable.