Files
abdulive/docs/decisions/ADR-0004-docker.md
T
ZeasyAlexandClaude Opus 5 d09e2b945a Struktur, Doku und S0-Toolchain fuer das abdulive-Toolkit
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
2026-09-09 08:56:09 +02:00

64 lines
3.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.