voc / srtrelay

SRT relay server for distributing media streams to multiple clients.
MIT License
134 stars 37 forks source link

Features: Adding config support, streamID filtering via URL or slice #1

Closed ravenium closed 3 years ago

ravenium commented 3 years ago

Hello! First off, thank you so much for writing this - my golang probably wasn't up to the challenge of properly utilizing the srtgo bindings.

I've forked and added some basic support for configs (viper) and a few filtering mechanisms based on our needs (streaming aggregation for twitch across sites). I can submit a PR but figured I'd check in first.

iSchluff commented 3 years ago

Hi, thanks for your feedback. Yeah this is pretty basic at this point, I am currently already working on getting in some config and logging.

My plans for filtering where mainly introducing a http callback-based mechanism for authenticating publishers. Basically compatible to the nginx-rtmp on_publish callbacks (because I already have this https://github.com/voc/rtmp-auth). We don't really have a need for authenticating subscribers, however I wouldn't mind also adding a callback for that. But I think for basic use-cases having additional support for a static config file would also be fine.

Feel free to open a PR, however I will probably not integrate viper into this, it has a bit too many dependencies for my liking. I would probably go for either go-toml or go-yaml/yaml directly. But it would be cool to see what your requirements are.

iSchluff commented 3 years ago

However as the note on top of the readme says: this is not really ready for production yet. The basic functionality is there, but I am not sure about the edge cases, so mostly whether clients do or do not reconnect successfully in case of error.

Notably with ffmpeg and also srt-live-transmit as clients I currently don't get reliable reconnectionns. This may well be a problem in the client implementations but is still a problem when deploying this.

ravenium commented 3 years ago

Thanks for the followup! I'll make a better effort to apply some polish to my often-hackish additions before I submit.

Totally understand that this is highly experimental and no guarantees (and with the release of 1.4.2 of SRT, srtgo needs an update because I think not all sockopts are being set correctly). Right now we're just a bunch of engineers who game for charity and like coding random helper widgets, so this is more to encourage everyone to move off of RTMP than anything. We were going to use srt-live-server, but we had some publisher filtering needs and nobody knew enough C++ to add it :)

It's interesting that you've experienced problems with various clients - I had a lot of issues with ffmpeg/OBS clients using srt-live-server (vs using Larix as a client, which worked just fine). In that particular case the issue seemed to be incorrect latency settings (I ended up doing about 3x ping ms to get it to work). I wonder if some of it is due to differing options set.

iSchluff commented 3 years ago

Well the clients generally work, but most (e.g. ffmpeg) seem to make no attempt of reconnecting or exiting when the socket is closed on the other side. Currently I disconnect all subscribers once the publisher goes away, so if you are just running ffmpeg with srt input your stream will stop and never continue. So there is several options here: not letting the server sockets die (works for a short time, but impractical at some point because you will just leak memory), fixing the ffmpeg implementation and wrapping ffmpeg with something else like srt-live-transmit (which also doesn't reconnect properly, it has no rate limit on reconnect and seems to hang in some race condition or so) However this is not really an issue specific to this software.

Related to the latency: I also had the feeling that the default of 100ms in srt-live-server was too low. I compared the go-code with sls across the internet with artificial packetloss and jitter on the sender side generated using netem (https://wiki.linuxfoundation.org/networking/netem).

iSchluff commented 3 years ago

I have now added some basic config and static auth support. Currently working on http auth.

ravenium commented 3 years ago

I have now added some basic config and static auth support. Currently working on http auth.

I saw just as I was pushing a commit last night - I like your package layout and structure better than anything I've tried, and I think I saw you restructured the main/server relationship, so I might re-fork and work from there again. At the very least this has been a great reason for me to improve my Go practices :)

re: the problem with reconnects, I'm guessing this is by design - for example, in OBS you have to open a Media window and click "apply" to get it to retry. I think there's a feature request open on their side to have a "retry interval" but I agree with you that this might be difficult to practically implement server-side. Unless you can adjust socket timeouts, but I believe this is intended for 1:1 connection disruption and a connected but non-data receiving socket would error out.

A couple things I was thinking of adding from here on:

-A "scoreboard" similar to SLS's where it does a json POST to a predefined URL (or local file, or console) with currently active players and publishers. I got a basic one working (mutex lock etc) but got a bit stuck getting source IPs into the struct (since they're pulled on Accept() and not in Server. However, I think that's more possible with your last few revisions.

-Using srtgo's Stats package in some way, though most of the metrics aren't that interesting (maybe packetloss)

-Finding any sort of way to have a browser preview of streams, but this is probably far outside the scope of your project and would probably involve transmuxing to HLS/DASH, which sounds Not Very Fun.

iSchluff commented 3 years ago

Yeah I also think there should be some way to get a list of the currently running streams with statistics and such. However I think that maybe an api that you can call to from an external service would maybe be my preferred way of doing this. (Taking inspiration from icecasts status xml/json and nginx-rtmp stats page)

And yeah it would probably be a good idea to integrate some srt stats into that.

Preview is really hard if your stream is not something the browser can readily display. I think I would avoid doing that in this daemon however I think that is something that could be done using an additional service via the api if need be. Then that piece of software could concentrate on the srt -> hls part, or just use ffmpeg for that.