jukebox-vibe/README.md

223 lines
7 KiB
Markdown
Raw Permalink Normal View History

2026-03-05 11:13:03 +01:00
# Jukebox Vibe Discord Soundboard
Self-hosted Discord Soundboard mit Web-UI. Spielt Sounds in Discord Voice Channels, verwaltet per Browser. Dockerized, ein Container, fertig.
## Tech Stack
| Komponente | Technologie |
|---|---|
| **Backend** | Node.js 20, Express, TypeScript, discord.js 14 |
| **Voice** | @discordjs/voice 0.19, @discordjs/opus, DAVE E2EE (@snazzah/davey) |
| **Frontend** | React 18, Vite, TypeScript, Custom CSS |
| **Audio** | ffmpeg (EBU R128 Loudnorm), yt-dlp |
| **Deployment** | Multi-Stage Dockerfile, GitLab CI/CD (Kaniko) |
## Features
### Soundboard
- **MP3/WAV Playback** in Discord Voice Channels
- **Loudness Normalization** (EBU R128) mit PCM-Cache fuer Instant-Playback
- **Per-Guild Volume** (0-100%), live adjustable, persistiert
- **Party Mode** zufaellige Sounds alle 30-90 Sekunden
- **Stop/Panic** sofortiger Playback-Stop fuer alle
### Discord Bot
- **Entrance Sounds** persoenlicher Sound beim Channel-Join
- **Exit Sounds** Sound beim Disconnect (nicht bei Channel-Wechsel)
- **DM Upload** Sounds per Direktnachricht an den Bot hochladen
- **Voice Resilience** 3-Tier Reconnect mit Exponential Backoff
### Web-UI
- **Sound Grid** mit klickbaren Cards
- **Suche** mit optionalem Fuzzy-Matching
- **Ordner-Filter** mit farbigen Chips
- **Favoriten** (Cookie-basiert)
- **Kategorien** und **Badges** (Admin-verwaltet)
- **Channel-Selector** gruppiert nach Guild
- **Now Playing** Anzeige mit Wellenform-Animation
- **5 Themes** Discord, Midnight, Forest, Sunset, Ocean
- **Card-Size Slider** (80-160px)
- **Drag & Drop Upload** (Admin)
- **MP3-URL Import** direkter Download und Playback
- **Real-Time Sync** via Server-Sent Events (SSE)
### Admin
- **Login** mit HMAC-SHA256 Token (HttpOnly Cookie, 7 Tage)
- **Bulk Delete / Rename** von Sounds
- **Upload** bis zu 20 Dateien (je max. 50MB)
- **Kategorien** erstellen, bearbeiten, loeschen, zuweisen
- **Custom Badges** zuweisen/entfernen
## Quickstart
### Voraussetzungen
- Docker
- Discord Bot Token mit Intents: `Guilds`, `GuildVoiceStates`, `GuildMembers`, `DirectMessages`, `MessageContent`
### Setup
2025-08-07 23:24:56 +02:00
```bash
2026-03-05 11:13:03 +01:00
git clone https://git.daddelolymp.de/root/jukebox-vibe.git
cd jukebox-vibe
cp .env.example .env
2026-03-05 11:13:03 +01:00
# .env anpassen (DISCORD_TOKEN, ADMIN_PWD)
docker compose up -d
```
2026-03-05 11:13:03 +01:00
### Docker Run (ohne Compose)
2025-08-07 23:24:56 +02:00
```bash
2026-03-05 11:13:03 +01:00
docker run -d \
--name jukebox \
-p 8199:8080 \
-e DISCORD_TOKEN=dein_token \
-e ADMIN_PWD=dein_passwort \
-v $(pwd)/sounds:/data/sounds \
--restart unless-stopped \
git.daddelolymp.de/root/jukebox-vibe:latest
2025-08-07 23:24:56 +02:00
```
2026-03-05 11:13:03 +01:00
## Konfiguration
2026-03-05 11:13:03 +01:00
| Variable | Default | Beschreibung |
|---|---|---|
| `DISCORD_TOKEN` | *erforderlich* | Discord Bot Token |
| `ADMIN_PWD` | `''` | Admin-Passwort fuer Web-UI |
| `PORT` | `8080` | Server Port |
| `SOUNDS_DIR` | `/data/sounds` | Sound-Verzeichnis (Docker Volume) |
| `ALLOWED_GUILD_IDS` | `''` | Komma-getrennte Guild-IDs (leer = alle) |
| `NORMALIZE_ENABLE` | `true` | Loudness Normalization an/aus |
| `NORMALIZE_I` | `-16` | Ziel-Lautstaerke in LUFS |
| `NORMALIZE_LRA` | `11` | Loudness Range |
| `NORMALIZE_TP` | `-1.5` | True Peak in dBTP |
| `NORM_CONCURRENCY` | `2` | Parallele ffmpeg-Prozesse |
2025-08-07 23:24:56 +02:00
2026-03-05 11:13:03 +01:00
## Bot Commands
2026-03-05 11:13:03 +01:00
Alle Commands per DM an den Bot oder im Server-Chat:
2025-08-07 23:24:56 +02:00
2026-03-05 11:13:03 +01:00
| Command | Beschreibung |
|---|---|
| `?help` | Hilfe anzeigen |
| `?list` | Alle Sounds auflisten |
| `?entrance <datei>` | Entrance-Sound setzen |
| `?entrance remove` | Entrance-Sound entfernen |
| `?exit <datei>` | Exit-Sound setzen |
| `?exit remove` | Exit-Sound entfernen |
2026-03-05 11:13:03 +01:00
**Upload via DM:** MP3/WAV als Anhang an den Bot senden wird automatisch gespeichert und normalisiert.
2026-03-05 11:13:03 +01:00
## API
2026-03-05 11:13:03 +01:00
### Public
2025-08-07 23:24:56 +02:00
```
2026-03-05 11:13:03 +01:00
GET /api/health Healthcheck + Stats
GET /api/sounds Sound-Liste (query: q, folder, categoryId, fuzzy)
GET /api/analytics Top 10 Most Played, Gesamt-Plays
GET /api/channels Verfuegbare Voice Channels
GET /api/selected-channels Gespeicherte Channel-Auswahl
POST /api/selected-channel Channel-Auswahl setzen
POST /api/play Sound abspielen (body: soundName, guildId, channelId)
POST /api/play-url MP3-URL downloaden und abspielen
POST /api/stop Playback stoppen
GET /api/volume Volume abfragen
POST /api/volume Volume setzen (0-1)
POST /api/party/start Party Mode starten
POST /api/party/stop Party Mode stoppen
GET /api/events SSE Stream (Real-Time Updates)
```
2025-08-07 23:24:56 +02:00
2026-03-05 11:13:03 +01:00
### Admin (Cookie-Auth)
2026-03-05 11:13:03 +01:00
```
POST /api/admin/login Login (body: password)
POST /api/admin/logout Logout
GET /api/admin/status Auth-Status pruefen
POST /api/upload Dateien hochladen (multipart, max 20x50MB)
POST /api/admin/sounds/delete Sounds loeschen (body: paths[])
POST /api/admin/sounds/rename Sound umbenennen
GET /api/categories Kategorien auflisten
POST /api/categories Kategorie erstellen
PATCH /api/categories/:id Kategorie bearbeiten
DELETE /api/categories/:id Kategorie loeschen
POST /api/categories/assign Kategorien zuweisen
POST /api/badges/assign Badges zuweisen
POST /api/badges/clear Badges entfernen
2025-08-07 23:24:56 +02:00
```
2026-03-05 11:13:03 +01:00
## Sound-Dateien
2025-08-07 23:24:56 +02:00
2026-03-05 11:13:03 +01:00
```
/data/sounds/
state.json # Persistierter State (Volumes, Plays, Kategorien, etc.)
.norm-cache/ # Normalisierte PCM-Caches
airhorn.mp3 # Sounds im Root
memes/ # Ordner-Struktur (1 Ebene)
bruh.mp3
oof.wav
2025-08-07 23:24:56 +02:00
```
2026-03-05 11:13:03 +01:00
- Formate: `.mp3`, `.wav`
- Ordner werden als Filter-Chips im Frontend angezeigt
- `.norm-cache/` wird automatisch verwaltet (Cache-Invalidierung bei Datei-Aenderung)
2026-03-05 11:13:03 +01:00
## Loudness Normalization
2026-03-05 11:13:03 +01:00
Alle Sounds werden per ffmpeg `loudnorm` (EBU R128) normalisiert:
2026-03-05 11:13:03 +01:00
1. **Startup:** Hintergrund-Sync normalisiert alle uncached Sounds
2. **Cache Hit:** Gecachte PCM-Datei wird direkt gestreamt (kein ffmpeg, instant)
3. **Cache Miss:** ffmpeg streamt live zum Player UND schreibt gleichzeitig in Cache
4. **Upload:** Neue Dateien werden sofort im Hintergrund normalisiert
2026-03-05 11:13:03 +01:00
## Voice Connection
2026-03-05 11:13:03 +01:00
3-stufiges Recovery bei Verbindungsproblemen:
2026-03-05 11:13:03 +01:00
1. **Wait for Ready** (15s Timeout)
2. **Rejoin** im selben Channel (15s Timeout)
3. **Destroy + Fresh Join** (15s Timeout)
2026-03-05 11:13:03 +01:00
Lifecycle-Handler mit:
- Max 3 Reconnect-Versuche mit Exponential Backoff
- Anti-Reentrancy Guard gegen Endlosschleifen
- Automatisches State-Cleanup bei totalem Verbindungsverlust
2026-03-05 11:13:03 +01:00
## Projektstruktur
2026-03-05 11:13:03 +01:00
```
jukebox-vibe/
server/
src/index.ts # Server + Discord Bot (Hauptdatei)
package.json
tsconfig.json
web/
src/
App.tsx # React SPA
styles.css # Themes + Layout
types.ts # TypeScript Types
package.json
vite.config.ts
Dockerfile # Multi-Stage Build (web + server + runtime)
docker-compose.yml
.gitlab-ci.yml # CI/CD Pipeline (Kaniko)
.env.example
2025-08-07 23:24:56 +02:00
```
2026-03-05 11:13:03 +01:00
## CI/CD
2025-08-07 23:24:56 +02:00
2026-03-05 11:13:03 +01:00
GitLab CI baut automatisch bei jedem Push:
2025-08-07 23:24:56 +02:00
2026-03-05 11:13:03 +01:00
| Branch | Image Tag |
|---|---|
| `main` | `:main`, `:latest`, `:sha` |
| `nightly` | `:nightly`, `:sha` |
| andere | `:<branch-name>`, `:sha` |
2025-08-07 23:24:56 +02:00
2026-03-05 11:13:03 +01:00
Registry: `git.daddelolymp.de/root/jukebox-vibe`
2025-08-07 23:24:56 +02:00
2026-03-05 11:13:03 +01:00
## Lizenz
2025-08-07 23:24:56 +02:00
2026-03-05 11:13:03 +01:00
MIT