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
135 lines
6.8 KiB
Markdown
135 lines
6.8 KiB
Markdown
# 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.
|