Owncast Instances
directory.owncast.online
directory.owncast.online
Unfortunately I immediately ran into huge performance issues with owncast compared to my solution, with input bitrates stuck at 200-300kbps. I haven't looked into it exhaustively but I think the main problem is that owncast seems to encode the video n+1 times where n is the number of desired quality levels (extra encoding pass on the published stream to smooth out publishing problems), while my solution sends out the original published stream as the high-quality variant and so encodes n-1 times with a couple additional steps of putting the same streams into new containers. Of course I have also set ffmpeg/libx264 to very high performance options, and I think owncast is less conservative here.
Really just an FYI for anyone else looking at making a switch or doing something similar. Video encoding is CPU intensive so if you want to run it on a small/inexpensive VPS, it's helpful to 1) architect to absolutely minimize the number of encoding passes required (even when new containers are needed), 2) provide fine-tuning of the encoder settings, since just the change from "fast" to "veryfast" with libx264 makes a pretty big difference on CPU time without a very noticeable difference in the video output.
Another issue with owncast is that it has choppy/unreliable response from the video player to the actual stream starting/stopping. My solution has the same problems. We're both using the same frontend video player, and I think it's a combination of limitations of that video player and inherent limitations of HLS/MPEG-DASH (the "download a playlist over and over again" model of HLS has some intrinsic issues when it comes to the generation of the playlist starting and stopping). I almost solved this in my own solution by 1) making it so that, in theory, there is always a video stream because the server "plays a video to itself" when there is no publisher, 2) a very lazy fix of having the frontend page auto-refresh periodically when playback fails to start. These are far from perfect and there is still some choppiness/buffering/repeated playback of a small segment when publishing starts and stops (and thus the management server starts/stops feeding the idle animation).
I think the way to really fix these problems is to write a custom demuxer for ffmpeg that uses a small buffer of a "technical difficulties" still or whatever to feed into the processing chain when the stream publisher (whether internal or external) fails to deliver a packet for a certain time period, thus preventing generation of the HLS playlist ever halting for long enough for the video player to stall. I'm currently feeding an ffmpeg encoder with named pipes of uncompressed media streams and this is kind of an off-label use that ffmpeg handles but isn't entirely happy about, and particularly requires some hacking to get ffmpeg to never think the stream ended even when the container says so. A custom demuxer is is on my list of things to do but I'm not much of a C++ person so it's a little daunting for me.
Perhaps one day I will publish my solution but it's extremely janky right now and has a lot of hard-coded config. I also think it's fairly easy to come up with on your own with some basic Linux knowledge and a willingness to spend an evening messing around with ffmpeg, pipes, different containers, and just seeing what it lets you get away with. Hint: getting ffmpeg to completely ignore the DTS timestamps on the incoming container was surprisingly confusing, know that the -re and -r flags have special meanings when used on the "input side" of the command.
Finally, if you're especially latency/synchronization sensitive (e.g. multiple are watching and you want them to be strictly in sync), HLS and MPEG-DASH both become a nightmare. This is frustrating enough that I originally decided to just provide RTMP and make people use a native client but ofc there's a large portion of people who don't want to expose their computer to anything that isn't a web browser, so instead I spent a lot of time trying to tune the HLS production to both be stable and low latency, and, well, HLS just doesn't do that well. The HLS settings that I got to provide a really stable stream lead to up to 60s, occasionally greater out-of-sync.
Encoding/decoding aside as codecs are understandably challenging, end-to-end latency is basically a nightmare even at scale (I feel like I’ve tried every one-to-many video streaming apps starting with Periscope, and I have yet to see one with less than 15s latency from broadcaster to recipient)
As well, viewer sync seems to either be a “problem” no one wants to “solve”, or it’s in the realm of magic. Plex clients even report their playback position every second or less and yet the variation on the “watch together” feature is all over the place. We also now have PTP which feels like a perfect fit for “clock” synchronization, but I have yet to see a single streaming technology use it or anything close to it.
If you care about adaptive HLS streaming, make sure to add "hls_variant" directives for each quality level such as:
hls_variant _1080p BANDWIDTH=10485760,RESOLUTION=1920x1080;
on the OBS/source side you want to match stream names like: rtmp(s)://your-nginx-server/your-publish-endpoint/your-stream_1080p
If you care about RTMPS (with TLS), you will want to look at NGINX Stream Core module⁴, with a server "listen" directive with the "ssl" option and a "proxy_pass" to the RTMP endpoint. For sending RTMPS from RTMP you will need another server "listen" with no "ssl" option and "proxy_ssl on", since the module has no native RTMPS capabilities, in order to get RTMPS as both server and sending client.For RTMP auto-publishing to multiple servers, you will want the "push" directive, and don't forget to give it a "name=" option, or it will grump. I struggled to get the "pull" directives to always work consistently and quickly.
If you want lower latency, make sure your source stream has small keyframe periods and that they match "buflen" directive; I opt for 2 seconds. But if using HLS, there isn't that much more you can do on that front.
³ https://github.com/arut/nginx-rtmp-module/wiki/Directives
⁴ http://nginx.org/en/docs/stream/ngx_stream_core_module.html
The other open-source alternative I know is PeerTube, which is getting live-streaming support in 3.0 (currently release candidate).
The interesting part is where content creators, personalities, etc own their own rails. They don't need a massive audience to run their own show. Even if I only push 10-20 TB / month that is enough to make a lifestyle "+" business.
That is my hypothesis, and 2021 looks like a good time to test it.
(Edit - I can't grammar, apparently)
direct ad sales and "reads" (old school way of doing it)
run pre and mid-roll in the content (again, already done)
paid live-streams with ticket sales. Paul Richards from Stream Geeks wrote a book on this.
Merch
Paid newsletters / content which is marketed in the show.
Everything exists -- lots of value in helping creators stitch it all together.
I see a similar opportunity how web devs helped grow the e-commerce for small companies, we will see the same growth helping creators stand on their own.
Peertube is apparently getting support for live streaming, or already has it. I can't tell.
This is not a dig at Peertube, they're doing truly great work. My use case is probably different
[1]: https://github.com/Chocobozzz/PeerTube/releases/tag/v3.0.0-r...
[2]: https://github.com/Chocobozzz/PeerTube/blob/develop/support/...
If you would be interested, please drop me a way to get in touch with you:
https://forms.gle/2KiR87rRdC4PSoCd6
(throwaway because I have currently have a day job that is emphatically not keen about side projects)
Might want to approach it instead as a consulting service that helps folks set it up on hosting that they are responsible for and have their names on.
Legal consulting to set up the correct corporate shell structure would probably also be a popular value add.
The lazy way seems to be to configure owncast to use an S3 compatible service. Some even support CDNs and provide unlimited egress bandwidth: