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
This commit is contained in:
ZeasyAlexandClaude Opus 5 committed 2026-09-09 17:39:26 +02:00
1 parent 71dd660d01
commit 5f6301268a
41 files changed
+2254 -312

No files matched your search

+82 -52
View File
@@ -1,34 +1,51 @@
# Setup
Alles läuft in Containern. Auf dem Rechner selbst wird nur Docker Desktop und
OBS gebraucht — ffmpeg, whisper.cpp, Node und pnpm stecken im Image.
Begründung: [ADR-0004](decisions/ADR-0004-docker.md).
Eine native Windows-Anwendung. Node, ffmpeg, whisper.cpp und die Schriften
sind mitgeliefert — vorausgesetzt wird nur OBS.
Begruendung: [ADR-0007](decisions/ADR-0007-native-windows.md).
## Voraussetzungen
| Was | Version | Wo |
| Was | Version | Anmerkung |
|---|---|---|
| Docker Desktop | aktuell, WSL2-Backend | Host |
| OBS Studio | 30+ mit obs-websocket v5 | Host |
| Git | beliebig | Host |
| Windows | 10 oder 11, 64 Bit | |
| OBS Studio | 30+ mit obs-websocket v5 | derselbe Rechner |
Alles Weitere (Node 22, pnpm, ffmpeg mit libx264/libass, whisper.cpp,
Sprachmodell) liefert das Image.
Mehr nicht. Kein Docker, kein WSL2, kein Compiler, kein Git.
## WSL2 begrenzen
## Installieren
Docker Desktop startet eine VM, die sich ohne Grenze so viel RAM nimmt, wie sie
kriegen kann. Auf einem Stream-PC ist das nicht egal. `%USERPROFILE%\.wslconfig`
anlegen:
Das Paket herunterladen, entpacken, darin `install.ps1` ausfuehren:
```ini
[wsl2]
memory=4GB
processors=4
swap=2GB
```powershell
Expand-Archive .\abdulive-0.5.0-win-x64.zip -DestinationPath .\abdulive
.\abdulive\install.ps1
```
Danach `wsl --shutdown` und Docker Desktop neu starten.
Liegt das Paket an einer Adresse **ohne** Anmeldung, holt der Installer es
selbst:
```powershell
.\install.ps1 -Quelle https://.../abdulive
```
> Ein `irm … | iex`-Einzeiler funktioniert mit `git.zeasy.dev` nicht. Die
> Instanz verlangt fuer alles eine Anmeldung und antwortet mit einer Umleitung
> auf `/user/login`; `iex` fuehrt dann die Anmeldeseite als PowerShell aus.
> Wo die Pakete liegen sollen, ist noch zu entscheiden.
Der Installer laeuft **ohne Administratorrechte**:
| Was | Wohin |
|---|---|
| Programm | `%LOCALAPPDATA%\Programs\abdulive` |
| Daten, Datenbank, Clips | `%LOCALAPPDATA%\abdulive` |
| Autostart | Aufgabe `abdulive`, bei der Anmeldung |
| Update-Pruefung | Aufgabe `abdulive-update`, taeglich 05:00 |
Beim ersten Start warnt Windows SmartScreen vor einem unbekannten Herausgeber —
das Paket ist nicht signiert. Einmal auf *Weitere Informationen* → *Trotzdem
ausfuehren*.
## Twitch-Apps anlegen
@@ -64,60 +81,73 @@ im Einrichtungs-Assistenten einfügen (siehe unten). Begründung:
## Erste Einrichtung
```powershell
Copy-Item config\config.example.yaml config\config.yaml
docker compose build
docker compose run --rm toolkit check-env # ffmpeg, whisper, Modell, Volumes, Layout
docker compose run --rm toolkit fetch-model # Sprachmodell, ca. 465 MB
docker compose up -d
abdulive check-env # ffmpeg, whisper, Schriften, Verzeichnisse, Layout
abdulive fetch-model # Sprachmodell, ca. 465 MB
Start-ScheduledTask -TaskName abdulive
```
Dann **http://localhost:4792/setup** öffnen. Dort werden nacheinander
eingetragen:
Dann **http://localhost:4792/setup** oeffnen: Client-ID und Secret der beiden
Twitch-Apps eintragen und je einmal auf „Mit Twitch verbinden" klicken.
1. Client-ID und Client-Secret der beiden Twitch-Apps
2. „Mit Twitch verbinden" für Broadcaster- und Bot-Konto (OAuth)
3. obs-websocket-Passwort
4. später: Discord-Webhook, Bluesky-Zugang
Alles landet verschlüsselt im Docker-Volume, nicht in einer Datei im Projekt.
> **Diese Seite zeigt Zugangsdaten. Nicht öffnen, während gesendet wird.**
Eine `.env` ist optional und enthält nur noch den Pfad zum Wiedergabepuffer
und das Log-Level (Vorlage: `.env.example`).
## Facecam einmessen
Einmalig, sobald eine Replay-Datei vorliegt:
## Layout einmessen
```powershell
docker compose run --rm toolkit calibrate
abdulive calibrate
```
Legt einen Frame als PNG in `data/clips/_calibration/` ab, fragt die vier
Crop-Werte ab und schreibt sie nach `config/layout.yaml`.
Legt einen Frame als PNG unter `%LOCALAPPDATA%\abdulive\clips\_calibration`
ab und rendert die 9:16-Vorschau dazu. Anleitung: [`obs-layout.md`](obs-layout.md).
Welche OBS-Quelle im Ausschnitt landet — etwa fremde Untertitel:
```powershell
abdulive sources
```
## Betrieb
```powershell
docker compose up -d # startet
docker compose logs -f # Logs
docker compose down # stoppt
Start-ScheduledTask -TaskName abdulive # startet
Stop-ScheduledTask -TaskName abdulive # stoppt
Get-Content "$env:LOCALAPPDATA\abdulive\logs\abdulive.log" -Wait -Tail 40
```
Sichtungsseite: http://localhost:4792
## Aktualisieren
```powershell
abdulive update
```
Prueft das Manifest, laedt das Paket, vergleicht die SHA256 und legt es
bereit. Die Adresse steht in `config.yaml` unter `update.url` und hat
**keine Vorgabe** — ohne Eintrag sagt der Befehl das auch. Liegt die Ablage
hinter einer Anmeldung, gehoert ein Lese-Token in den verschluesselten
Speicher (Einrichtungsseite), nicht in die `config.yaml`. **Eingespielt wird es beim naechsten Start** — waehrend eines Streams
wird nichts ausgetauscht. Sofort uebernehmen:
```powershell
Stop-ScheduledTask -TaskName abdulive; Start-ScheduledTask -TaskName abdulive
```
Die Aufgabe `abdulive-update` macht die Pruefung taeglich um 05:00 von selbst.
## Backup
```powershell
.\scripts\backup.ps1
```
Kopiert die Datenbank per `VACUUM INTO` aus dem Volume `abdulive-db` nach
`data/db/backup/` und hält 30 Generationen. Die DB liegt bewusst in einem
Docker-Volume und nicht in einem Windows-Ordner — Dateisperren über die
WSL2-Brücke sind für SQLite nicht verlässlich.
Kopiert die Datenbank per `VACUUM INTO` aus `%LOCALAPPDATA%\abdulive\db`
nach `backup\` und haelt 30 Generationen. `VACUUM INTO` und nicht einfach
kopieren: die Datei wird im laufenden Betrieb gesichert, und ein Kopieren
waehrend eines Schreibvorgangs ergaebe eine unbrauchbare Sicherung.
Die Datenbank liegt seit [ADR-0007](decisions/ADR-0007-native-windows.md)
in einem gewoehnlichen Windows-Ordner. Der Grund fuer das fruehere
Docker-Volume - unzuverlaessige Dateisperren ueber die WSL2-Bruecke - ist
mit dem Container weggefallen.
## Was nicht ins Repo gehört