# ADR-0007: Native Windows-Anwendung statt Container **Status:** akzeptiert · **Datum:** 2026-09-09 · **ersetzt:** [ADR-0004](ADR-0004-docker.md) ## Kontext ADR-0004 hat den Betrieb in Docker festgelegt und dabei zwei Dinge versprochen: „Die einzige Voraussetzung auf dem Stream-PC ist Docker Desktop und OBS" und „Updates sind ein `docker compose pull && up -d`". Das zweite Versprechen wurde nie eingelöst. Es gab keine CI, kein veröffentlichtes Image, und `image: abdulive/toolkit:dev` zeigte auf nichts. Wer das Toolkit installieren wollte, musste `docker compose build` ausführen — und damit **whisper.cpp aus dem Quelltext übersetzen**, gut zehn Minuten, mit allen Fehlermöglichkeiten eines Compilers. Für Abdu ist das nicht zumutbar. Beim Nachdenken über die Reparatur fiel auf, dass die Voraussetzung selbst teurer ist als der Nutzen. Die Kosten stehen ehrlich in ADR-0004: die WSL2-VM belegt im Leerlauf ein bis zwei GB RAM, und Intel QSV ist aus WSL2 heraus nicht verlässlich erreichbar, also bleibt CPU-Encoding — beides auf einem Rechner, der gleichzeitig streamt. Dem steht ein Umstand gegenüber, der die ursprüngliche Begründung untergräbt: **Das Projekt hat keine npm-Abhängigkeiten**, und Node führt TypeScript direkt aus (ADR-0001). Es gibt nichts zu bauen. Der Container schrieb also nur noch drei Programme fest — Node, ffmpeg, whisper.cpp — und dafür braucht es keine Virtualisierung, sondern einen Ordner. ## Entscheidung Das Toolkit wird als **native Windows-Anwendung** ausgeliefert. Ein Ordner mit allem darin, ein PowerShell-Installer, ein Updater. Kein Docker, kein WSL2. ``` abdulive/ node.exe portable Node-Laufzeit bin/ ffmpeg, ffprobe, whisper-cli und ihre DLLs fonts/ DejaVu Sans (im Repo mitgeliefert, siehe unten) app/ die TypeScript-Quellen, unverändert abdulive.cmd Kommandozeile launcher.ps1 vom Aufgabenplaner gestartet version.json ``` Gebaut wird mit `node scripts/build-package.ts` — lädt die drei Bausteine bei ihren Herausgebern, packt alles zusammen, schreibt Prüfsummen. Das läuft auch in der CI unter Linux. ## Begründung - **Abdu baut nichts.** Herunterladen, `install.ps1`, fertig. Kein Docker Desktop, kein `.wslconfig`, kein Compiler. - **Ein bis zwei GB RAM** stehen wieder dem Stream zur Verfügung. - **Hardware-Encoding wird erreichbar.** Der mitgelieferte ffmpeg ist mit `--enable-libvpl`, `--enable-amf` und `--enable-ffnvcodec` gebaut; QSV und AMF sind nativ ansprechbar. Genutzt wird das noch nicht — aber es ist jetzt möglich, und aus WSL2 heraus war es das nicht. - **Die Pfadübersetzung entfällt.** `mapReplayPath` musste OBS' Windows-Pfade auf `/replay` abbilden; laut Übergabe die Stelle, an der die Clip-Pipeline am ehesten scheitert. Nativ sieht die Anwendung denselben Pfad wie OBS. - **Kein Kopieren über die WSL2-Brücke mehr.** ADR-0004 Punkt 2 verbot das Verarbeiten auf dem Bind-Mount, weil es „ein Vielfaches der Zeit" kostet. Diese Klasse von Fehlern gibt es nicht mehr. ## Konsequenzen — was dabei zu beachten ist **1. Programme werden neben der Anwendung gesucht, nicht im PATH.** `packages/core/src/platform.ts` löst auf: erst die Umgebungsvariable (`FFMPEG_BIN` …), dann `bin/`, dann der PATH. Die Umgebungsvariable steht bewusst vorn — eine kaputte Mitlieferung lässt sich so ohne Neuinstallation überschreiben. **2. Schriften müssen mitgeliefert werden.** Im Container kam DejaVu Sans aus `fonts-dejavu-core` und libass fand sie über fontconfig. Windows hat DejaVu nicht. Fehlt der Ordner, setzt libass **wortlos** eine Ersatzschrift ein — gemessen: dieselbe Zeile wird 720 statt 826 Pixel breit, ohne jede Fehlermeldung. Deshalb liegen die Schriftdateien unter `assets/fonts/` im Repo, und `assFilter` setzt `fontsdir`. **3. Windows-Pfade im ffmpeg-Filtergraphen brauchen drei Schritte.** `C:\Users\…` enthält einen Doppelpunkt (trennt Filteroptionen) und Rückwärtsschrägstriche (ffmpeg-Escapes). An echtem ffmpeg 8.1 durchprobiert: | Form | Ergebnis | |---|---| | `ass=filename=C:/x/s.ass` | `No option name near '/x/s.ass'` | | `ass=filename=C\:/x/s.ass` | ebenso | | `ass=filename='C:/x/s.ass'` | ebenso | | `ass=filename='C\:/x/s.ass'` | läuft | Anführungszeichen allein schützen den Doppelpunkt nicht, das Escape allein auch nicht. `filterPath()` macht alle drei Schritte, mit Tests. **4. `nice` gibt es unter Windows nicht.** Ersetzt durch `os.setPriority` auf die Kind-PID. Das kann beides, braucht keinen Hilfsprozess davor, und das Zurückstufen darf jeder Benutzer. **5. Daten liegen unter `%LOCALAPPDATA%\abdulive`, nicht neben dem Programm.** Ein Update tauscht den Programmordner komplett aus; die Datenbank darf dabei nicht mitgehen. `LOCALAPPDATA` und nicht `ProgramData`, weil die Anwendung als angemeldeter Benutzer läuft — dieselbe Sitzung wie OBS. Damit braucht weder Installation noch Update Administratorrechte. Genau daran scheitern Aktualisierungen sonst auf einem Rechner, an dem gerade gestreamt wird. **6. Autostart über den Aufgabenplaner, nicht als Windows-Dienst.** Ein Dienst liefe unter SYSTEM in einer anderen Sitzung als OBS, bräuchte Administratorrechte und ein zusätzliches Wrapper-Programm (nssm, WinSW). Die Aufgabe `abdulive` startet bei der Anmeldung, versteckt, mit Neustart nach zwei Minuten bei Absturz. **7. Updates werden bereitgelegt, nicht sofort eingespielt.** Windows sperrt die Dateien laufender Programme — `node.exe` lässt sich nicht ersetzen, solange es läuft. `abdulive update` prüft das Manifest, lädt das Paket, **prüft die SHA256** und legt es unter `pending/` ab. `launcher.ps1` tauscht beim nächsten Start aus, bevor irgendetwas startet. Damit gibt es nie einen halb ausgetauschten Ordner, und mitten im Stream wird nichts angefasst. Schlägt der Tausch fehl, läuft die alte Fassung weiter. **Kosten, ehrlich benannt:** - **Die Umgebung ist nicht mehr festgeschrieben.** Der Container garantierte „kein läuft bei mir". Jetzt garantiert das nur noch der Paketinhalt — Node, ffmpeg und whisper sind mitgeliefert, aber Windows selbst ist es nicht. - **Kein Code-Signing.** SmartScreen warnt beim ersten Start vor einem unbekannten Herausgeber. Ein Zertifikat kostet Geld; bis dahin muss man einmal auf „Trotzdem ausführen" klicken. Steht in `offene-punkte.md`. - **Windows-only.** Ein Linux-Paket gibt es nicht mehr. Für ein Werkzeug, das neben OBS auf einem Windows-Stream-PC läuft, ist das kein Verlust — die Pfade in `platform.ts` kennen den Linux-Fall aber weiterhin, und die Tests laufen dort. - **Drei Bausteine wollen gepflegt werden.** Node, ffmpeg und whisper.cpp aktualisieren sich nicht von selbst. `build-package.ts` holt jeweils die aktuelle Ausgabe und schreibt Name und Prüfsumme nach `version.json` — was drin ist, lässt sich also nachlesen.