{ "id": "multistreaming", "name": "multistreaming", "description": "Self-built live production dashboard (shadcn/ui sidebar): per-person OBS feeds, shared rooms with editor/streamer roles, pluggable streaming providers, zero-knowledge key vault, per-account streaming grants, and scenes & composition (grid/PiP layouts, text/image overlays, per-output audio routing).", "version": "4.1.0", "category": "media", "tags": ["streaming", "restream", "rtmp", "obs", "multistream", "zero-knowledge", "collaboration", "shadcn"], "author": "homelab", "license": "MIT", "homepage": "https://github.com/ReinadoRojo/homelab", "compose": { "build": { "context": ".", "dockerfile": "Dockerfile" }, "container_name": "multistreaming", "restart": "unless-stopped", "ports": [ "1935:1935", "8080:8080" ], "volumes": [ "multistreaming_data:/data" ], "environment": [ "AUTH_MODE=${AUTH_MODE}", "OIDC_ISSUER=${OIDC_ISSUER}", "OIDC_CLIENT_ID=${OIDC_CLIENT_ID}", "OIDC_REDIRECT_URI=${OIDC_REDIRECT_URI}", "PUBLIC_HOST=${PUBLIC_HOST}", "SESSION_SECRET=${SESSION_SECRET}", "GRANT_TTL_MS=${GRANT_TTL_MS}" ], "networks": ["homelab"] }, "volumes": { "multistreaming_data": {} }, "networks": { "homelab": { "external": true } }, "env": [ { "name": "AUTH_MODE", "label": "Auth mode", "description": "oidc = Authelia SSO (recommended); local = username/password (dev only)", "default": "oidc", "required": false, "secret": false, "options": ["oidc", "local"] }, { "name": "OIDC_ISSUER", "label": "OIDC issuer", "description": "Authelia root URL, e.g. https://auth.example.com", "default": "https://auth.example.com", "required": false, "secret": false }, { "name": "OIDC_CLIENT_ID", "label": "OIDC client id", "default": "multistreaming", "required": false, "secret": false }, { "name": "OIDC_REDIRECT_URI", "label": "OIDC redirect URI", "description": "Must match the redirect_uris registered in Authelia, e.g. https://streaming.example.com/api/auth/oidc/callback", "default": "https://streaming.example.com/api/auth/oidc/callback", "required": false, "secret": false }, { "name": "SESSION_SECRET", "label": "Session secret (auto-generated)", "generate": true }, { "name": "PUBLIC_HOST", "label": "Public host", "description": "Host shown in feed ingest URLs (e.g. feed.streaming.example.com). Leave empty to use the machine hostname.", "default": "", "required": false, "secret": false }, { "name": "GRANT_TTL_MS", "label": "Streaming grant lifetime (ms)", "description": "How long a streamer's decrypted keys stay in memory after they click Start streaming.", "default": "21600000", "required": false, "secret": false } ], "notes": "Web panel at http://:8080 (or https://streaming.example.com via nginx-proxy-manager). Login is Authelia OIDC (public client + PKCE); the client is pre-registered in authelia's configuration.yml with redirect_uri https://streaming.example.com/api/auth/oidc/callback — keep OIDC_REDIRECT_URI in sync. Each user creates one or more zero-knowledge Vaults (passphrase-protected key stores, encrypted in the browser — the server stores only ciphertext and can never read a key); the sidebar lets you unlock one vault at a time and set a default. Accounts (Twitch/YouTube/Kick/custom) live inside a vault. Rooms share a production with editor (edit feeds/outputs/scenes, no keys) and streamer (own accounts + start streaming) roles via invite links. Feeds = per-person OBS ingest at rtmp://:1935/live/ (RTMP bypasses the proxy). Outputs route a feed to an account; a streamer clicks Start streaming and picks platforms, which decrypts their keys client-side and grants the server a short-lived in-memory copy. Scenes compose live feeds into grid or PiP layouts with text/image overlays and per-output audio routing; activating a scene switches the room from per-feed passthrough to the composed program (see services/multistreaming/docs/SCENES.md)." }