Raid-Scout, Auswertung, VOD-Kapitel, Community-Gedaechtnis, Punkteshop und Recap samt Platzhaltern, Spezifikationen und Konfiguration. Der Hub schickt am Chat zusaetzlich die Sendezeit mit, fuer die Uhrzeit im Pult. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
5.7 KiB
Architektur
Bild
Stand vor dem Umzug in den Hub (ADR-0008). Raid-Scout, Auswertung, VOD-Kapitel, Community-Gedaechtnis und Recap sind seit 2026-10-27 gestrichen.
Twitch OBS
┌──────────────────┐ ┌───────────┐
│ EventSub (WS) │ │ obs- │
│ IRC / Chat │ │ websocket │
│ Helix REST │ └─────┬─────┘
└────────┬─────────┘ │
│ │
┌────────▼────────────────────────▼────────┐
│ apps/ingest (Daemon) │
│ normalisiert alles zu Events │
└────────┬─────────────────────┬───────────┘
│ │
schreibt │ │ publiziert
▼ ▼
┌─────────────────┐ ┌──────────────────────┐
│ SQLite │ │ Event-Bus │
│ data/db/ │ │ (in-proc + WS 4790) │
└─────────────────┘ └──────────┬───────────┘
│
┌─────────┴─────────┐
▼ ▼
overlay-server clipper-Kette
(Pult, Sounds) ffmpeg, whisper
│ │
overlay-web data/clips
(Browser-Source)
Prozesse
Ein Prozess. Oberflaeche, Ingest und die Werkzeugmodule laufen gemeinsam in einem Container; schwere Arbeit (ffmpeg, whisper.cpp) laeuft als Kindprozess und darf abstuerzen, ohne die Chat-Aufnahme mitzureissen. Begruendung und Grenzen: ADR-0006.
| Port | Wofuer |
|---|---|
| 4792 | Weboberflaeche: Einrichtung, OAuth-Rueckruf, Sichtung, Dashboard, /health |
| 4791 | Overlay-Server fuer die OBS-Browser-Quellen (ab M3) |
Beide nur auf 127.0.0.1 des Hosts veroeffentlicht.
Die Werkzeuge sind Module, keine eigenen Dienste:
| Modul | laeuft | Ausloeser |
|---|---|---|
| Ingest | dauernd | IRC, EventSub, Helix-Polling |
| Community, Loyalty | dauernd | Chat-Ereignisse |
| Clipper | bei Bedarf | !clip, OBS-Hotkey, spaeter Chat-Spitze |
| Broadcaster | bei Bedarf | stream.online |
| Recap, VOD-Kapitel | bei Bedarf | stream.offline |
| Raid-Scout | bei Bedarf | !raidziel, Oberflaeche |
Event-Bus
Der Ingest normalisiert alles auf ein einheitliches Event-Format:
type StreamEvent = {
id: string; // ULID
ts: string; // ISO-8601, UTC
type: EventType; // 'chat.message' | 'stream.online' | ...
streamId: string | null;
userId: string | null;
payload: unknown; // typisiert pro EventType
};
Transport: ein EventEmitter im Prozess. Solange alles unter einem Dach laeuft
(ADR-0006), braucht es keinen Netzwerk-Bus. Die events-Tabelle ist trotzdem
die Wahrheit: sie wird immer geschrieben, und ein spaeter herausgeloester
Prozess kann seinen Rueckstand ueber ts > lastSeen aufholen.
Vollständige Event-Liste: siehe 03-data-model.md.
Pakete
| Paket | Inhalt |
|---|---|
packages/shared |
Ereignistypen, ULID |
packages/core |
Config, Layout, Logger mit Maskierung, Retry, YAML-Leser |
packages/twitch |
Secret-Speicher, OAuth, Helix-Client, IRC-Client |
packages/db |
SQLite-Verbindung, Migrationen, Repositories |
Regel: Apps dürfen von Paketen abhängen, Pakete nie von Apps. Apps hängen nicht voneinander ab — Kommunikation läuft über Bus und DB.
Importiert wird über die imports-Map der Wurzel-package.json
(#core/config.ts, #db/repos.ts). Das ist eine Node-Funktion, kein
Build-Werkzeug — es gibt keinen Bundler und keine Pfad-Aliasse im Compiler.
Technologie
- TypeScript auf Node 24, ohne Build-Schritt und ohne
Laufzeitabhängigkeiten — Node führt die
.ts-Dateien direkt aus. Siehe ADR-0001 - SQLite über das eingebaute
node:sqlite— siehe ADR-0002 - EventSub über WebSocket, nicht Webhooks — siehe ADR-0003
- ffmpeg (CLI) für Videoverarbeitung
- whisper.cpp (CLI) für Untertitel — kein Python, keine GPU
- Serverseitiges HTML ohne Framework für Einrichtung und Sichtungsseite; für Dashboard und Overlays ab M3 ggf. Vite + Preact
- Docker Compose für den Betrieb — siehe ADR-0004
Fehlerverhalten
- Jeder Netzwerkaufruf hat Retry mit exponentiellem Backoff (
packages/core/retry). - Der Ingest darf niemals wegen eines Konsumentenfehlers sterben. Konsumenten
laufen in eigenen Prozessen; ein Fehler dort schreibt in
logs/und wird im Dashboard als Warnung angezeigt. - Wenn EventSub die Verbindung verliert: Reconnect mit Session-Resume, danach
Lücke über Helix-Polling schließen (
stream.online-Status, Follower-Liste).