bhetherman 180e95f74d Fix audio, routing, auth, and stream lifecycle
- Switch OBS output to RTMP; add FFmpeg AAC->Opus transcoding via MediaMTX
  runOnReady so WebRTC can carry audio (WebRTC requires Opus, not AAC)
- Enable RTSP on localhost so FFmpeg reads game path without publisher conflict;
  viewers connect to game-opus path (H264+Opus)
- Fix WHEP/HLS path prefix stripping in NPM advanced config; move all custom
  locations (/whep, /hls, /v3) out of NPM GUI and into advanced conf so
  trailing-slash proxy_pass correctly strips prefixes before hitting MediaMTX
- Fix MediaMTX API port 49997->19997 (49997 was in Windows ephemeral range)
- Add /status proxy endpoint to OBS HTTP server so frontend can poll stream
  readiness without hitting /v3/ through NPM where auth_request blocked it
- Fix authInternalUsers: split publish (localhost only) from read (any IP)
  so WHEP viewers are not challenged with Basic Auth by MediaMTX
- Remove muted attribute from video element; show unmute/play button on
  autoplay block so viewers get audio after one click
- Fix webrtcAdditionalHosts to include LAN IP 192.168.50.254
- Fix hlsAllowOrigin->hlsAllowOrigins deprecation warning
- Move MediaMTX/HTTP server startup to script_load (not streaming started)
  so MediaMTX is ready before OBS attempts RTMP connection
- Log MediaMTX output to bin/mediamtx.log for easier debugging

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 03:42:38 -04:00
2026-04-05 17:16:51 -04:00
2026-04-05 17:16:51 -04:00
2026-04-05 17:16:51 -04:00

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, WHIP out)
    -> MediaMTX (localhost) ---> WHEP / HLS / API
    -> Frontend HTTP server (localhost:8080)
        -> NPM (TLS, Authentik forward auth, reverse proxy)
            -> Friend's browser

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 (WHIP in, WHEP/HLS out, locked-down)
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 configuration
docs/npm-setup.md NPM proxy host + stream (UDP) configuration
docs/obs-setup.md OBS encoder + WHIP output settings

Setup at a glance

  1. Clone this repo onto the Windows gaming PC.
  2. Install MediaMTX and the firewall rule: open an elevated PowerShell in the repo root and run .\scripts\install.ps1.
  3. Configure Authentik - see docs/authentik-setup.md.
  4. Configure NPM - see docs/npm-setup.md.
  5. Configure OBS - see docs/obs-setup.md, then add obs-script/game_stream.py via Tools -> Scripts.
  6. 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, HLS, or the MediaMTX API.
  • 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

S
Description
No description provided
Readme 94 KiB
Languages
JavaScript 39.4%
Python 39.1%
PowerShell 9.6%
CSS 8.6%
HTML 3.3%