Monorepo-Geruest fuer neun Streamer-Tools plus den Ingest-Daemon, der unter sechs davon liegt. Enthaelt: - docs/: Ueberblick, Architektur, Twitch-Integration, Datenmodell, Roadmap, Setup, Hebel-Analyse und den MVP-Plan "Clip-Knopf" - docs/projects/: je eine Spezifikation pro Tool - docs/decisions/: vier ADRs (TS-Monorepo, SQLite, EventSub/IRC, Docker) - docker/: Image mit ffmpeg und whisper.cpp, abhaengigkeitsfreier Entrypoint mit check-env, fetch-model und calibrate - config/layout.yaml: aus einem VOD-Screenshot eingemessener Facecam-Ausschnitt (440x330 oben links, Chat-Overlay ab x=1270) Noch kein Anwendungscode - Scheibe S0 aus docs/07-mvp-plan.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013VTGjd92LsDDWF3frd9FTB
2.7 KiB
Ingest-Daemon (apps/ingest)
Kein eigenes "Tool" im Sinne der Wunschliste, sondern das Fundament, auf dem sechs der neun Tools stehen. Wird zuerst gebaut.
Aufgabe
Ein Prozess, der dauerhaft läuft und alle Datenquellen in einen einheitlichen Event-Strom übersetzt: schreibt in SQLite, publiziert auf dem Bus.
Quellen
| Quelle | Verbindung | liefert |
|---|---|---|
| Twitch IRC | wss://irc-ws.chat.twitch.tv:443 |
Chat-Nachrichten mit Tags |
| Twitch EventSub | wss://eventsub.wss.twitch.tv/ws |
Follows, Subs, Raids, Kategorie, Online/Offline |
| Twitch Helix | REST, Polling 60 s | Viewerzahl, Chatter-Liste (5 min) |
| obs-websocket | ws://127.0.0.1:4455 |
Szenenwechsel, Replay-Buffer-Events |
Was der Ingest selbst berechnet
Stream-Sessions. stream.online legt eine streams-Zeile an,
stream.offline schließt sie. Wenn der Daemon mitten im Stream startet, wird
die laufende Session über GET /helix/streams rekonstruiert. Kurze
Unterbrechungen (< 5 min) werden als dieselbe Session behandelt — sonst
zerfallen Streams bei jedem Verbindungsabbruch in Fragmente.
Chat-Spikes. Gleitendes Fenster über die Nachrichtenrate:
rate(t) = Nachrichten in den letzten 15 s
baseline(t) = Median von rate über die letzten 10 min
spike = rate >= max(baseline * 3, baseline + 4)
&& Zeit seit letztem Spike > 60 s
Zusätzlich gewichtet: Lach-Emotes (KEKW, LUL, OMEGALUL, Kanal-Emotes),
Ausrufe (?!, Großbuchstaben-Anteil), das Wort clip. Ergebnis ist ein
chat.spike-Event mit score. Wer darauf reagiert, entscheidet der Konsument.
Bei 10 Zuschauern ist die Baseline klein und die Statistik dünn. Der Detektor ist deshalb bewusst konservativ und protokolliert alle Kandidaten mit Score, auch die unter der Schwelle — so lässt sich die Schwelle nachträglich am echten Material kalibrieren, statt sie zu raten.
Anwesenheit. Aus GET /helix/chat/chatters (alle 5 min) plus jeder
Nachricht wird user_streams fortgeschrieben: Ersterscheinung, letzte
Aktivität, Minuten. Daraus fällt streams_present für jeden User ab.
Schnittstellen nach außen
- WS
ws://127.0.0.1:4790— Broadcast aller Events als JSON-Zeilen. Ein Client kann beim Connect{"since":"<iso-ts>"}senden und bekommt die verpassten Events aus der DB nachgeliefert. - HTTP
GET /health— Status aller vier Verbindungen, für das Dashboard.
Abnahmekriterien
- Läuft 7 Tage ohne Neustart durch, inklusive Twitch-Reconnects.
- Nach einem erzwungenen Prozess-Kill mitten im Stream: Neustart rekonstruiert
die laufende Session, keine doppelten
streams-Zeilen, keine doppelten Events. - Jede Chat-Nachricht eines Test-Streams ist in
chat_messages(Abgleich gegen ein parallel mitgeschriebenes Log).