Files
abdulive/docs/decisions/ADR-0004-docker.md
T
ZeasyAlexandClaude Opus 5 5f6301268a Native Windows-Auslieferung statt Container
Docker faellt weg. Das Projekt hat keine npm-Abhaengigkeiten und Node fuehrt
TypeScript direkt aus - der Container schrieb nur noch drei Programme fest,
und dafuer braucht es keine Virtualisierung, sondern einen Ordner.

Der Anlass war, dass ADR-0004 zwar `docker compose pull` versprach, es aber
nie ein veroeffentlichtes Image gab. Wer installieren wollte, musste
whisper.cpp aus dem Quelltext uebersetzen.

Plattformschicht (packages/core/src/platform.ts):
- Programme werden neben der Anwendung gesucht, nicht im PATH
- Daten unter %LOCALAPPDATA%, damit Installation und Update ohne
  Administratorrechte auskommen
- Schriften mitgeliefert: ohne fontsdir setzt libass wortlos eine
  Ersatzschrift ein - gemessen 720 statt 826 Pixel Zeilenbreite

Windows-Eigenheiten, an echtem ffmpeg 8.1 durchprobiert:
- Pfade im Filtergraphen brauchen alle drei Schritte (Vorwaertsschraegstriche,
  escapter Doppelpunkt, Anfuehrungszeichen); je zwei davon reichen nicht
- `nice` gibt es nicht, ersetzt durch os.setPriority

Auslieferung:
- scripts/build-package.ts baut das Paket, laeuft auch unter Linux
- install.ps1 ohne Administratorrechte, Autostart ueber den Aufgabenplaner
- update legt neue Fassungen bereit; eingespielt wird beim naechsten Start,
  nie mitten im Stream
- ZIP lesen und schreiben ohne Abhaengigkeiten (packages/core/src/zip.ts)

Kein `irm ... | iex`-Einzeiler: git.zeasy.dev antwortete instanzweit mit einer
Umleitung auf /user/login, und `iex` fuehrte die Anmeldeseite als PowerShell
aus. Der Updater verfolgt Umleitungen jetzt nicht und hat keine erfundene
Vorgabeadresse mehr.

Ausserdem: backup.ps1 war an zwei Stellen dokumentiert, aber nie geschrieben.

ADR-0007 ersetzt ADR-0004. 84 Tests, Typpruefung sauber.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AhVSfMFdWnXKCv5JfLnArZ
2026-09-09 17:39:26 +02:00

3.5 KiB
Raw Permalink Blame History

ADR-0004: Betrieb in Docker

Status: akzeptiert ersetzt durch ADR-0007 · Datum: 2026-09-09

Diese Entscheidung gilt nicht mehr. Das Toolkit laeuft nativ unter Windows. Die Analyse unten bleibt lesenswert - die vier Fallen, die sie beschreibt, waren real, und zwei davon (Pfaduebersetzung, Kopieren ueber die WSL2-Bruecke) sind mit dem Container weggefallen statt geloest worden zu sein. Warum gewechselt wurde, steht in ADR-0007.

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, 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.