# ADR-0004: Betrieb in Docker **Status:** akzeptiert · **Datum:** 2026-09-09 ## Kontext Das Toolkit braucht ffmpeg, ein Whisper-Modell, Node und SQLite. Der Check der Zielmaschine ergab: kein ffmpeg, kein pnpm, Python 3.14 (für das `ctranslate2` — die Basis von faster-whisper — noch keine verlässlichen Wheels liefert), keine NVIDIA-GPU. Das Toolkit soll auf Abdus Stream-PC laufen, also auf einem Rechner, dessen Umgebung sich unabhängig vom Projekt ändert. ## Entscheidung Alles läuft in Containern, orchestriert über `docker-compose`. Die einzige Voraussetzung auf dem Stream-PC ist Docker Desktop und OBS. ## Begründung - Die gesamte Toolchain (Node 22, ffmpeg mit libx264/libass, whisper.cpp, das Sprachmodell) ist im Image festgeschrieben. Kein "läuft bei mir". - Der Python-Konflikt entfällt vollständig, weil kein Python mehr gebraucht wird (siehe [ADR-0001](ADR-0001-monorepo-typescript.md), aktualisiert). - Updates sind ein `docker compose pull && up -d`, kein Nachinstallieren auf einem Rechner, der gerade streamt. ## Konsequenzen — die vier Dinge, die man dabei falsch machen kann **1. Die SQLite-Datei gehört nicht in einen Windows-Bind-Mount.** Dateisperren über die 9p/virtiofs-Brücke zwischen Windows und WSL2 sind unzuverlässig; SQLite im WAL-Modus reagiert darauf mit `SQLITE_BUSY`/`database is locked` und im schlimmsten Fall mit Korruption. Die Datenbank liegt deshalb in einem **benannten Docker-Volume** (`abdulive-db`). Backups werden per Skript aus dem Volume nach Windows kopiert, nicht durch direktes Mounten. **2. Große Mediendateien nicht über den Bind-Mount verarbeiten.** Das OBS-Replay-Verzeichnis wird nur lesend gemountet. Die Rohdatei wird **einmal** in ein containerlokales Volume kopiert, dort verarbeitet, und nur das fertige Ergebnis wird zurück nach `data/clips/` geschrieben. Direkt auf dem Bind-Mount zu encodieren kostet ein Vielfaches der Zeit. **3. OBS läuft auf dem Host, nicht im Container.** Erreichbar über `host.docker.internal:4455`. In `docker-compose.yml` steht `extra_hosts: ["host.docker.internal:host-gateway"]`, damit es auch außerhalb von Docker Desktop funktioniert. **4. Ein globaler Windows-Hotkey lässt sich aus einem Container nicht abfangen.** Deshalb wird gar nicht erst versucht, einen eigenen Hotkey-Dienst zu bauen: Der Hotkey wird **in OBS** auf "Wiedergabepuffer speichern" gelegt. OBS meldet danach über obs-websocket das Ereignis `ReplayBufferSaved` mit dem Dateipfad — das ist der Trigger. Kein Agent auf dem Host, kein zusätzlicher Autostart. **Kosten, ehrlich benannt:** Docker Desktop startet eine WSL2-VM, die im Leerlauf ein bis zwei GB RAM belegt und beim Encodieren CPU zieht, die dem Stream fehlt. Gegenmaßnahmen: `.wslconfig` mit `memory=4GB` und `processors=4`, ffmpeg mit `-preset veryfast` und niedriger Priorität, und Rendering standardmäßig **nach** Streamende (`clipper.renderWhileLive: false`), sofern die Kandidatenliste erst danach gebraucht wird. **GPU:** Kein NVENC (keine NVIDIA-Karte), und Intel QSV ist aus WSL2 heraus nicht verlässlich erreichbar. Es bleibt bei CPU-Encoding mit libx264. Für Clips von 30–60 Sekunden ist das unkritisch.