Files
obs-game-stream-plugin/README.md
T
bhetherman 0dff4eeee3 Update all docs to reflect current working configuration
- README: update architecture diagram for RTMP+FFmpeg pipeline, add FFmpeg
  install step, fix path descriptions
- obs-setup: switch from WHIP to RTMP output, add FFmpeg prerequisite, fix
  script log messages (MediaMTX starts on load not streaming start), add
  Python setup note, update troubleshooting for game-opus path and audio
- npm-setup: remove Custom Locations GUI instructions (must be empty - all
  locations defined in Advanced tab only), update verify steps to game-opus
  paths, add troubleshooting for WHEP 400/401 causes
- authentik-setup: add section 6 covering both manual account creation and
  self-service enrollment via invite link; clarify User Write stage group
  field is what triggers auto-add (not the invitation form)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 03:46:13 -04:00

4.1 KiB

game-stream-app

Low-latency browser-based game streaming to a small group of friends, gated by Authentik authentication.

  • Streamer: Windows PC with an NVIDIA GPU running OBS Studio.
  • Viewers: up to ~6 friends, any modern browser, no client install.
  • Auth: Authentik forward auth at the Nginx Proxy Manager (NPM) edge.
  • Transport: WebRTC (WHEP) for low latency, with LL-HLS fallback.
  • Latency target: ~200 ms over WebRTC, ~1-2 s over LL-HLS fallback.

How it works

OBS Studio (NVENC H.264, RTMP out)
    -> MediaMTX (localhost, RTMP ingest)
        -> FFmpeg (AAC -> Opus transcode, internal RTSP)
            -> game-opus path (H.264 + Opus)
                -> WHEP / HLS for viewers
    -> Frontend HTTP server (localhost:48080)
        -> NPM (TLS, Authentik forward auth, reverse proxy)
            -> Friend's browser

OBS outputs RTMP to MediaMTX on localhost. MediaMTX spawns FFmpeg via runOnReady to transcode audio from AAC to Opus (required for WebRTC) and re-publish to the game-opus path. Viewers connect to game-opus via WHEP (WebRTC) or HLS.

Everything on the gaming PC (MediaMTX, HTTP server, Windows Firewall rule for the WebRTC UDP port) is spawned and torn down by an OBS Python script - obs-script/game_stream.py. You just click Start Streaming in OBS and the whole pipeline comes up; click Stop Streaming and it all goes away.

Repository layout

Path Purpose
config/mediamtx.yml MediaMTX configuration (RTMP in, WHEP/HLS out, FFmpeg transcode)
config/npm-advanced.conf Authentik forward-auth snippet for the NPM Advanced tab
obs-script/game_stream.py OBS script: lifecycle, HTTP server, firewall toggle
frontend/index.html Viewer page
frontend/js/player.js WHEP client with HLS fallback
frontend/js/app.js Status polling and DOM glue
frontend/css/style.css Dark theme
scripts/install.ps1 Downloads MediaMTX, creates the Windows Firewall rule
docs/authentik-setup.md Authentik proxy provider, group, and invite configuration
docs/npm-setup.md NPM proxy host + stream (UDP) configuration
docs/obs-setup.md OBS encoder + RTMP output settings

Setup at a glance

  1. Clone this repo onto the Windows gaming PC.
  2. Install FFmpeg: winget install Gyan.FFmpeg in an elevated PowerShell, then open a new terminal to verify: ffmpeg -version.
  3. Install MediaMTX and the firewall rule: open an elevated PowerShell in the repo root and run .\scripts\install.ps1.
  4. Configure Authentik - see docs/authentik-setup.md.
  5. Configure NPM - see docs/npm-setup.md.
  6. Configure OBS - see docs/obs-setup.md, then add obs-script/game_stream.py via Tools -> Scripts.
  7. Click Start Streaming in OBS. Friends can now open https://stream.hetherman.cloud, log in with Authentik, and watch.

Security posture

  • TLS terminates at NPM with Let's Encrypt.
  • Every request is gated by Authentik forward auth before it reaches the frontend, WHEP signaling, or HLS.
  • MediaMTX only accepts publishers from 127.0.0.1 - nobody on the public internet can hijack the stream.
  • The UDP port used for WebRTC media is opened on the Windows Firewall only while streaming is active (toggled by the OBS script). Even though NPM and the router still forward the port, the OS silently drops packets between streams, so there is no exposed listener.
  • WebRTC media is DTLS-encrypted SRTP. An attacker who hits the UDP port without an Authentik-authenticated WHEP session cannot decrypt or inject media.
  • Removing a friend from the Authentik stream-viewers group revokes their access on the next auth_request subrequest (within seconds).

License

MIT