Browse Source

Custom RTMP server

Cara Salter 1 week ago
Signed by: muirrum
GPG Key ID: 90C66610C82B29CA
  1. 1
  2. 1
  3. 2
  4. 91
  5. 8
  6. 5
  7. 10

.direnv/flake-profile vendored

@ -0,0 +1 @@

.direnv/flake-profile-1-link vendored

@ -0,0 +1 @@


@ -1 +1 @@
eval "$(lorri direnv)"
use flake


@ -0,0 +1,91 @@
title: Self-hosting a Live Stream Server
author: Cara Salter
date: 2022-06-15
This Sunday, I will be running the technical side of an online Pride event
hosted by my partner. Part of this includes live music performances that all
need to go to the same stream output. I also need to be able to scale and
transcode the streams appropriately. There are, of course, commercial options
available, but that wouldn't be very fun (or cheap!). What fun is having servers
if I can't also mess around with them?
The specific final destination has particular codecs and resolutions, and they
recommend something like [Oven Media Engine][ome] to take in all the streams and
allow them to be rebroadcasted into their intake server. I spent most of today
trying to make it work, and while I was able to successfully *send* to it, I
couldn't get anything out of it, no matter how much I tried. This was mostly
because of a lack of understanding on my part, but also the relatively
confusing-to-newcomers way that the configuration and documentation is
That's not to say that it's unfriendly to new users, just that it requires a lot
more prior knowledge and research than I expected or was capable of dealing with
in the moment. I'm sure it's a wonderfully useful software, it just didn't
fulfill my need for something that could be set up and tested for this weekend.
Eventually I remembered an [old post][ddevault] by Drew DeVault that talked
about self-hosting his own live-streaming server with `nginx`. In it, he streams
a screengrab of an X11 window via `ffmpeg`[^1] into a DASH[^2] sink using the
`nginx-rtmp` module.
This looks great! Streaming into nginx that then can be republished and pulled
into OBS for transcoding and restreaming. I ended up installing the RTMP module
on one of my servers, and wrote the following configuration:
rtmp {
server {
listen 1935;
chunk_size 4096;
application live {
live on;
record off;
That's really all it takes. `1935` is used because it's the standard RTMP port,
but really any one can be used. This lets me send streams to
`rtmp://<my-server>:1935/live/<key or name>`. Where it says `<key or name>`,
that's the bit where you can separate each stream. Then, I can add a Media
Source to OBS or VLC with that same URL, and it will automatically pull the
stream down. By managing stream keys, you can have multiple people streaming in
at once, and then switch between them using software like OBS.
I'm mostly using the stock OBS settings, but I'm making sure to use the `x264`
encoder and the `veryfast` encoder preset, which is easier on web browsers.
There's no noticable difference in quality, so in my opinion there's no need to
go any higher.
The RTMP module also lets you use the nginx `allow` and `deny` directives, for
access control based on IP addresses or subnets. For example, if I only wanted
to be able to stream from within my VPN, I could set
allow publish <my-laptops-vpn-ip>;
deny publish all;
which would only let my laptop (or any other IP I wanted) broadcast. I'm sure
there's some way to do this better, like predetermining which stream keys are
able to play, but I haven't been able to find it yet, so I've just been
disabling the module when I don't need it.
To recap, the general steps I took were:
1. Install and configure the nginx RTMP module
2. Configure OBS to stream to the RTMP URL
3. Add a media source to VLC with that same URL to play
I hope this was able to help! I plan on looking into this more, especially the
access control bits, so I'll be sure to update this post with anything I find.
[^1]: Which, if you didn't know, is a really wonderful tool that can do
basically anything related to A/V including transcoding and streaming.
[^2]: Dynamic Adaptive Streaming over HTTP


@ -10,7 +10,11 @@ a {
/* Base container */
.container {
margin: auto; /* centered */
width: 80%; /* looks nice */
width: 60%; /* looks nice */
.centered {
margin: auto;
/* Navbar */
@ -43,6 +47,8 @@ a {
.inner-column {
flex: 50%;
margin-right: 0.5rem;
margin-left: 0.1rem;
/* Post list */


@ -40,4 +40,9 @@
<div class="centered">
<p>REST API management plane for virtual machines, to enable remote
management across a network.</p>


@ -13,7 +13,7 @@
<h3>About me</h3>
I am a:
<li>Trans <div class="p-gender-identity">woman</div> (she/her)</li>
<li>Trans woman (she/her)</li>
<li>Eagle Scout</li>
<li>Software Engineer</li>
@ -32,6 +32,7 @@
My past projects are, in no particular order:
<li><a href="">solard</a></li>
<li><a href="">WG-manager</li>
@ -47,15 +48,12 @@
<h4>Web Development</h4>
<li>Rust (Warp)</li>
<li>Go (Gin-gonic)</li>
<li>Rust (Axum)</li>
<li>Python (Django/Flask)</li>
<li>NodeJS (Svelte)</li>
<h4>Systems Administration</h4>
<li>Prometheus & Zabbix Monitoring/Alerts</li>
<li>Prometheus Monitoring/Alerts</li>
<li>Shell scripting</li>