# 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":""}` 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).