LiveKit-based streaming infrastructure for live music performances.


Overview

The streaming stack is built on LiveKit, an open-source WebRTC Selective Forwarding Unit (SFU). LiveKit handles real-time audio/video streaming with low latency, supporting multiple participants and recording.

A custom SvelteKit dashboard at stream.spacemusic.tv provides a web interface for managing rooms, streams, and tokens.

Components

Component Image Port Purpose
LiveKit Server livekit/livekit-server:v1.6.1 7880 SFU core -- routes WebRTC media between participants
Redis redis:7-alpine 6379 Session state and coordination
Egress livekit/egress:latest -- Recording and restreaming (outputs to MinIO)
Ingress livekit/ingress:latest 8080 (WHIP), 1935 (RTMP) Ingest streams from OBS, GStreamer, browsers

All four LiveKit containers run with network_mode: host -- they bind directly to the host network, not Docker bridge networking. This is required for WebRTC's UDP port ranges to work correctly.

Network and Ports

Endpoint Port(s) Protocol Purpose
livekit.spacemusic.tv 7880 TCP LiveKit API and WebSocket signaling
livekit-whip.spacemusic.tv 8080 TCP WHIP ingest (browser-based WebRTC push)
RTMP Ingest 1935 TCP RTMP ingest from OBS or similar
livekit-turn.spacemusic.tv 5349 (TLS), 3478 (UDP) TCP/UDP TURN server for NAT traversal
WebRTC Media 50000-60000 UDP RTC peer connections
Prometheus Metrics 7889 TCP Internal metrics endpoint

Stream Dashboard

The stream dashboard at stream.spacemusic.tv is a custom SvelteKit application that wraps the LiveKit server SDK. It is deployed via devpush on a Node.js 20 runner.

Stack: SvelteKit 2.x, Svelte 5 (runes), shadcn-svelte, Tailwind CSS v4, livekit-server-sdk v2.15.0

Features:

  • Room management (create, list, delete rooms)
  • Participant list with mute/kick controls
  • Token generation for room access
  • Ingress management (create RTMP/WHIP/URL ingress streams)
  • Egress controls (start/stop recording)
  • Authentication via Authentik forward auth

Dashboard API routes:

Route Methods Purpose
/api/health GET LiveKit connectivity check
/api/rooms GET, POST List / create rooms
/api/rooms/[name] GET, DELETE Room detail / delete
/api/rooms/[name]/participants GET, POST List / remove / mute participants
/api/ingress GET, POST, DELETE Ingress stream management
/api/tokens POST Generate JWT access tokens

Ingress (Stream Input)

LiveKit Ingress accepts streams from external sources and publishes them into LiveKit rooms.

RTMP -- Push from OBS or similar software to rtmp://livekit.spacemusic.tv:1935/live/<stream-key>. Configure in OBS as a custom RTMP server.

WHIP -- Browser-based WebRTC ingest at livekit-whip.spacemusic.tv. Supported by OBS 30+ and GStreamer. Lower latency than RTMP.

URL Pull -- LiveKit can pull from an existing RTMP/HLS/WHIP URL and republish into a room.

Egress (Recording)

LiveKit Egress records room audio/video and outputs to the MinIO recordings bucket (30-day lifecycle). Recordings can be triggered via the stream dashboard or the API gateway.

The Egress service uses a headless Chrome instance internally to composite room layouts, so it requires more resources than other LiveKit components.

Token Authentication

LiveKit uses JWT tokens for room access. The stream dashboard generates tokens via the livekit-server-sdk:

const token = new AccessToken(API_KEY, API_SECRET, {
    identity: username,
    ttl: '6h'
});
token.addGrant({
    room: roomName,
    roomJoin: true,
    canPublish: true,
    canSubscribe: true,
    canPublishData: true
});

Environment variables required: LIVEKIT_API_KEY, LIVEKIT_API_SECRET, LIVEKIT_URL (internal WebSocket), LIVEKIT_WS_URL (public WebSocket).

Monitoring

Prometheus scrapes LiveKit metrics at 172.17.0.1:7889/metrics (Docker gateway IP, since LiveKit runs on host network). These metrics power the "LiveKit Streaming" Grafana dashboard at dashboard.spacemusic.tv, showing:

  • Active rooms and participants
  • Track bandwidth (audio/video)
  • Connection quality scores
  • Egress/Ingress status