2026-03-06 11:51:57 +01:00
# Gaming Hub
2026-03-05 21:46:11 +00:00
2026-03-09 00:19:53 +01:00
Plugin-basierte Discord-Bot-Plattform mit Web-Dashboard und Electron Desktop App.
Drei Bots (Jukebox, Radio, Notifications) laufen parallel mit eigenem Discord-Token und eigener Voice-Connection pro Guild.
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
## Architektur
2026-03-05 21:46:11 +00:00
```
2026-03-06 11:51:57 +01:00
gaming-hub/
├── server/ # Backend (Node.js + Express + TypeScript)
│ └── src/
2026-03-09 00:19:53 +01:00
│ ├── index.ts # Entry Point, SSE, Plugin-Loader, WebSocket
2026-03-06 11:51:57 +01:00
│ ├── core/
2026-03-09 00:19:53 +01:00
│ │ ├── discord.ts # Discord.js Client Factory (Multi-Bot)
2026-03-06 11:51:57 +01:00
│ │ ├── plugin.ts # Plugin-System + Voice Claims
│ │ ├── sse.ts # Server-Sent Events Broadcasting
2026-03-09 00:19:53 +01:00
│ │ └── persistence.ts # JSON State auf Disk (Atomic Writes)
2026-03-06 11:51:57 +01:00
│ └── plugins/
2026-03-09 00:19:53 +01:00
│ ├── radio/ # World Radio (3D Globe + FFmpeg)
│ ├── soundboard/ # Jukebox / Soundboard (PCM Cache)
│ ├── lolstats/ # League of Legends Statistiken
│ ├── streaming/ # P2P Live-Streaming (WebRTC)
│ ├── watch-together/ # Synchron Video schauen
│ ├── game-library/ # Steam + GOG Spielebibliothek
│ └── notifications/ # Discord Benachrichtigungen
2026-03-06 11:51:57 +01:00
│
├── web/ # Frontend (React 19 + Vite + TypeScript)
│ └── src/
│ ├── App.tsx # Root, Tab-Navigation, SSE-Handler
2026-03-09 00:19:53 +01:00
│ ├── styles.css # Globale Styles
2026-03-06 11:51:57 +01:00
│ └── plugins/
2026-03-09 00:19:53 +01:00
│ ├── radio/ # 3D Globe UI (Three.js Sprites)
│ ├── soundboard/ # Sound Grid UI + Admin Panel
│ ├── lolstats/ # Summoner-Suche + Match History
│ ├── streaming/ # Stream-Erstellung + Viewer
│ ├── watch-together/ # Raeume, Queue, Chat, Voting
│ └── game-library/ # Spielebibliothek Grid
│
├── electron/ # Desktop App (Windows, Squirrel Installer)
│ ├── main.js # BrowserWindow, Auto-Updater, Ad-Blocker
│ ├── preload.js # IPC Bridge (contextBridge)
│ ├── ad-blocker.js # Request-Filter + Filterliste
│ └── forge.config.js # Electron Forge (Squirrel.Windows)
2026-03-06 11:51:57 +01:00
│
├── Dockerfile # Multi-Stage Production Build (4 Stages)
2026-03-09 00:19:53 +01:00
├── .gitlab-ci.yml # CI/CD (Kaniko Build + Deploy + Electron Build)
└── VERSION # Aktuelle Version (SemVer)
2026-03-05 21:46:11 +00:00
```
2026-03-06 11:51:57 +01:00
## Tech Stack
| Komponente | Technologie | Version |
|------------|-------------|---------|
| Runtime | Node.js | 24 (slim) |
| Backend | Express | 5.x |
| Frontend | React + Vite | 19.x / 6.x |
| Discord | discord.js + @discordjs/voice | 14.x / 0.19.x |
| 3D Globe | globe.gl + three.js | 2.35 / 0.172 |
| Audio | FFmpeg (GPL Build) + @discordjs/opus | latest / 0.10.x |
2026-03-09 00:19:53 +01:00
| Streaming | WebSocket (ws) + WebRTC (Browser) | 8.x |
| Desktop | Electron + Squirrel.Windows | 33.x |
2026-03-06 11:51:57 +01:00
| TypeScript | tsc | 5.9.x |
| CI/CD | GitLab + Kaniko | v1.23.2 |
## Plugins
### Radio (`radio`)
- 3D-Globus mit 30.000+ Radiosendern weltweit (Radio Garden API)
2026-03-06 14:06:40 +01:00
- NASA Blue Marble Globus-Textur (statisches Satellitenbild)
- Sender als Sprite-Partikel mit radialer Gradient-Textur (Theme-Farbe)
2026-03-09 00:19:53 +01:00
- Server-seitiger Tile-Proxy mit In-Memory Cache (max 500 Tiles)
2026-03-06 11:51:57 +01:00
- FFmpeg PCM-Streaming in Discord Voice Channels
- Per-Guild Lautstaerke, Favoriten, Suche
- Voice Stats (Ping, Status, Uptime) via SSE
### Soundboard / Jukebox (`soundboard`)
- Sound-Upload (MP3/WAV) mit Drag & Drop
- Automatische Audio-Normalisierung (LUFS, FFmpeg)
- PCM Memory Cache (Standard 512 MB) fuer sofortige Wiedergabe
2026-03-09 00:19:53 +01:00
- Kategorien, Badges, Statistiken, Entrance/Exit Sounds
- Admin-Panel mit HMAC-Token-Authentifizierung
2026-03-06 11:51:57 +01:00
- Party-Modus (Chaos Mode)
2026-03-09 00:19:53 +01:00
### LoL Stats (`lolstats`)
- League of Legends Spielerstatistiken via op.gg
- Summoner-Suche nach Game Name + Tag Line + Region
- Match History mit Detail-Analyse
- Letzte Suchen (max 10) persistent gespeichert
- Unterstuetzte Regionen: NA, EUW, EUNE, KR, JP, BR, LAN, LAS, OCE, TR, RU, PH, SG, TH, TW, VN
### Streaming (`streaming`)
- Peer-to-Peer Live-Streaming via WebRTC (kein Media-Server noetig)
- WebSocket-Signaling fuer Offer/Answer/ICE-Austausch
- Qualitaets-Presets: 720p30, 1080p30, 1080p60, 1440p60, 4K60, 4K165 Ultra
- Einstellbare Bitrate (2.5 Mbit/s bis 50 Mbit/s je nach Preset)
- Optionaler Passwortschutz (Server-seitige Verifikation)
- Viewer-Liste mit Echtzeit-Updates
- Discord-Benachrichtigungen bei Stream-Start/-Ende (via Notifications Plugin)
- Stream-Link Auto-Join aus Discord (?viewStream=UUID)
- Heartbeat-basierte Client-Erkennung (5s Intervall)
### Watch Together (`watch-together`)
- Synchronisiertes Video-Schauen in Raeumen
- Video-Queue mit URL-Eingabe
- Demokratisches Voting (Skip, Pause)
- Integrierter Chat pro Raum
- Raum-Passwortschutz
- Playback-Sync alle 2.5 Sekunden
- Host/Member-Rollen
- Auto-Cleanup nach 30s Inaktivitaet
### Game Library (`game-library`)
- Multi-Plattform Spielebibliothek (Steam + GOG)
- Steam API Integration (Spielzeit-Tracking)
- GOG OAuth2 Login Flow (mit Token-Refresh)
- IGDB Game-Enrichment (Metadaten, Cover-Bilder)
- Mehrere Benutzerprofile pro Instanz
- Spiele-Caching mit Ablaufzeit
### Notifications (`notifications`)
- Discord Embed-Benachrichtigungen fuer andere Plugins
- Kanal-Abonnement-Verwaltung pro Guild
- Event-Filterung (stream_start, stream_end, etc.)
- Konfigurierbare Ziel-Kanaele pro Event-Typ
- Klickbare Stream-Links in Benachrichtigungen
## Electron Desktop App
- Native Windows-Anwendung (Squirrel.Windows Installer)
- Automatische Updates via `/downloads` Endpoint
- Integrierter Ad-Blocker (Request-Filter + Filterliste)
- Screen Capture Picker (getDisplayMedia mit nativem Dialog)
- GOG OAuth Redirect-Handling in Child Windows
- Stream-Warnung beim Schliessen (wenn Broadcast aktiv)
- Windows Toast Notifications
- Custom User-Agent (`GamingHubDesktop/{version}` )
2026-03-06 11:51:57 +01:00
## Environment Variables
### Erforderlich
| Variable | Beschreibung |
|----------|-------------|
| `DISCORD_TOKEN_JUKEBOX` | Discord Bot Token fuer Soundboard/Jukebox |
| `DISCORD_TOKEN_RADIO` | Discord Bot Token fuer Radio |
2026-03-09 00:19:53 +01:00
| `DISCORD_TOKEN_NOTIFICATIONS` | Discord Bot Token fuer Benachrichtigungen |
2026-03-06 11:51:57 +01:00
2026-03-09 00:19:53 +01:00
> Alle drei Bots muessen im Discord Developer Portal separat erstellt werden.
2026-03-06 11:51:57 +01:00
> Jeder braucht die Intents: `GUILDS`, `GUILD_VOICE_STATES`, `GUILD_MEMBERS`.
### Optional
| Variable | Default | Beschreibung |
|----------|---------|-------------|
| `PORT` | `8080` | HTTP Server Port |
| `DATA_DIR` | `/data` | Persistenter Speicher (State, Sounds) |
2026-03-09 00:19:53 +01:00
| `ADMIN_PWD` | _(leer)_ | Admin-Passwort fuer geschuetzte Bereiche |
2026-03-06 11:51:57 +01:00
| `ALLOWED_GUILD_IDS` | _(leer)_ | Komma-separierte Guild-IDs (Whitelist, leer = alle) |
2026-03-09 00:19:53 +01:00
| `PUBLIC_URL` | _(leer)_ | Oeffentliche URL fuer Notification-Links (z.B. `https://hub.example.de` ) |
| `STEAM_API_KEY` | _(leer)_ | Steam Web API Key fuer Game Library |
| `DISCORD_TOKEN` | _(leer)_ | Legacy Fallback fuer Jukebox |
2026-03-06 11:51:57 +01:00
### Soundboard-spezifisch
| Variable | Default | Beschreibung |
|----------|---------|-------------|
| `SOUNDS_DIR` | `/data/sounds` | Verzeichnis fuer Sound-Dateien |
| `NORMALIZE_ENABLE` | `true` | Audio-Normalisierung aktivieren |
| `NORMALIZE_I` | `-16` | LUFS Integrated Loudness |
| `NORMALIZE_LRA` | `11` | LUFS Loudness Range |
| `NORMALIZE_TP` | `-1.5` | LUFS True Peak |
| `NORM_CONCURRENCY` | `2` | Parallele Normalisierungs-Threads |
| `PCM_CACHE_MAX_MB` | `512` | Max. PCM Memory Cache in MB |
### Build-Time (Vite)
| Variable | Default | Beschreibung |
|----------|---------|-------------|
| `VITE_APP_VERSION` | `1.0.0-dev` | Angezeigte Version im Frontend |
| `VITE_BUILD_CHANNEL` | `dev` | Release-Kanal (`stable` / `nightly` / `dev` ) |
## Docker
### Image bauen
```bash
docker build -t gaming-hub:latest .
```
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
### Container starten
```bash
docker run -d \
--name gaming-hub \
--restart unless-stopped \
-p 8080:8080 \
-v gaming-hub-data:/data \
-e DISCORD_TOKEN_JUKEBOX="dein-jukebox-token" \
-e DISCORD_TOKEN_RADIO="dein-radio-token" \
2026-03-09 00:19:53 +01:00
-e DISCORD_TOKEN_NOTIFICATIONS="dein-notifications-token" \
2026-03-06 11:51:57 +01:00
-e ADMIN_PWD="dein-admin-passwort" \
2026-03-09 00:19:53 +01:00
-e PUBLIC_URL="https://hub.example.de" \
2026-03-06 11:51:57 +01:00
gaming-hub:latest
```
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
### Docker Compose
```yaml
version: "3.8"
services:
gaming-hub:
image: gaming-hub:latest
container_name: gaming-hub
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- gaming-hub-data:/data
environment:
# Erforderlich
- DISCORD_TOKEN_JUKEBOX=dein-jukebox-token
- DISCORD_TOKEN_RADIO=dein-radio-token
2026-03-09 00:19:53 +01:00
- DISCORD_TOKEN_NOTIFICATIONS=dein-notifications-token
2026-03-06 11:51:57 +01:00
# Optional
- ADMIN_PWD=dein-admin-passwort
2026-03-09 00:19:53 +01:00
- PUBLIC_URL=https://hub.example.de
- STEAM_API_KEY=dein-steam-api-key
2026-03-06 11:51:57 +01:00
- ALLOWED_GUILD_IDS=
# Soundboard Tuning
- PCM_CACHE_MAX_MB=512
- NORMALIZE_ENABLE=true
volumes:
gaming-hub-data:
```
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
### Unraid Docker Template
```xml
<?xml version="1.0"?>
< Container version = "2" >
< Name > gaming-hub< / Name >
2026-03-09 00:19:53 +01:00
< Repository > 192.168.1.100:5050/root/gaming-hub:latest< / Repository >
< Registry > http://192.168.1.100:9080/< / Registry >
2026-03-06 11:51:57 +01:00
< Network > bridge< / Network >
< Privileged > false< / Privileged >
< Support / >
2026-03-09 00:19:53 +01:00
< Overview > Discord Gaming Hub - Soundboard, Radio, Streaming, LoL Stats, Watch Together, Game Library< / Overview >
2026-03-06 11:51:57 +01:00
< Category > MediaApp:Other< / Category >
< WebUI > http://[IP]:[PORT:8080]/< / WebUI >
< ExtraParams > --restart unless-stopped< / ExtraParams >
< Config Name = "Web UI Port" Target = "8080" Default = "8080" Mode = "tcp" Description = "Web Dashboard Port" Type = "Port" Display = "always" Required = "true" Mask = "false" > 8080< / Config >
2026-03-09 00:19:53 +01:00
< Config Name = "Data" Target = "/data" Default = "/mnt/user/appdata/gaming-hub" Mode = "rw" Description = "Persistenter Speicher" Type = "Path" Display = "always" Required = "true" Mask = "false" > /mnt/user/appdata/gaming-hub< / Config >
2026-03-06 11:51:57 +01:00
< Config Name = "Discord Token Jukebox" Target = "DISCORD_TOKEN_JUKEBOX" Default = "" Mode = "" Description = "Discord Bot Token fuer Soundboard" Type = "Variable" Display = "always" Required = "true" Mask = "true" / >
< Config Name = "Discord Token Radio" Target = "DISCORD_TOKEN_RADIO" Default = "" Mode = "" Description = "Discord Bot Token fuer Radio" Type = "Variable" Display = "always" Required = "true" Mask = "true" / >
2026-03-09 00:19:53 +01:00
< Config Name = "Discord Token Notifications" Target = "DISCORD_TOKEN_NOTIFICATIONS" Default = "" Mode = "" Description = "Discord Bot Token fuer Benachrichtigungen" Type = "Variable" Display = "always" Required = "true" Mask = "true" / >
< Config Name = "Admin Passwort" Target = "ADMIN_PWD" Default = "" Mode = "" Description = "Admin-Passwort" Type = "Variable" Display = "always" Required = "false" Mask = "true" / >
< Config Name = "Public URL" Target = "PUBLIC_URL" Default = "" Mode = "" Description = "Oeffentliche URL fuer Notification-Links" Type = "Variable" Display = "always" Required = "false" Mask = "false" / >
< Config Name = "Steam API Key" Target = "STEAM_API_KEY" Default = "" Mode = "" Description = "Steam Web API Key fuer Game Library" Type = "Variable" Display = "advanced" Required = "false" Mask = "true" / >
2026-03-06 11:51:57 +01:00
< Config Name = "Erlaubte Guild IDs" Target = "ALLOWED_GUILD_IDS" Default = "" Mode = "" Description = "Komma-separierte Guild-IDs (leer = alle)" Type = "Variable" Display = "advanced" Required = "false" Mask = "false" / >
< Config Name = "PCM Cache MB" Target = "PCM_CACHE_MAX_MB" Default = "512" Mode = "" Description = "Max. PCM Memory Cache in MB" Type = "Variable" Display = "advanced" Required = "false" Mask = "false" > 512< / Config >
< Config Name = "Normalisierung" Target = "NORMALIZE_ENABLE" Default = "true" Mode = "" Description = "Audio-Normalisierung aktivieren" Type = "Variable" Display = "advanced" Required = "false" Mask = "false" > true< / Config >
< Config Name = "Sound-Verzeichnis" Target = "SOUNDS_DIR" Default = "/data/sounds" Mode = "" Description = "Sound-Dateien Pfad im Container" Type = "Variable" Display = "advanced" Required = "false" Mask = "false" > /data/sounds< / Config >
< / Container >
```
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
## Lokale Entwicklung
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
### Voraussetzungen
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
- Node.js 20+
- FFmpeg im PATH
2026-03-09 00:19:53 +01:00
- Drei Discord Bot Tokens
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
### Setup
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
```bash
2026-03-09 00:19:53 +01:00
git clone http://192.168.1.100:9080/root/gaming-hub.git
2026-03-06 11:51:57 +01:00
cd gaming-hub
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
# Server Dependencies
cd server & & npm install & & cd ..
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
# Web Dependencies
cd web & & npm install & & cd ..
```
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
### Dev Server starten
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
```bash
# Terminal 1: Backend
cd server
2026-03-09 00:19:53 +01:00
DISCORD_TOKEN_JUKEBOX="..." \
DISCORD_TOKEN_RADIO="..." \
DISCORD_TOKEN_NOTIFICATIONS="..." \
ADMIN_PWD="test" \
DATA_DIR="./data" \
npm run dev
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
# Terminal 2: Frontend (Proxy auf localhost:8080)
cd web
npm run dev
```
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
Backend laeuft auf `http://localhost:8080` , Frontend auf `http://localhost:5173` (mit API-Proxy).
2026-03-05 21:46:11 +00:00
2026-03-09 00:19:53 +01:00
### Electron Desktop App (Windows)
```bash
cd electron
npm install
npm start
```
Build fuer Distribution:
```bash
cd electron
npx electron-forge make
```
Erzeugt einen Squirrel.Windows Installer unter `electron/out/make/` .
2026-03-06 11:51:57 +01:00
### Production Build
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
```bash
cd server & & npm run build # -> server/dist/
cd ../web & & npm run build # -> web/dist/
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
# Starten
cd ../server
NODE_ENV=production node dist/index.js
```
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
## API Endpoints
### Core
| Method | Pfad | Beschreibung |
|--------|------|-------------|
| GET | `/api/health` | Server-Status, Plugins, Bots, SSE-Clients |
| GET | `/api/plugins` | Plugin-Liste (Name, Version, Description) |
| GET | `/api/events` | SSE-Stream (Snapshot + Live-Updates) |
| POST | `/api/admin/login` | Admin-Login (Body: `{ password }` ) |
### Radio Plugin
| Method | Pfad | Beschreibung |
|--------|------|-------------|
| GET | `/api/radio/places` | Alle Orte fuer den Globus |
| GET | `/api/radio/place/:id/channels` | Sender an einem Ort |
| GET | `/api/radio/search?q=...` | Sender/Orte suchen |
| GET | `/api/radio/guilds` | Verfuegbare Guilds + Voice Channels |
| POST | `/api/radio/play` | Stream starten |
| POST | `/api/radio/stop` | Stream stoppen |
| POST | `/api/radio/volume` | Lautstaerke setzen (0-1) |
| GET | `/api/radio/favorites` | Favoriten lesen |
| POST | `/api/radio/favorites` | Favorit togglen |
| GET | `/api/radio/status` | Aktueller Wiedergabestatus |
2026-03-06 14:06:40 +01:00
| GET | `/api/radio/tile/:z/:x/:y` | Tile-Proxy (Fallback Satellitenbild) |
2026-03-06 11:51:57 +01:00
### Soundboard Plugin
| Method | Pfad | Beschreibung |
|--------|------|-------------|
| GET | `/api/soundboard/channels` | Voice Channels aller Guilds |
| GET | `/api/soundboard/sounds` | Sound-Liste (mit Filter/Suche) |
| POST | `/api/soundboard/play` | Sound abspielen |
| POST | `/api/soundboard/stop` | Wiedergabe stoppen |
| POST | `/api/soundboard/volume` | Lautstaerke setzen |
| POST | `/api/soundboard/upload` | Sound hochladen (Multipart) |
2026-03-09 00:19:53 +01:00
### Streaming Plugin
| Method | Pfad | Beschreibung |
|--------|------|-------------|
| WebSocket | `/ws` | Signaling (offer, answer, ice, viewer_joined, stream_ended) |
### Watch Together Plugin
| Method | Pfad | Beschreibung |
|--------|------|-------------|
| WebSocket | `/ws` | Raum-Sync (create, join, queue, vote, chat, playback) |
### Game Library Plugin
| Method | Pfad | Beschreibung |
|--------|------|-------------|
| GET | `/api/game-library/profiles` | Benutzerprofile |
| POST | `/api/game-library/profiles` | Profil erstellen/aktualisieren |
| GET | `/api/game-library/games` | Spieleliste (Steam + GOG) |
| POST | `/api/game-library/gog/exchange` | GOG OAuth Code Exchange |
### Notifications Plugin
| Method | Pfad | Beschreibung |
|--------|------|-------------|
| GET | `/api/notifications/config` | Kanal-Konfiguration lesen |
| POST | `/api/notifications/config` | Kanal-Konfiguration speichern |
2026-03-06 11:51:57 +01:00
## CI/CD Pipeline
GitLab CI mit Kaniko (`.gitlab-ci.yml` ):
2026-03-09 00:19:53 +01:00
| Stage | Job | Beschreibung |
|-------|-----|-------------|
| build | docker-build | Kaniko Multi-Platform Image Build |
| deploy | deploy | Docker Pull + Run auf adriahub |
| deploy | electron-build | Squirrel.Windows Installer + `.nupkg` + `.exe` |
| bump-version | bump-version | PATCH-Version in VERSION auto-inkrementieren |
| Branch | Tags | Version | Channel |
|--------|------|---------|---------|
| `main` | `latest` , `main` | `1.8.0` | `stable` |
| `nightly` | `nightly` | `x.y.z-nightly` | `nightly` |
| andere | `branch-name` | `x.y.z-dev` | `dev` |
2026-03-06 11:51:57 +01:00
2026-03-09 00:19:53 +01:00
Registry: `192.168.1.100:5050/root/gaming-hub`
2026-03-06 11:51:57 +01:00
## SSE Event Types
Alle Clients empfangen Events ueber `GET /api/events` :
| Event Type | Plugin | Beschreibung |
|-----------|--------|-------------|
| `snapshot` | - | Initialer Gesamtstatus beim Connect |
| `radio` | radio | Wiedergabestatus (playing/stopped) |
| `radio_volume` | radio | Lautstaerkeaenderung |
| `radio_voicestats` | radio | Voice-Ping, Gateway-Ping, Status, Uptime |
| `radio_favorites` | radio | Favoriten-Update |
| `soundboard_voicestats` | soundboard | Voice-Verbindungsdetails |
| `soundboard_nowplaying` | soundboard | Aktuell gespielter Sound |
| `soundboard_volume` | soundboard | Lautstaerkeaenderung |
| `soundboard_channel` | soundboard | Channel-Wechsel |
| `soundboard_party` | soundboard | Party-Modus Status |
## Discord Bot Setup
1. [Discord Developer Portal ](https://discord.com/developers/applications ) oeffnen
2026-03-09 00:19:53 +01:00
2. **Drei** Applications erstellen (z.B. "Jukebox Bot", "Radio Bot", "Notifications Bot")
2026-03-06 11:51:57 +01:00
3. Fuer jede Application:
- Bot erstellen unter "Bot"
- Token kopieren
- **Privileged Gateway Intents** aktivieren:
- Server Members Intent
- Message Content Intent (optional)
- Unter "OAuth2 > URL Generator":
- Scopes: `bot`
2026-03-09 00:19:53 +01:00
- Bot Permissions: `Connect` , `Speak` , `Use Voice Activity` , `Send Messages` , `Embed Links`
2026-03-06 11:51:57 +01:00
- Generierte URL im Browser oeffnen, Bot zum Server einladen
2026-03-09 00:19:53 +01:00
4. Tokens als `DISCORD_TOKEN_JUKEBOX` , `DISCORD_TOKEN_RADIO` und `DISCORD_TOKEN_NOTIFICATIONS` setzen
2026-03-06 11:51:57 +01:00
## Persistenz
Alle Daten werden im `DATA_DIR` (`/data` ) gespeichert:
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
```
/data/
2026-03-09 00:19:53 +01:00
├── sounds/
│ ├── hub-state.json # Plugin-State (Volumes, Favorites, Channels, Profiles, ...)
│ ├── sound1.mp3
│ ├── subfolder/
│ │ └── sound2.wav
│ └── ...
2026-03-06 11:51:57 +01:00
```
2026-03-05 21:46:11 +00:00
2026-03-09 00:19:53 +01:00
State wird automatisch bei Aenderungen geschrieben (Atomic Writes mit `.tmp` + `.bak` Rotation) und beim Start geladen.
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
## Dockerfile (Multi-Stage)
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
4 Build-Stages:
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
1. **web-build** - React/Vite Frontend kompilieren
2026-03-09 00:19:53 +01:00
2. **server-deps** - npm install + native Build-Tools (python3, make, g++)
3. **server-build** - TypeScript Backend kompilieren + Dev-Dependencies entfernen
4. **runtime** - Finales Image (node:24-slim) mit FFmpeg + kompiliertem Code
2026-03-05 21:46:11 +00:00
2026-03-06 11:51:57 +01:00
Finales Image enthaelt nur Production Dependencies, kein TypeScript/Dev-Tooling.
2026-03-09 00:19:53 +01:00
## Streaming Qualitaets-Presets
Der Streamer kann vor dem Broadcast ein Preset waehlen:
| Preset | Aufloesung | FPS | Bitrate |
|--------|-----------|-----|---------|
| 720p30 | 1280x720 | 30 | 2.5 Mbit/s |
| 1080p30 | 1920x1080 | 30 | 5 Mbit/s |
| 1080p60 | 1920x1080 | 60 | 8 Mbit/s |
| 1440p60 | 2560x1440 | 60 | 14 Mbit/s |
| 4K60 | 3840x2160 | 60 | 25 Mbit/s |
| 4K165 Ultra | 3840x2160 | 165 | 50 Mbit/s |
Standard: 1080p60. Das Dropdown ist waehrend eines aktiven Broadcasts deaktiviert.