Commander: „Das soll NICHT Teil des neuen Standalone-Produktes sein, da dieser NUR fuer die Docker-Variante verwendet wird." Damit ist bestaetigt, was in Paragraph 11.1 zuvor nur als Auslegung stand. Der Remote-Encode-Worker wird WEDER abgeraeumt (er ist Docker, und Docker bleibt unangetastet — Entscheid 2) NOCH nach v5 uebernommen (v5 ist Einzelplatz, Entscheid 3 — es gibt dort keinen zweiten Knoten, dem man etwas schicken koennte). Dazu die eigentliche Reparatur an diesem Abschnitt: Er war in Entwickler-Begriffen geschrieben (Modulnamen, PyInstaller, os.name-Zweige) und deshalb fuer den Adressaten nicht lesbar — zweimal nachgefragt, zweimal zu Recht. Paragraph 11.1 fuehrt die drei Teile jetzt erst in Klartext ein: A ist Rippy. B ist ein Handlanger fuer die VM. C sind Notizzettel, die wegen A eingeklebt wurden. Und macht den Unterschied A/C an dem fest, worauf es beim Aufraeumen ankommt — nicht am Inhalt, sondern am Ort: A sind ganze Ordner, die Docker nie aufschlaegt (wegwerfen). C sind einzelne Seiten in Ordnern, die Docker taeglich benutzt (einzeln durchgehen). Erst danach kommt die Tabelle mit den Dateinamen. Das ist kein Beiwerk: Genau diese Verwechslung wuerde beim Aufraeumen die laufende VM treffen. Und manche Windows-Zeile braucht sogar B weiter — etwa die Regel, dass eine Laufwerkswurzel ihren abschliessenden Trenner behaelt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
51 KiB
KONZEPT — Rippy für Windows
Rippy v5. Ein eigenständiges Windows-Programm, gebaut mit Electron und TypeScript. Grüne Wiese: kein Docker-Code, kein Python, keine Container-Reste.
Stand: 30.08.2026 · Branch
worktree-windows-electron
0. Leseanleitung
| § | Frage |
|---|---|
| 1 | Warum wird neu gebaut statt repariert? |
| 2 | Was hat der Commander entschieden? |
| 3 | Was wurde gemessen, bevor entschieden wurde? |
| 4–5 | Wie ist das Programm aufgebaut, und was passiert, wenn eine Disc reingeht? |
| 6–9 | Features, Oberfläche, Setup, Werkzeuge |
| 10 | Was kommt aus dem alten Rippy mit? |
| 11 | Was aus main entfernt wird |
| 12–14 | Etappen, Risiken, was NICHT gebaut wird |
Was dieses Dokument NICHT tut: Es erfindet keine Messungen. Alles, was hier
als Zahl oder Verhalten steht, ist entweder in § 3 an dieser Maschine gemessen,
im alten Rippy belegt (SAVEPOINT.md, AGENTS.md) oder ausdrücklich als
Annahme markiert. Die Trennung ist wichtig, weil dieses Projekt schon
mehrfach teuer dafür bezahlt hat, dass jemand eine plausible Erklärung für eine
gemessene gehalten hat.
1. Warum neu gebaut wird
Die heutige Windows-Fassung ist kein Windows-Programm. Sie ist der Docker-Code in einer EXE:
RippySetup.exe (PyInstaller)
├─ docker/api/ → FastAPI, uvicorn auf 127.0.0.1:7788
├─ docker/worker/ → der Celery-Worker, nur ohne Celery
├─ docker/ui/dist/ → dieselbe React-Oberfläche wie im Browser
└─ pywebview → ein Fenster davor
Das Ergebnis steht im SAVEPOINT.md: elf Release-Kandidaten in drei Tagen.
Und die Funde sind fast alle vom selben Typ — Linux-Annahmen, die unter Windows
etwas anderes bedeuten:
| Fund | Was passierte |
|---|---|
timeout 4 ls -d <pfad> als Verzeichnisprüfung |
Unter Windows gibt es timeout.exe, aber sie kennt weder ls noch -d. Antwort war „weg" für jedes Verzeichnis — Rohdaten waren grundsätzlich unsichtbar. Dazu blitzten Konsolenfenster auf. |
shutil.which("makemkvcon") |
Findet unter Windows nie etwas — Programme liegen in Program Files, nicht im PATH. Die 4K-Schlüssel-Automatik lief deshalb nie an. |
os.path.isdir("/app") |
Rippy hielt sich für einen fremden Docker-Worker. Zweimal gefunden, an zwei Stellen. |
Routen /dev/{name} |
Das UI ruft mit G auf, gebaut war /dev/G. Auswerfen und Disc-Scan antworteten immer mit 404. |
F:\ wurde zu F: |
Unter Windows ist F: ohne Trenner der aktuelle Ordner auf F, nicht dessen Wurzel. 16,5 GB Rohschnitt unsichtbar; der Dialog bot nur „Neu rippen" an. |
makemkvcon überlebte den Elternprozess |
Windows räumt Kindprozesse nicht auf. Zwei Waisen hielten das Laufwerk fest. |
| Zwei Speicher für dieselben Ordner | Die Oberfläche schrieb outputDir in die Datenbank, der Betrieb las storage.medien aus einer Konfigurationsdatei, die niemand schrieb. Eingestellt E:\Rippy, angezeigt C:\Users\...\Videos\Rippy. |
Diese Liste ist nicht das Problem — sie ist das Symptom. Jeder einzelne Fund war eine Stelle, an der Code, der für einen Linux-Container geschrieben wurde, unter Windows etwas anderes bedeutet. Solange die Grundlage ein umgebogener Container ist, ist der nächste Fund dieser Sorte nur eine Frage der Zeit.
Die Entscheidung ist deshalb nicht „das ist schlecht gebaut", sondern: das ist am falschen Ort gebaut. Ein Windows-Programm fängt bei Windows an, nicht bei einem Container, dem man Windows beibringt.
2. Die Entscheidungen (Commander, 30.08.2026)
Acht Entscheide, alle am selben Tag. Die ersten vier legen die Architektur fest, die naechsten drei beantworten die Punkte, die das Konzept offengelassen hatte, und der achte steht bei der Sache, zu der er gehoert (Paragraph 11.1). Sie stehen hier, damit später nachvollziehbar ist, was Entscheidung war und was Vorschlag.
Entscheid 1 — Alles TypeScript/Node
Es gibt keinen Python-Anteil in Rippy für Windows. Kein Sidecar, keine mitgelieferte Laufzeit, keine IPC-Brücke zwischen zwei Sprachen. Eine Sprache, eine Werkzeugkette, ein Setup.
Was das kostet: Die rund 18.000 Zeilen Python werden nicht übernommen. Was übernommen wird, ist ihr Wissen — die Parser-Regeln, die gemessenen Fallen, die Kommandozeilen (§ 10). Das ist der teure Teil an ihnen, und der wandert vollständig mit.
Was das bringt: Der ganze Fehlertyp aus § 1 kann nicht mehr entstehen. Es gibt keinen Container-Pfad, den jemand vergessen könnte, weil es nie einen gab.
Entscheid 2 — Die Docker-Version bleibt unangetastet
Rippy auf der VM läuft weiter wie heute. Es wird nicht angefasst, nicht migriert, nicht mitgepflegt. Zwei getrennte Produkte, keine geteilten Module.
Begründung: Geteilte Module zwischen zwei Betriebssystemen sind genau die
Konstruktion, an der v1 gelitten hat — drei Dateien lagen byte-identisch
doppelt im Repo, und db.py schrieb es sogar in den Kopfkommentar: „Wer die
Struktur ändert, ändert BEIDE Dateien."
Entscheid 3 — Reiner Einzelplatz
Ein Rechner macht alles: erkennen, rippen, komprimieren, ablegen. Kein Server, keine Netz-Queue, keine Worker-Verwaltung, keine Pfad-Übersetzung zwischen Maschinen.
Was damit ersatzlos wegfällt: Celery, Redis, Postgres, die Worker-Tabelle,
worker_direct, die Lease-Mechanik über Netz, RIPPY_PATH_MAP, die
Zombie-Erkennung, die Mount-Wache, das Rate-Limit (es gibt keinen fremden
Client mehr), /worker-setup/*, die Encoder-Auswahl je Knoten.
Grob geschätzt sind das 40 % der heutigen Komplexität — und zwar der Teil, der die meisten Fehlerbilder erzeugt hat.
Was bleibt: Die Ablage darf trotzdem auf dem NAS liegen. Ein UNC-Pfad
(\\nas\medien) oder ein verbundenes Netzlaufwerk ist für Rippy nur ein Pfad.
Windows mountet, Rippy prüft — dieselbe Trennung wie in Entscheid 3 des
v2-Konzepts, nur ohne Container drumherum.
Entscheid 4 — Eigener Branch im selben Gitea-Repo
Ein Git-Worktree unter .claude/worktrees/windows-electron auf dem Branch
worktree-windows-electron. main bleibt unberührt und jederzeit deploybar.
Entscheid 5 — Kein Code-Signing-Zertifikat
„ist egal, brauchen wir nich"
Die EXE bleibt unsigniert. Folge: Beim ersten Start eines Downloads zeigt Windows den SmartScreen-Hinweis („Der Computer wurde geschützt"); über Weitere Informationen → Trotzdem ausführen geht es weiter. Das gehört in die Anleitung, nicht unter den Teppich.
Eine Folge, die dazugehört und in § 6.8 steht: Ohne Signatur kann
electron-updater ein heruntergeladenes Update nicht auf Echtheit prüfen.
Die Absicherung liegt damit vollständig beim Transportweg — Updates werden nur
über HTTPS geladen, nie über einfaches HTTP.
Entscheid 6 — Updates aus Gitea, auch für Fremde erreichbar
„Gerne das Gitea Release, mit Möglichkeit dass auch EXTERNE diese Updates fahren können"
Zwei Teile, und der zweite hat eine Bedingung, die Rippy nicht selbst lösen kann:
-
Rippys Seite — die Update-Adresse steht in der Konfiguration, vorbelegt mit dem Gitea des Commanders.
electron-updaterbraucht dafür nur einen statischen HTTPS-Ort mit zwei Dateien (latest.ymlund das Setup). Damit ist Rippy von der Frage unabhängig, wo dieser Ort liegt. -
Die Netz-Seite — ⚠️ Gitea läuft auf
192.168.178.153im Heimnetz. Von außen ist das nicht erreichbar. „Externe können Updates fahren" verlangt also einen von drei Wegen, und die Wahl gehört dem Commander:Weg Was zu tun ist Bewertung Gitea veröffentlichen Reverse-Proxy + DynDNS + TLS-Zertifikat Ein Dienst im Heimnetz wird öffentlich — die Angriffsfläche wächst. Nur mit Bedacht Öffentlicher Spiegel Der Bau schiebt das Release zusätzlich zu einem öffentlichen Ort (GitHub-Release, Objektspeicher, gemieteter Webspace) Empfehlung. Gitea bleibt privat, nur die fertigen Dateien liegen draußen Jeder trägt seine eigene Quelle ein Nichts — die Konfiguration kann es schon Für einzelne Nutzer mit eigenem Server. Skaliert nicht Rippy wird für alle drei gebaut: eine Adresse in der Konfiguration, sonst nichts. Die Entscheidung kann später fallen, ohne das Programm anzufassen.
Entscheid 7 — Der alte Windows-Weg wird entfernt, auch aus main
„Nein — direkt weg, auch aus dem Original Repo. Das neue Standalone Windows Rippy wird ein komplett neues Produkt und kein Aufbau auf die Docker-Architektur."
Die PyInstaller-Fassung bleibt nicht parallel installierbar, und ihr Code verlässt das Repo. Das ist die schärfere Fassung von Entscheid 2: Nicht nur werden die beiden Produkte nicht verwandt sein — der Zwitter dazwischen wird abgeräumt.
Das ist kein Widerspruch zu Entscheid 2. „Docker bleibt unangetastet" meint die Docker-Funktion; der Windows-Standalone-Zweig ist gerade nicht Docker, sondern der Fremdkörper darin. Was genau entfernt wird, steht in § 11 — mit einer Unterscheidung, die beim Aufräumen entscheidend ist.
3. Was gemessen wurde, bevor entschieden wurde
Electron bedeutet: Die Arbeit macht Node, nicht Python. Damit hängt das ganze Konzept an einer Frage, die vorher niemand geprüft hat:
Kann Node überhaupt alles, was Rippy am Laufwerk braucht?
Wäre die Antwort nein, wäre das Konzept wertlos. Also gemessen — am 30.08.2026, auf diesem Rechner, am echten Laufwerk.
3.1 Die Werkzeuglage
Node v24.19.0
npm 11.17.0
Electron 44.0.0 (Chromium 152.0.7977.54 · Node 24.18.1)
WebView2 151.0.4129.107
Laufwerk G: HL-DT-ST BD-RE BU40N USB Device (Medium eingelegt)
3.2 Win32 aus Node — die Laufwerks-Steuerung
koffi 3.1.6 installiert, dieselben Steuercodes wie in
src/rippy/drives/win_ioctl.py (die dort aus dem CTL_CODE-Makro hergeleitet
sind, nicht abgeschrieben). Nur lesende Aufrufe, nichts ausgeworfen:
1. GetLogicalDrives + GetDriveTypeW -> optische Laufwerke: [ 'G' ]
2. CreateFileW \\.\G: (Zugriff 0) -> offen
CreateFileW \\.\G: (GENERIC_READ) -> offen
3. IOCTL_STORAGE_QUERY_PROPERTY -> Hersteller: HL-DT-ST | Modell: BD-RE BU40N
| Rev: 1.03 | Serial: 0025114C0149
4. IOCTL_STORAGE_CHECK_VERIFY2 -> Medium eingelegt
5. IOCTL_CDROM_DISK_TYPE -> Win32-Fehler 50
6. IOCTL_DISK_GET_LENGTH_INFO -> 33.759.690.752 Bytes (33,76 GB) => Blu-ray
Punkt 5 ist kein Fehlschlag, sondern eine Bestätigung. Fehler 50 ist
ERROR_NOT_SUPPORTED — genau das, was auch der Python-Treiber an diesem
Laufwerk sieht (SAVEPOINT.md, rc11). Node verhält sich identisch. Und die
Lehre daraus steht schon im alten Code: Die Disc-Einordnung darf sich nicht
auf IOCTL_CDROM_DISK_TYPE verlassen — die Größe ist der verlässliche Weg.
3.3 Die Prozess-Leine — überlebt makemkvcon einen Absturz?
Der Befund aus rc10: Windows räumt Kindprozesse nicht auf. Ein hart beendeter
Rippy hinterlässt ein makemkvcon, das das Laufwerk festhält. Die Lösung dort
war eine Windows-Arbeitsgruppe (Job Object) mit
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.
In Node nachgestellt — Job Object gesetzt, Kind gestartet, Eltern mit
taskkill /F ohne /T abgeschossen (genau das, was bei einem Absturz und
beim Drüber-Installieren passiert):
1. CreateJobObjectW -> Arbeitsgruppe angelegt
2. SetInformationJobObject -> KILL_ON_JOB_CLOSE gesetzt
3. AssignProcessToJobObject -> dieser Prozess hängt in der Gruppe
4. Kindprozess gestartet, PID 16040
vor dem Abschuss: Eltern lebt: True Kind lebt: True
taskkill /F /PID 29488 -> ERFOLGREICH
danach: Eltern lebt: False Kind lebt: False
3.4 Datenbank ohne native Abhängigkeit
node:sqlite eingebaut -> geht
Node 24 bringt SQLite mit (node:sqlite, DatabaseSync). Keine
better-sqlite3-Kompilierung, kein node-gyp, kein Visual-Studio-Build in der
Bau-Kette.
⚠️ Ungeprüft: Electron kompiliert sein Node mit eigenen Flags. Ob
node:sqlitein Electron 44 vorhanden ist, ist an dieser Stelle nicht gemessen — nur in Node 24.19.0 selbst. Das ist der erste Handgriff in Etappe W-0. Rückfallebene:better-sqlite3(bewährt, aber nativ und damit eine Kompilierung in der Bau-Kette).
3.5 Ein Nebenbefund für die Bau-Kette
npm 11 blockiert Install-Skripte fremder Pakete standardmäßig:
npm warn allow-scripts koffi@3.1.6 (install: node ./cnoke.cjs -P . --prebuild --release)
koffi lädt trotzdem — es bringt vorgebaute Binärdateien mit. Aber die
Warnung gehört in die Bau-Anleitung, sonst sucht jemand eines Tages an der
falschen Stelle.
4. Aufbau
4.1 Drei Teile, drei Prozesse
┌──────────────────────────────────────────────────────────────┐
│ Rippy.exe — Electron Main-Prozess │
│ ├─ Tray-Symbol, Fensterverwaltung, Autostart, Selbst-Update │
│ └─ hält die Prozess-Leine (§ 3.3) — ALLES stirbt mit ihm │
└───────────┬─────────────────────────────┬────────────────────┘
│ IPC │ MessagePort
┌───────────▼──────────────┐ ┌──────────▼───────────────────────┐
│ Fenster (Renderer) │ │ Kern (utilityProcess) │
│ React + Tailwind │◄──┤ die GANZE Arbeit │
│ zeigt an, sonst nichts │ │ ├─ Laufwerkswache (koffi/Win32) │
│ │ │ ├─ Ablauf-Steuerung │
│ kein Node-Zugriff │ │ ├─ Auftragstabelle (SQLite) │
│ (contextIsolation) │ │ └─ Werkzeuge als Kindprozesse: │
│ │ │ makemkvcon · HandBrakeCLI │
└──────────────────────────┘ └──────────────────────────────────┘
Warum drei und nicht einer:
- Ein Rip dauert 30–90 Minuten. Läuft er im Main-Prozess, friert die Oberfläche ein — Electrons eigene Dokumentation sagt das ausdrücklich.
- Der Kern darf abstürzen, ohne das Fenster mitzureißen. Dann steht dort „Der Kern ist abgestürzt, ich starte ihn neu" statt eines toten Fensters.
- Das Fenster darf zugehen, ohne den Rip zu beenden. Rippy lebt dann im Tray weiter — genau wie heute, nur ohne den Umweg über einen HTTP-Server.
Warum utilityProcess und nicht child_process.fork: Electrons eigene
Empfehlung. utilityProcess kann einen MessagePort direkt zum Renderer
aufbauen — der Fortschritt eines Rips geht damit ohne Umweg über den
Main-Prozess ins Fenster.
Was es NICHT gibt: keinen HTTP-Server, keinen Port, kein localhost:7788,
keine REST-API, kein SSE. Fenster und Kern reden über Electrons IPC. Ein
lokaler Webserver in einer Einzelplatz-Anwendung ist eine offene Tür ohne
Gegenwert — und er war der Grund für das Rate-Limit, den Proxy-Kummer und die
Polling-Last im alten Rippy.
4.2 Ordner
rippy-windows/
├── package.json
├── electron.vite.config.ts
├── src/
│ ├── haupt/ Electron Main
│ │ ├── index.ts Start, Einzelinstanz-Sperre, Leine setzen
│ │ ├── fenster.ts Fenster anlegen, Zustand merken
│ │ ├── tray.ts Symbol + Kontextmenü
│ │ ├── autostart.ts HKCU\...\Run
│ │ └── update.ts electron-updater
│ │
│ ├── kern/ utilityProcess — die Arbeit
│ │ ├── laufwerk/
│ │ │ ├── win32.ts DER EINZIGE ORT MIT koffi
│ │ │ ├── wache.ts Einwurf/Auswurf erkennen
│ │ │ └── disc.ts Typ, Label, Größe, TOC
│ │ ├── metadaten/
│ │ │ ├── tmdb.ts tvdb.ts omdb.ts musicbrainz.ts
│ │ │ ├── discmerkmale.ts Label + Laufzeiten + BDMV-Titel
│ │ │ └── zuordnung.ts Treffer + Sicherheitsgrad
│ │ ├── rip/
│ │ │ ├── makemkv.ts Kommandobau + Aufruf
│ │ │ ├── parser.ts TINFO/SINFO/PRGV/MSG (rein, testbar)
│ │ │ ├── audiocd.ts Roh-Sektoren + FLAC
│ │ │ └── iso.ts Datendiscs 1:1 sichern
│ │ ├── komprimieren/
│ │ │ ├── handbrake.ts Kommandobau + Aufruf + Fortschritt
│ │ │ ├── encoder.ts GEMESSEN, nicht behauptet
│ │ │ └── presets.ts
│ │ ├── ablage/
│ │ │ ├── struktur.ts Jellyfin/Emby/Kodi/Plex
│ │ │ ├── nfo.ts poster.ts medienserver.ts
│ │ ├── ablauf/
│ │ │ ├── pipeline.ts die Verkettung — NUR HIER
│ │ │ ├── zustand.ts Zustandsmaschine
│ │ │ └── auftraege.ts Warteschlange, Slots
│ │ ├── werkzeuge/
│ │ │ ├── katalog.ts wo liegt makemkvcon/HandBrakeCLI/flac
│ │ │ ├── beschaffen.ts holen, prüfen, einrichten
│ │ │ └── leine.ts Job Object (§ 3.3)
│ │ └── speicher/
│ │ ├── db.ts SQLite
│ │ ├── einstellungen.ts EINE Quelle (§ 6.7)
│ │ └── bibliothek.ts
│ │
│ ├── gemeinsam/ Typen + Ereignis-Schema — Fenster UND Kern
│ └── fenster/ React
│
├── bau/ electron-builder, NSIS-Skript, Icon
└── test/ Vitest
4.3 Sechs Regeln, die den Aufbau tragen
Jede ist aus einem bezahlten Fehler abgeleitet. Sie sind mechanisch prüfbar und bekommen je einen Wächter-Test.
R1 — Win32 lebt nur in laufwerk/win32.ts.
Kein koffi-Import irgendwo sonst. Ein Wächter-Test greift bei jedem anderen
Fundort. (Grund: In v1 rief main.py eject() direkt auf — deshalb brauchte
der API-Container Geräte-Zugriff und SYS_ADMIN.)
R2 — Ein Fehlschlag löscht nie einen Zustand.
Kein catch { return [] }. Wer nichts Neues weiß, behält, was er wusste.
(Grund: Fünfmal catch(() => []) im alten UI — jeder verpasste Abruf hieß
„es gibt keine Jobs", die Liste leerte sich im Sekundentakt. Der Commander
meldete es als „wird oft neu geladen".)
R3 — Auswerfen heißt: entriegeln, auswerfen, nachsehen.
In dieser Reihenfolge. Kein Rückgabewert gilt als Beweis. (Grund: CDROMEJECT
quittiert auf einem verriegelten Laufwerk Erfolg und tut nichts. MakeMKV
verriegelt die Tür während des Rips.)
R4 — Jede Hintergrundschleife meldet ihren Fehler.
Kein stilles catch {}. (Grund: Ein except Exception: pass in einer
Vorrats-Schleife hat einmal eine Stunde gekostet.)
R5 — Externe Schnittstellen werden gemessen, nicht erinnert.
Jeder Kommandozeilen-Schalter, jeder IOCTL-Code trägt im Kommentar, wo er
herkommt. (Grund: --audio-codec gibt es bei HandBrakeCLI nicht — es heißt
-E/--aencoder. Ein unbekannter Schalter ist für HandBrake kein Fehler:
Rückgabewert 0. Das kostete einen fertigen 16,5-GB-Rip, und ein Test hatte den
Fehler festgeschrieben statt ihn zu finden.)
R6 — Alles läuft an der Leine. Jeder Werkzeugaufruf hängt in der Arbeitsgruppe aus § 3.3. Ausgenommen ist nur das Aufräum-Skript der Deinstallation — es muss Rippy überleben.
5. Der Ablauf — was passiert, wenn eine Disc reingeht
Der rote Faden des Commanders: so viel Arbeit abnehmen wie möglich.
1. Disc rein
│ WM_DEVICECHANGE / DBT_DEVICEARRIVAL (Ereignis, kein Poll)
│ Rückfallebene: 3-Sekunden-Takt, falls die Nachricht ausbleibt
▼
2. Was ist das?
│ Größe (33,76 GB → Blu-ray) · Audio-TOC? · Dateisystem lesbar?
│ → Film / Serie / Musik / Daten
▼
3. Was ist da drauf? ← DER SCHRITT, DER HEUTE ZU DÜNN IST
│ Disc-Label · Titel-Laufzeiten · BDMV-Titel · DVD-IFO · CD-DiscID
│ → TMDb / TVDb / OMDb / MusicBrainz
│ → Treffer mit SICHERHEITSGRAD
▼
4. Sicher genug?
│ ja → sofort losrippen, nur Bescheid sagen (Zero-Click)
│ nein → fragen: Fenster hoch, Vorschläge zur Wahl
▼
5. Rippen makemkvcon, verlustfrei, Fortschritt aus PRGV
▼
6. Komprimieren HandBrakeCLI, Encoder GEMESSEN, Preset je Disc-Typ
▼
7. Ablegen Zielstruktur · NFO · Poster/Fanart
▼
8. Melden Medienserver anstoßen · Benachrichtigung · Auswerfen
▼
9. Merken Bibliothek fortschreiben — beim nächsten Mal erkannt
Was an Schritt 3 neu ist. Heute nimmt Rippy im Wesentlichen das Disc-Label und die längste Laufzeit. Das reicht bei „PIRATES_OF_THE_CARIBBEAN", aber nicht bei „LOGICAL_VOLUME_ID" — und dann fragt Rippy, obwohl die Antwort auf der Disc steht. Vier Quellen kommen dazu:
| Quelle | Wo | Was sie liefert |
|---|---|---|
| BDMV-Metadaten | BDMV/META/DL/bdmt_*.xml auf der Blu-ray |
Der vom Studio hinterlegte Disc-Titel, oft mit Sprachvarianten. Deutlich besser als das Volume-Label. |
| Titel-Struktur | makemkvcon info |
Die Anzahl und Länge der Titel ist ein Fingerabdruck: 1 langer + viele kurze = Film; 6–13 gleich lange = Serienstaffel. |
| DVD-Struktur | VIDEO_TS, IFO-Dateien |
Kapitelzahl und Titelsatz-Aufbau |
| CD-DiscID | Audio-TOC | Bereits gebaut und bewiesen (rc8): Spurlage → MusicBrainz → Album, Interpret, Jahr, jeder Titel. |
Dazu ein Sicherheitsgrad, der ehrlich ist. Rippy sagt nicht „das ist Akira", sondern „das ist sehr wahrscheinlich Akira (1988)" — und fragt nur, wenn es das nicht sagen kann. Die Schwelle ist einstellbar; wer will, lässt Rippy immer fragen, und wer will, lässt es immer durchlaufen.
Und wenn Rippy sich irrt: Der Titel lässt sich nachträglich ändern, und die Ablage wandert mit. Das ist der Unterschied zwischen „falsch geraten" und „falsch abgelegt".
6. Die Features
6.1 Automatische Erkennung (§ 5, Schritt 2–4)
Siehe oben. Kernsatz: Rippy fragt nur, wenn es wirklich nicht weiß.
6.2 Rippen
makemkvcon im Robot-Modus (--robot --messages=-stdout --progress=-same),
verlustfrei. Der Parser (TINFO/SINFO/PRGV/MSG) wandert aus dem Python-Code
nach TypeScript — er ist reine Textverarbeitung und damit vollständig
testbar, ohne Laufwerk.
Was aus dem alten Rippy zwingend mitkommt:
- Lesefehler heißen Lesefehler. MakeMKV kann 1 von 2 Titeln sichern und sich trotzdem mit 0 beenden. Rippy warnt nach dem Rip — auch und gerade dann, wenn er als Erfolg endete — und nennt die MSG-Nummer: MakeMKVs Texte sind übersetzt, die Nummern nicht.
- Erst nachsehen, dann rippen. Liegt keine Disc drin, sagt Rippy das in einem Satz, statt zwei Minuten in makemkvcon zu laufen und mit Code 11 zu enden. Aber: Wenn das Nachsehen selbst scheitert, wird trotzdem gerippt — „ich weiß es nicht" darf nie zu „es geht nicht" werden.
- Die Ausgabe binär lesen. makemkvcon mischt Kodierungen; ein
üim Pfad hat die Kompression einmal getötet (UnicodeDecodeErrorauf Byte 0x81).
6.3 Audio-CDs
Der Weg aus rc8, bewiesen: Roh-Sektoren über Win32 lesen (eine Audio-CD hat
kein Dateisystem — die Track01.cda sind 44-Byte-Platzhalter), dann durch
flac.exe. Dazu MusicBrainz über die DiscID.
Zwei Fallen, beide gemessen und beide dokumentiert: Die DiscID rechnet mit den 150 Frames Vorlauf, das Lesen ohne. Und die Leseadresse zählt in 2048er-Einheiten, obwohl ein Audio-Sektor 2352 Bytes hat.
6.4 ISO-Backup für Datendiscs (neu)
Die einzige echte Lücke gegenüber ARM. Wird eine Disc weder als Film noch als
Musik erkannt, wird sie 1:1 gesichert statt abgelehnt: sequenziell aus
\\.\G: lesen, Länge aus IOCTL_DISK_GET_LENGTH_INFO (in § 3.2 gemessen:
liefert exakte Bytes). Kein Fremdwerkzeug nötig.
6.5 Mehrere Laufwerke gleichzeitig (neu)
Laufwerke sind eigenständige Objekte mit stabiler Kennung (Seriennummer, nicht
Buchstabe — 0025114C0149 in § 3.2 gemessen). Ein Rip-Auftrag belegt genau
ein Laufwerk; die Zahl gleichzeitiger Rips und Kompressionen ist einstellbar.
⚠️ Annahme, zu messen bevor sie festgeschrieben wird: Mehrere
makemkvcon-Prozesse teilen sich ein Datenverzeichnis (_private_data.tar,settings.conf). Der Entwurf sieht deshalb vor: Rip-Phase parallel, Schlüssel-Phase serialisiert. Das ist aus der Aktenlage abgeleitet, nicht gemessen — und gehört an zwei Laufwerken geprüft, bevor die Grenze im Code steht.
6.6 Bibliothek (neu)
Eine Ansicht über alles Gerippte: Cover, Größe, Datum, Ablageort, Dauer des Vorgangs. Und der praktische Teil: Rippy erkennt beim Einlegen, wenn eine Disc schon einmal durchgelaufen ist (über die Disc-Merkmale aus § 5) und fragt nach, statt stumm zu doppeln.
6.7 Arbeitsverzeichnis und Ablage — eine Quelle
Der Fund aus rc11: Die Oberfläche schrieb in die Datenbank, der Betrieb las
aus einer Konfigurationsdatei, die niemand schrieb. Eingestellt E:\Rippy,
angezeigt C:\Users\...\Videos\Rippy.
In v5 gibt es genau einen Speicher für Einstellungen (speicher/einstellungen.ts,
SQLite). Ein Wächter-Test prüft mechanisch, dass kein zweiter Ort entsteht.
Dazu die Pfad-Regeln aus rc11, als reine Funktionen mit Tests:
- Eine Laufwerkswurzel behält ihren Trenner (
F:\, nichtF:) - UNC-Wurzeln bleiben absolut
- Verzeichnisprüfungen sind windows-nativ — kein
timeout ls -d - Pro Rip darf ein anderes Arbeitsverzeichnis gewählt werden, und gesucht wird später unter der Wahl des Jobs, nicht unter der heutigen Einstellung
6.8 Selbst-Update (neu)
electron-updater gegen die Releases im Gitea (Entscheid 6). Rippy prüft beim
Start und danach täglich, lädt im Hintergrund und installiert beim nächsten
Start — nie mitten in einem Rip.
Die Quelle steht in der Konfiguration und ist vorbelegt. Ein nicht erreichbarer Update-Server ist kein Fehler, sondern eine Zeile im Protokoll.
Vier Regeln, die zum Entscheid gehören:
- Nur HTTPS. Ohne Code-Signing (Entscheid 5) kann
electron-updaterein heruntergeladenes Update nicht auf Echtheit prüfen — die Absicherung liegt damit ganz beim Transportweg. Einehttp://-Update-Adresse wird abgelehnt, nicht stillschweigend akzeptiert. - Nie während eines Rips. Weder herunterladen noch installieren. Ein Neustart mitten in einem 90-Minuten-Rip wäre der teuerste Fehler, den ein Update-Mechanismus machen kann.
- Ein Fehlschlag ist sichtbar, aber nicht laut. Die Prüfung darf still scheitern (WLAN weg, Server aus) — aber der Zeitpunkt der letzten erfolgreichen Prüfung steht im Über-Dialog. Wer nie prüft, weiß sonst nicht, dass er nie prüft.
- Die Version, die läuft, ist ablesbar. Im Fenster und im Protokollkopf. Eine Fehlermeldung ohne Versionsnummer ist bei einem sich selbst aktualisierenden Programm die halbe Miete verloren.
6.9 Erst-Einrichtung (neu gedacht)
Der Befund des Commanders zur heutigen Fassung: „Dann hätte ich beim Setup auch erwartet, dass ein echtes Setup passiert — wo will ich das hinspeichern, ein Pre-Requirement-Check usw. Da kommt gar nichts, Rippy geht einfach auf."
Der Assistent läuft nach der Installation, im Programm selbst, in fünf Schritten:
| Schritt | Was passiert |
|---|---|
| 1 Willkommen | Was Rippy tut, in vier Sätzen |
| 2 Prüfung | Laufwerke · Werkzeuge · Plattenplatz · Internet · WebView2 — jeder Befund sagt, was zu tun ist |
| 3 Werkzeuge | Was fehlt, wird geholt (§ 9) — mit Fortschritt, nicht mit einem eingefrorenen Fenster |
| 4 Ordner | Ablage und Arbeitsverzeichnis, mit echten Windows-Ordnerdialogen und Platzanzeige |
| 5 Automatik | Wie viel soll Rippy allein entscheiden? Je Disc-Typ einstellbar. |
Zwei Regeln, die aus dem alten Setup übernommen werden:
- Nur ein Fehler blockiert. Eine Warnung, die den Knopf sperrt, ist Bevormundung; ein Fehler, der nur warnt, ist eine Falle. Kein optisches Laufwerk ist eine Warnung — eine reine Komprimier-Maschine ist ein vorgesehener Betriebsfall.
- Ein Setup meldet nie Erfolg, während ein Pflichtwerkzeug fehlt. Der Bestand wird VOR und NACH dem Versuch gelesen; berichtet wird, was danach wirklich da ist.
6.10 Was unverändert erhalten bleibt
Alles, was der Commander heute benutzt:
Kompression je Disc-Typ abwählbar (4K verlustfrei durchreichen) · Preset-Wahl je Typ · Sprachwahl für Ton und Untertitel vor dem Rip · Original behalten · Vollautomatik · Nur-Hauptfeature · automatischer Auswurf · Medienserver-Refresh (Jellyfin/Emby/Plex/Kodi) · NFO + Poster + Fanart · Serien-Staffelablage mit Episoden-Zuordnung per Laufzeitabgleich (nur bei eindeutiger Zuordnung wird umbenannt) · Webhook-Benachrichtigungen (Discord/Slack/ntfy/generisch) · Live-Log · Job-Detailansicht · Wiederholen ab Rip oder ab Kompression · 4K-Schlüsselkette in drei Stufen · Restzeit-Schätzung.
7. Die Oberfläche
Entscheid: Neu bauen, Look behalten.
Wiedererkennbar bleibt die Design-Sprache — dunkel/hell, die Kachel-Anordnung, das Kino-Banner, die Farbwelt. Neu ist, dass die Oberfläche eine Einzelplatz-Anwendung bedient statt eines Docker-Clusters.
Was verschwindet: Worker-Verwaltung · Container-Platte · „Prüfen:
docker compose ps" · Speicherziele-Einhängen · Pfad-Map · Worker-Setup-Paket ·
Encoder-Auswahl je Knoten · alles, was einen zweiten Rechner voraussetzt.
Was dazukommt:
- Echte Windows-Ordnerdialoge statt eines nachgebauten Dateibrowsers im Web. Das ist ein spürbarer Unterschied im Alltag: Der Nutzer sieht seine Netzlaufwerke, seine Schnellzugriffe, seine gewohnte Oberfläche.
- Tray-Symbol mit Zustand — auf einen Blick: läuft ein Rip, wie weit, wie lange noch. Rechtsklick: Öffnen, Pause, Beenden.
- Windows-Benachrichtigungen (echte Toasts, nicht Browser-Popups), mit Klick direkt in den Job.
- Fortschritt in der Taskleiste — Windows kann einen Fortschrittsbalken über dem Symbol zeigen. Bei einem 90-Minuten-Rip ist das genau die Information, die man will, ohne das Fenster zu öffnen.
- Die Bibliothek als eigene Ansicht (§ 6.6).
Was die Oberfläche NIE tut: Eine Liste auf leer setzen, weil eine Nachricht ausblieb (R2). Bei einem Aussetzer bleibt der letzte Stand stehen, und ein Banner sagt, dass gerade nichts Neues kommt.
8. Setup, Autostart, Deinstallation
Entscheid: pro Benutzer, ohne Administratorrechte, Windows 10 (ab 1809) und 11, x64.
| Installer | electron-builder → NSIS, ein RippySetup.exe |
| Ziel | %LOCALAPPDATA%\Programs\Rippy — kein UAC-Dialog |
| Autostart | HKCU\Software\Microsoft\Windows\CurrentVersion\Run |
| Update | electron-updater, NSIS-Ziel (§ 6.8) |
| Deinstallation | Über die Windows-Programmliste, räumt wirklich auf |
Warum kein Windows-Dienst: Ein Dienst startet vor der Anmeldung — klingt besser, kostet aber bei jeder Installation und jedem Update eine Administrator-Abfrage, und er kann kein Tray-Symbol zeigen (keine Benutzersitzung). Für einen Rechner, an dem jemand sitzt und Discs einlegt, ist der Autostart-Eintrag der richtige Weg.
Drei Dinge, die aus den alten Fehlern übernommen werden:
- Drüber-Installieren funktioniert. Rippy läuft fast immer (Autostart) —
der Installer beendet die laufende Fassung, bevor er kopiert. Sonst landet
die neue Version als
Rippy.exe.neudaneben. (Genau das ist passiert.) - Die Deinstallation räumt die WebView-Reste weg. Beim letzten Mal blieben 148 Dateien liegen, weil die Renderer-Hilfsprozesse den Zwischenspeicher offen hielten — und der Deinstallierer meldete trotzdem „Rippy wurde entfernt."
- Das Aufräum-Skript darf keine Laufwerkswurzel löschen. Wenn der Installationsort aus der Registry eine Wurzel wäre, löschte die Deinstallation das Laufwerk. Nicht beobachtet — aber nicht wiedergutzumachen.
SmartScreen — entschieden (Entscheid 5): kein Zertifikat. Die unsignierte EXE bekommt beim ersten Start eine Warnung („Der Computer wurde geschützt"); über Weitere Informationen → Trotzdem ausführen geht es weiter. Das gehört in die Anleitung, nicht unter den Teppich — und die Anleitung sagt auch, woran man erkennt, dass die Datei aus der richtigen Quelle stammt (Größe und Prüfsumme stehen beim Release).
Die Folge für den Update-Weg steht in § 6.8: Ohne Signatur ist der Transportweg die einzige Absicherung, also nur HTTPS.
9. Die Werkzeuge
Der Entscheid vom 28.08.2026 gilt unverändert: „handbrake und makemkv MÜSSEN mitgeliefert werden oder während des Setups separat installiert werden." Die Wege unterscheiden sich, und der Grund ist die Lizenz, nicht die Bequemlichkeit.
| Weg | Warum | |
|---|---|---|
| HandBrakeCLI | mitgeliefert (~35 MB) | GPL-2 erlaubt die Weitergabe, solange Lizenztext und Quellverweis dabei sind. Damit komprimiert Rippy auch ohne Internet. |
| FLAC | mitgeliefert (~2 MB) | Xiph-Lizenz (BSD-artig), Weitergabe erlaubt. ⚠️ flac.exe braucht libFLAC.dll daneben — mit nur der EXE endet jeder Aufruf ohne eine Zeile Ausgabe. |
| MakeMKV | beim Einrichten geholt | Proprietär — die Lizenz erlaubt Dritten keine Weitergabe. Rippy lädt die offizielle Datei vom Hersteller und startet dessen Installer. |
Die Bezugskette für MakeMKV (aus dem 28.08.-Entscheid, unverändert): eigene Quelle → Hersteller-Seite → Hersteller-Forum → Internet Archive. Mit zwei Feinheiten, beide gemessen: Die höchste Versionsnummer gewinnt, nicht die erste (das Archiv meldet sonst 1.18.2 statt 1.18.4), und jeder Versuch bekommt eine knappe Zeitgrenze (8 s), weil das Forum in zwei von drei Abrufen ausfiel.
MakeMKV signiert seinen Installer nicht (NotSigned, an der echten Datei
gemessen) — geprüft wird deshalb die Versions-Ressource
(CompanyName: GuinpinSoft inc). Das ersetzt keine Signatur, fängt aber ab,
was hier wirklich droht: eine Fehlerseite mit .exe-Namen, ein abgebrochener
Download, eine falsche Fassung.
9.1 Der Beta-Key — ein Termin, kein Detail
MakeMKVs freier Beta-Key ist bis Ende September 2026 gültig. Die Kaufseite für die Dauerlizenz ist seit Mai 2026 defekt.
Das trifft Rippy in etwa vier Wochen, und ohne gültigen Key geht keine Blu-ray und keine 4K-Disc mehr auf (DVDs laufen weiter).
Rippy v5 geht damit so um:
- Der Key wird automatisch geholt (wie heute) — aus dem Forum-Thread, in dem der Hersteller ihn veröffentlicht.
- Rippy zeigt das Ablaufdatum im Dashboard und warnt sieben Tage vorher — statt dass ein Rip mitten in der Nacht scheitert und niemand weiß, warum.
- Ein abgelaufener Key ist eine klare Meldung, kein rätselhafter MakeMKV-Fehlercode.
- Ein eingetragener Dauerlizenz-Schlüssel schlägt alles. Wer eine Lizenz hat, trägt sie ein und ist raus aus dem Thema.
10. Was aus dem alten Rippy mitkommt
Kein Code. Aber jede teuer bezahlte Erkenntnis.
Das ist der Kern des Grüne-Wiese-Ansatzes: Der Python-Code wird nicht portiert, aber er ist die beste verfügbare Dokumentation darüber, wie sich MakeMKV, HandBrake und Windows-Laufwerke wirklich verhalten. Diese Tabelle ist die Arbeitsliste für den Neubau.
| Herkunft | Was übernommen wird | Wohin |
|---|---|---|
ripping.py |
TINFO/SINFO/PRGV/MSG-Parser, Kommandobau, laengster_titel, episoden_titel, Sprach-Zusammenfassung |
rip/parser.ts, rip/makemkv.ts |
win_ioctl.py |
Die hergeleiteten Steuercodes samt Herleitung — in § 3.2 aus Node bestätigt | laufwerk/win32.ts |
windows.py, winlauf.py |
Zugriffsgründe je Fehlernummer, CREATE_NO_WINDOW, Standby verhindern, die Prozess-Leine |
laufwerk/, werkzeuge/leine.ts |
caps.py |
Encoder messen statt behaupten (HandBrakeCLI --help auswerten) |
komprimieren/encoder.ts |
handbrake_aufruf.py |
--aencoder (nicht --audio-codec), Container aus dem Preset erzwingen, letzte 12 Zeilen puffern, unknown option-Erkennung |
komprimieren/handbrake.ts |
medien.py |
Zielstruktur, NFO-Schema, Episoden-Zuordnung per Laufzeit, Medienserver-Refresh | ablage/ |
prescan.py, clients/* |
TMDb/TVDb/OMDb/MusicBrainz/Jikan-Abfragen, Zwischenspeicher, Confidence | metadaten/ |
pfade.py |
Laufwerkswurzeln, UNC, naechster_vorhandener ohne Endlosschleife |
speicher/pfade.ts |
musicbrainz_cd.py, audio_cd.py |
DiscID-Rechnung (mit/ohne 150 Frames), 2048-vs-2352-Falle | rip/audiocd.ts |
presets.py, eta.py, phasen.py |
Preset-Zuordnung je Disc-Typ, Restzeit, Phasenmodell | komprimieren/, ablauf/ |
beschaffen.py, katalog.py |
Suchreihenfolge für Werkzeuge, Registry-Auswertung, Ausweichquellen | werkzeuge/ |
AGENTS.md |
Die sechs Regeln aus § 4.3 | Wächter-Tests |
Die Tests wandern sinngemäß mit. Von den 977 heutigen Tests ist der größte Teil reine Textverarbeitung (Parser, Pfade, Kommandobau) — die Testfälle gelten unverändert, nur die Sprache wechselt. Das ist kein Nebeneffekt, sondern die Absicherung: Ein neu geschriebener Parser, der dieselben Testfälle besteht wie der alte, hat dieselben Fallen abgedeckt.
11. Was aus main entfernt wird
Entscheid 7. Die Arbeit gehört in den main-Branch, nicht hierher — dieser
Abschnitt ist die Arbeitsliste dafür, damit sie nicht aus dem Gedächtnis
gemacht wird.
11.1 Der Windows-Anteil in main sind DREI Dinge, nicht eins
Diese Unterscheidung ist der ganze Abschnitt. Wer sie überspringt, löscht entweder zu wenig oder reißt die Docker-Version mit.
Zuerst in Klartext, ohne Dateinamen:
A ist Rippy. B ist ein Handlanger für die VM. C sind Notizzettel, die wegen A eingeklebt wurden.
A — „Rippy" auf einem Windows-PC. Das Programm, das man heute kennt:
RippySetup.exe, Doppelklick, Symbol in der Taskleiste, ein Fenster geht auf.
Disc rein, Rippy erkennt sie, rippt, komprimiert, legt ab. Ein vollständiges
Rippy, das alles allein macht. Genau das wird durch v5 ersetzt.
B — „Rippy Worker" auf einem Hilfsrechner. Ein anderes Programm,
RippyWorkerSetup.exe. Es rippt nichts und hat keine Bedienoberfläche.
Beim Installieren fragt es drei Dinge: IP der Rippy-VM? Name dieses Helfers?
Wie viele Kerne? Danach wartet es. Will die Docker-Rippy auf der VM einen
Film komprimieren und ist selbst zu langsam, schickt sie die Arbeit dorthin.
VM (Docker-Rippy) Ein Windows-PC
├─ Disc einlesen
├─ rippen
└─ komprimieren? zu langsam ──────► B: „Rippy Worker"
komprimiert und
Ergebnis ◄───────────────────── schickt zurück
B läuft nur zufällig auf Windows — es gehört zur Docker-Welt.
C — Notizzettel im Docker-Code. Keine eigenen Dateien, sondern verstreute Stellen mitten in Dateien, die Docker jeden Tag benutzt, wo jemand schrieb: „falls wir gerade auf Windows laufen, mach es anders". Eingebaut wurden sie, damit A funktioniert.
Der Unterschied zwischen A und C ist nicht der Inhalt, sondern der Ort:
| Bild | Aufräumen heißt | |
|---|---|---|
| A | Ganze Ordner, auf denen „Windows" steht. Docker schlägt sie nie auf. | Ordner wegwerfen. Ganze Dateien löschen, fertig. |
| C | Einzelne Seiten mit Windows-Notizen, die in Ordnern liegen, die Docker täglich benutzt. | Seiten einzeln durchgehen. Die Datei bleibt, ein paar Zeilen gehen — und bei jeder Zeile ist zu prüfen, ob wirklich nur A sie brauchte. |
Deshalb ist C der heikle Teil: Erwischt man eine Zeile, die Docker doch
braucht, geht auf der VM etwas kaputt. Und manche Windows-Zeile braucht sogar
B weiter — etwa die Regel, dass eine Laufwerkswurzel F:\ mit Trenner
geschrieben werden muss (§ 1). Der Handlanger läuft ja auf Windows.
In Dateien ausgedrückt:
| Was es ist | Schicksal | |
|---|---|---|
| A | Die Standalone-App — PyInstaller-Setup, Tray, WebView2-Fenster, Einrichtungs-Assistent, lokale Queue, Werkzeug-Beschaffung, Win32-Treiber | weg — v5 ersetzt sie |
| B | Der Remote-Encode-Worker — deploy/worker-windows/, /worker-setup/*, Pfad-Map |
bleibt |
| C | Windows-Zweige im Docker-Code — die os.name == "nt"-Stellen in main.py, betrieb.py, ablauf.py, rohdaten.py, dazu die Fähigkeiten-Auskunft im UI |
einzeln prüfen |
Entscheid 8 (30.08.2026) — B bleibt bei Docker und kommt nicht nach v5.
Commander: „Das soll NICHT Teil des neuen Standalone-Produktes sein, da dieser NUR für die Docker-Variante verwendet wird."
Damit ist bestätigt, was zuvor nur Auslegung war: Der Remote-Worker ist kein Standalone-Rippy, sondern eine Funktion der Docker-Installation. Er wird weder abgeräumt (er ist Docker, und Docker bleibt unangetastet) noch nach v5 übernommen (v5 ist Einzelplatz, Entscheid 3 — es gibt dort keinen zweiten Knoten, dem man etwas schicken könnte).
11.2 Teil A — die Standalone-App (weg)
src/rippy/windows_app.py Installer, Dienst, Deinstallation
src/rippy/fenster.py WebView2-Fenster
src/rippy/setup_fenster.py Einrichtungs-Assistent
src/rippy/einrichtung.py Voraussetzungs-Prüfungen
src/rippy/standalone.py lokale Zustellung statt Celery
src/rippy/drives/windows.py Win32-Laufwerkstreiber
src/rippy/drives/win_ioctl.py die Steuercodes
src/rippy/platform/winlauf.py CREATE_NO_WINDOW, Waisen, Job Object
src/rippy/platform/win_registry.py
src/rippy/platform/verknuepfungen.py
src/rippy/platform/dateiangaben.py
src/rippy/tools/ Werkzeug-Katalog + Beschaffung (Windows-only)
src/rippy/rip/audio_cd.py Audio-CD über Win32
src/rippy/rip/musicbrainz_cd.py DiscID-Rechnung
packaging/windows/ der PyInstaller-Bau
dist/windows/ die gebaute EXE + vendor/
+ die zugehörigen test_*.py
Dazu: src/rippy/queue/lokal.py und queue/laeufer.py (die lokale Queue hat
außerhalb der Standalone-App keinen Aufrufer) und bus/waechter.py, soweit er
nur die Windows-Disc-Wache bedient.
Die Steuercodes und Parser sterben nicht — sie sind bereits nach v5 übernommen (§ 3.2 hat sie aus Node bestätigt, § 10 listet den Rest). Was gelöscht wird, ist die Python-Fassung, nicht das Wissen.
11.3 Teil C — die verstreuten Zweige (einzeln prüfen)
Hier ist blindes Löschen gefährlich, weil manches auch ohne die Standalone-App gebraucht wird — vom Remote-Worker (Teil B) oder von der Pfad-Behandlung allgemein.
| Fundort | Prüfen |
|---|---|
docker/api/main.py — betrieb.windows_laufwerke(), die Browse-Sonderfälle, /betrieb-Fähigkeiten |
Die Fähigkeiten-Auskunft bleibt sinnvoll (Docker-AiO vs. verteilt), nur die Windows-Werte fallen weg |
src/rippy/betrieb.py |
Ganz raus oder auf Docker-Fälle eindampfen |
docker/worker/ablauf.py, rohdaten.py |
Die Windows-Pfadzweige raus — aber nativ_nachsehen() prüfen: gilt es auch für den Remote-Worker? |
docker/api/rohdaten.py, mounts.py |
dito |
src/rippy/pfade.py |
Bleibt. Laufwerkswurzeln und UNC braucht auch der Remote-Worker |
UI: useBetrieb, WorkerVerwaltung, Anleitung, Settings |
Nur die Standalone-Texte raus; die Worker-Verwaltung bedient Teil B |
src/rippy/test_keine_container_reste.py |
Der Wächter-Test wird gegenstandslos — mit weg |
11.4 Wie das gemacht wird
- Ein eigener Branch, nicht direkt auf
main. Der Umfang ist zu groß für einen Freihand-Commit. - In der Reihenfolge A → C → (B bleibt). Erst die eindeutigen Dateien, dann die verstreuten Zweige — sonst sucht man Aufrufer, die es noch gibt.
- Die Ampel nach jedem Schritt.
AGENTS.mdRegel A gilt unverändert; ein Aufräumen, das die Tests rot macht, ist nicht fertig, sondern angefangen. - Erst wenn v5 die Etappe W-6 erreicht hat. Solange v5 nicht installierbar ist, ist die alte Fassung das einzige Windows-Rippy, das es gibt. Sie zu löschen, bevor der Ersatz steht, wäre eine Lücke ohne Gegenwert — der Entscheid nennt kein Datum, nur die Richtung.
- Ein SAVEPOINT-Eintrag dazu, mit der Zahl der entfernten Zeilen und dem Hinweis, wo das Wissen jetzt liegt.
12. Etappen
Grundregel: Jede Etappe endet mit grüner Ampel und einem Programm, das man starten kann. Kein großer Umbau, nach dem monatelang nichts geht.
| # | Titel | Inhalt | Fertig, wenn |
|---|---|---|---|
| W-0 | Gerüst | Electron 44 + TypeScript + Vite + Vitest, drei Prozesse, IPC, node:sqlite in Electron prüfen (§ 3.4), Prozess-Leine, CI-Ampel |
Ein Fenster geht auf, der Kern läuft, ein Testlauf ist grün |
| W-1 | Laufwerk | laufwerk/win32.ts aus dem § 3.2-Beweis, Wache über WM_DEVICECHANGE, Disc-Typ, Verriegeln, Auswerfen mit Nachsehen |
Disc rein → Rippy sagt korrekt, was es ist. Auswerfen wirkt (nachgemessen, nicht geglaubt) |
| W-2 | Rippen | makemkvcon-Aufruf, Parser, Fortschritt, Abbruch, Lesefehler-Warnung, Werkzeug-Beschaffung | Eine DVD und eine Blu-ray laufen durch, verlustfrei |
| W-3 | Komprimieren + Ablegen | HandBrake, Encoder gemessen, Presets, Zielstruktur, NFO, Poster, Medienserver | Ein Film liegt fertig in Jellyfin und ist dort sichtbar |
| W-4 | Metadaten-Automatik | Die vier Quellen aus § 5, Sicherheitsgrad, Nachkorrektur | Fünf verschiedene Discs richtig erkannt, ohne Nachfrage |
| W-5 | Oberfläche | Dashboard, Einstellungen, Logs, Bibliothek, Tray, Windows-Toasts, Taskleisten-Fortschritt | Der Commander bedient Rippy einen Abend lang ohne Rückfrage |
| W-6 | Setup + Update | NSIS, Autostart, Erst-Einrichtung, Selbst-Update, Deinstallation | Frischer Rechner: Setup → Disc rein → MKV raus. Und: drüber-installieren geht |
| W-7 | Der Rest | Audio-CD, ISO-Backup, mehrere Laufwerke, 4K-Schlüsselkette | Je Feature ein Nachweis |
Reihenfolge-Begründung: W-1 bis W-3 sind die Kette, ohne die Rippy nichts tut. W-4 und W-5 machen sie bequem. W-6 macht sie weitergebbar. W-7 sind die Ergänzungen, die ohne die Kette keinen Sinn hätten.
13. Risiken und offene Punkte
| Risiko | Bewertung | Behandlung |
|---|---|---|
| MakeMKV-Beta-Key läuft Ende September 2026 ab | hoch × sicher | § 9.1 — Ablaufdatum sichtbar, Warnung 7 Tage vorher, klare Meldung, Dauerlizenz eintragbar. Das ist der akuteste Punkt im ganzen Dokument. |
node:sqlite in Electron ungeprüft |
mittel × unbekannt | Erster Handgriff in W-0. Rückfallebene better-sqlite3 |
| Neubau dauert länger als eine Reparatur | sicher | Deshalb Entscheid 2: Die Docker-Version läuft weiter. Es entsteht keine Lücke |
| Electron-Paket ~150–200 MB | sicher, gering | Ein einmaliger Download. Der Gegenwert ist eine Werkzeugkette statt zweier |
| SmartScreen bei unsignierter EXE | mittel | Entscheid 5: kein Zertifikat. Anleitung + Prüfsumme beim Release |
| Update ohne Signaturprüfung | mittel × Folge von Entscheid 5 | § 6.8 — nur HTTPS, http:// wird abgelehnt. Der Transportweg ist die einzige Absicherung, deshalb darf er nicht optional sein |
| Öffentliche Update-Quelle für Externe | offen × Netz-Frage | Entscheid 6 — Gitea liegt im LAN. Rippy ist für alle drei Wege gebaut (Adresse in der Konfiguration); die Wahl ist eine Infrastruktur-Entscheidung, keine Programmänderung |
Aufräumen von main reißt Docker mit |
mittel × vermeidbar | § 11 — drei Teile sauber getrennt, Remote-Worker bleibt, Ampel nach jedem Schritt, und erst nach v5 W-6 |
| koffi + Electron + npm-Install-Sperre | niedrig | § 3.5 gemessen: koffi lädt mit vorgebauten Binärdateien. In W-0 im Electron-Kontext gegenprüfen |
| Parallel-Rip vs. MakeMKV-Datenverzeichnis | mittel | § 6.5 — messen, bevor die Grenze festgeschrieben wird |
| Ein neu geschriebener Parser bringt neue Fehler | mittel | Die alten Testfälle wandern mit (§ 10). Ein Parser, der sie besteht, kennt dieselben Fallen |
| 4K-UHD-Schlüssel | gelöst | Unter Windows holt makemkvcon sie selbst — der strukturelle Vorteil dieser Plattform, gemessen 25.07.2026 |
Alle drei offenen Punkte sind entschieden (30.08.2026)
Code-Signing: nein (Entscheid 5) · Update-Quelle: Gitea, auch für Externe (Entscheid 6) · alter Windows-Weg: wird entfernt (Entscheid 7) · der Remote-Worker bleibt bei Docker (Entscheid 8, § 11.1). Was daraus an Arbeit folgt, steht in § 11.
14. Was NICHT gebaut wird
- Kein Python. Auch nicht „nur für den einen Parser".
- Kein HTTP-Server, kein Port, kein localhost. Fenster und Kern reden über IPC.
- Keine Docker-Kompatibilität. Kein geteiltes Modul, kein gemeinsames Schema, keine Container-Pfade.
- Kein Linux, kein macOS. „100 % für Windows gebaut" heißt: Wo eine Windows-Lösung besser ist als eine portable, gewinnt die Windows-Lösung.
- Kein ARM-Fork. Rippy bleibt ein Eigenbau.
- Keine Auth. Einzelplatz, kein Netzdienst — es gibt nichts zu schützen.
Anhang — Verhältnis zu den bestehenden Konzepten
KONZEPT.md (v1) und KONZEPT-V2.md (v2) bleiben gültig für die
Docker-Version. Dieses Dokument ersetzt sie nicht, es steht daneben.
Drei Punkte aus v2 werden für Windows bewusst anders entschieden — jeweils mit Begründung:
| v2 sagt | v5 macht | Warum |
|---|---|---|
| Entscheid 4: kein Electron, pywebview + WebView2 (8 MB statt 150 MB) | Electron | Die Rechnung war richtig und die Schlussfolgerung trotzdem falsch: Sie hat nur die Fenster-Frage betrachtet. Der Preis für pywebview war nicht 0 MB, sondern eine zweite Werkzeugkette — PyInstaller, hidden imports, pythonnet, und ein Kern, der aus Container-Code bestand. Electron kostet 150 MB und schenkt uns eine Sprache von der Oberfläche bis zum Laufwerk. |
| Eine Anwendung, drei Verdrahtungen (Ports/Treiber) | Ein Windows-Programm | Die Ports-Architektur ist richtig für ein Produkt, das drei Betriebsarten tragen muss. Bei Entscheid 2 (Docker bleibt getrennt) trägt sie nichts mehr — sie wäre Abstraktion auf Vorrat. |
| REST + SSE als Schnittstelle | IPC | Ein lokaler Webserver in einer Einzelplatz-Anwendung ist eine offene Tür ohne Gegenwert. |
Rippy v5 · Konzept · 30.08.2026 · Branch worktree-windows-electron