diff --git a/SAVEPOINT.md b/SAVEPOINT.md index a793a3b..c5f0756 100644 --- a/SAVEPOINT.md +++ b/SAVEPOINT.md @@ -1,6 +1,170 @@ # SAVEPOINT — Rippy -## Aktueller Stand: v3.15 — Aufräum-Runde: Tempo, tote Routen, 4K-Entscheidung (25.07.2026, 20:00) +## Aktueller Stand: v3.16 — ÜBERGABE: externes Encoden konnte nie funktionieren (26.07.2026) + +> **Zuerst lesen.** Diese Sitzung endete wegen vollem Kontext. Der Auftrag war +> Commander-Feedback aus der ersten Selbst-Einrichtung plus die Diagnose eines +> fehlgeschlagenen Test-Rips. Die Diagnose ist abgeschlossen, zwei Commits sind +> gebaut — **aber NICHT deployt**, und der Kern-Blocker steht noch offen. + +### ZUSTAND, gemessen + +| | | +|---|---| +| Repo | `fd1feaa`, Ampel **grün** | +| **VM** | **`61c38a0` — die letzten 2 Commits sind NICHT aktiv** | +| Windows-Worker des Commanders | läuft mit **altem** Code (vor der Windows-Erkennung) | +| Job `95afdc89` | `failed` beim Encoden | +| **Rohschnitt** | **79,6 GB intakt** auf `/app/media/rippy/95afdc89-…/title_t00.mkv` (NAS) → „Neu komprimieren" genügt, **kein Neu-Rip** | +| Commander-PC | AMD Ryzen 7 9700X · **avx512f** · 16 Kerne · RX 9070 XT | +| Rippy-VM-CPU | QEMU-Generikum · nur `sse4_2` · 4 Kerne | + +### DER KERNBEFUND: drei Ursachen, die ineinandergriffen + +Der Commander vermutete „das System sieht den externen Encoder nicht". **Falsch — +das Routing funktionierte einwandfrei.** Gemessen: + +``` +meta.transcode_node = tobisnicerpc@TobisNicerPC +VM-Worker-Log = nur rip_disc, KEIN transcode_files +22:19:41.271 Kompression eingereiht +22:19:41.453 "Keine Roh-MKVs gefunden" ← 182 ms später +``` + +Sein PC nahm die Aufgabe an und lehnte sie sofort ab. Warum: + +1. **`RIPPY_PATH_MAP` wird von NIEMANDEM gesetzt** — nicht vom Installer, nicht + vom UI, nicht von Compose. `pfad_lokal()` in `tasks.py` hat sogar Tests, aber + keinen Anschluss. `/app/media/...` sind Container-Pfade; ein externer Worker + sieht sie nur übersetzt. **Ein Windows-Worker konnte also nie transcodieren.** + ⚠️ **DAS IST DER OFFENE BLOCKER.** +2. **Die Ablage war im UI überhaupt nicht einstellbar.** `outputDir` wurde von + Vollautomatik und Schnellwahl gelesen, hatte aber **kein Eingabefeld**. Das + Arbeitsverzeichnis hatte eine Auswahl eingehängter Ziele, das Ziel nicht. + Folge: Rohdaten auf der NAS (erreichbar), Ziel auf der VM-Platte (nicht + erreichbar — dort läuft **kein Samba**). Die richtige Einstellung war mit den + vorhandenen Bedienelementen **nicht erreichbar.** → behoben, siehe unten. +3. **Die Fehlermeldung log.** „Keine Roh-MKVs gefunden" klang nach kaputtem Rip, + obwohl der Rip vollständig war. → behoben. + +### GEBAUT in dieser Sitzung (2 Commits, gepusht, Ampel grün) + +**`fe12401`** — Hardware-Encoder + CPU-Merkmale auf Windows, ehrliche Fehler: +- **Hardware-Erkennung war MEIN Bug:** `leite_backends_ab()` verlangte + `/dev/dri` bzw. `nvidia-smi` — beides gibt es unter Windows nicht. Der PC des + Commanders meldete deshalb nur CPU, obwohl HandBrakes Windows-Build `vce_*` + kennt. Die Prüfung war zudem überflüssig: **HandBrake probiert Hardware selbst + an und listet nur Nutzbares** (auf der VM belegt: „qsv: not available", und + `qsv_*` fehlt dann in `--help`). Jetzt ist HandBrakes Liste die einzige + Auskunft, unterschieden nach Familie (`nvenc`/`qsv`/`vce`/`vaapi`) plus eigener + Kennung für Hardware-AV1. +- **Vektorbefehle unter Windows** über `IsProcessorFeaturePresent` (kernel32, + winnt.h) + CPU-Name aus der Registry. Auf dem Commander-PC gegengeprüft: + vorher „AMD64 Family 26 Model 68 / unbekannt", jetzt „AMD Ryzen 7 9700X / + avx512f". Damit verschwindet die AVX2-Warnung für diesen Worker von selbst. +- **`_erreichbarkeit_pruefen()`** unterscheidet jetzt „Pfad nicht erreichbar + + kein Mapping" (nennt `RIPPY_PATH_MAP` mit Beispiel), „Mapping greift nicht" + und „Ordner leer" — und prüft **beide** Pfade, nicht nur die Quelle. Jede + Meldung sagt ausdrücklich, dass die Rohdaten nicht verloren sind. +- Vier Platzhalter mit der Umgebung des Commanders (`192.168.178.20`, + `TOBIS-PC`, seine Jellyfin- und Rippy-IP) verallgemeinert. + +**`fd1feaa`** — Ablage einstellbar + Kohärenz-Prüfung: +- Auswahlliste **„Ablage"** in Einstellungen → Ripping, gleiche Liste wie beim + Arbeitsverzeichnis. Wirkt automatisch in Vollautomatik und Schnellwahl, weil + beide `outputDir` lesen — genau wie vom Commander gefordert. +- **Warnung, sobald ein EXTERNER Worker gemeldet ist** und Ablage + + Arbeitsverzeichnis nicht beide auf einer erreichbaren Freigabe liegen. Drei + Fälle mit Konsequenz im Klartext (kann nicht lesen / kann nicht schreiben / + läuft, kostet aber eine Vollkopie). +- „Extern" ist keine Heuristik: `caps.py` meldet `extern` selbst (`/app` gibt es + im Rippy-Image immer, außerhalb nie) und zusätzlich `pfad_map`. + +### OFFENE PUNKTE — nach Priorität, mit Kontext + +**1. `RIPPY_PATH_MAP` setzen (DER BLOCKER).** Der Installer muss fragen „wie +erreicht dieser PC die Freigabe?" und den Wert in `start-tray.bat` / +`start-worker.bat` schreiben. Format laut `pfad_lokal()`: +`/app/media=\\NAS\rippy;/app/temp=…` (Paare per `;`, Präfix-Ersetzung, wandelt +`/` zu `\`, wenn das Ziel Backslashes enthält). Commander-Vorgabe dazu: *„Wenn +ein externes Ziel für den Speicher eingehängt ist, soll Rippy das ausgewählte als +Arbeitsziel verwenden … das muss auch für den Automatik-Modus so sein."* Punkt 2 +oben erfüllt die Einstellungs-Seite davon; es fehlt die Worker-Seite. +Danach: Commander kann seinen 80-GB-Rohschnitt per „Neu komprimieren" auf dem +Ryzen laufen lassen. + +**2. Preset-Liste vom Worker holen** — Voraussetzung für „immer das Beste". +Commander: *„Bei den Presets soll IMMER das Beste ausgewählt werden"* und *„wenn +der Worker AV1 oder noch besseres kann, immer diesem empfehlen, die Warnung +verschwindet oder wird von orange zu grün"*. Blocker: Die Namen der +HandBrake-**Hardware**-Presets sind auf der Rippy-VM **nicht ermittelbar** (deren +HandBrake hat keinen Hardware-Encoder), und Erfinden verstößt gegen AGENTS +Regel D — das Projekt hat das zweimal teuer bezahlt. Richtige Lösung: `caps.py` +meldet `HandBrakeCLI --preset-list` des jeweiligen Workers, das UI bietet genau +diese an. Beendet das Raten dauerhaft. + +**3. Dashboard + ETA.** Commander: *„Der Server Status muss dringend überarbeitet +werden, das Dashboard soll ja quasi alles auf einen Blick zeigen"* — „Auslastung: +0 % (Aktiv)" ist nichtssagend. Dazu eine **ETA** im Dashboard und beim externen +Worker. Restzeit ist aus dem Fortschrittsverlauf schätzbar; ehrlich bleiben, +solange die Datenlage dünn ist. Verlässlichster Messpunkt (in dieser Sitzung +bewährt): Leseposition im Quellstrom über `/proc//fdinfo/`. + +**4. Datei-Browser aus dem Rip-Dialog.** Commander: *„Warum wird hier der Datei +Browser noch angezeigt — das ist doch quatsch"*. Prüfen, ob wirklich redundant +(darüber gibt es Schnellwahl + Arbeitsverzeichnis-Auswahl), dann raus oder +einklappen. Datei: `docker/ui/src/components/RipTargetModal.tsx`. + +**5. Nicht-Debian-Hosts.** `install.sh` nennt bei fehlendem Compose nur +`sudo apt install docker-compose-plugin`; auf Arch/Fedora/openSUSE falsch. +Paketmanager erkennen. Klarstellen: der Worker-**Container** ist unabhängig vom +Host-System. + +**6. Warnung im Rip-Dialog** (nicht nur in den Einstellungen), wenn der gewählte +externe Encoder die Pfade nicht erreicht — vor dem Start, nicht nach einer Stunde. +Bausteine liegen: `caps.py` meldet `extern` und `pfad_map`. + +**7. Jikan-Reihenfolge prüfen** (Nebenbefund). Kette ist TMDB → **Jikan** → OMDb +mit Gate `MINDEST_AEHNLICHKEIT = 0.55`. Jikan wird also wirklich benutzt (Antwort +auf die Commander-Frage), läuft aber **vor** OMDb: bei einem Nicht-Anime, den +TMDB verpasst, antwortet zuerst eine Anime-Datenbank. 0,55 ist großzügig. + +**8. Aus dem ARM-Vergleich, nicht gebaut:** ISO-Sicherung für Datenträger, die +weder Film noch Audio-CD sind (daran scheitert Rippy heute), und **mehrere +Laufwerke gleichzeitig** — Rippy sieht sie (`/dev/sr[0-9]*`), ob parallel gerippt +wird, ist **unbewiesen**. + +**9. Ältere offene Punkte, unverändert gültig:** +- „Job aus der Liste entfernen" sagt nicht, wie viel daneben liegen bleibt — der + Rohschnitt verwaist unsichtbar (v3.14). +- Discord-Webhook und MakeMKV-Key liegen im Klartext in der settings-Tabelle. +- **VM-CPU-Typ steht auf `qemu64`** → `host` würde AVX2 freischalten, 2–4× + schneller. Anleitung steht in der README („Rippy schneller machen"). +- **`install.sh` ist nie als root durchgelaufen** — Verzeichnisse anlegen, + `mount --make-rshared` und die systemd-Unit sind ungetestet. +- Zwei API-Tests laufen nur in der Ampel (`test_api_smoke.py` überspringt sich + unter Windows selbst). + +### FALLEN, die diese Sitzung gekostet haben + +- **Deutsche Anführungszeichen in DOPPELT gequoteten Python-Strings** beenden den + String vorzeitig. Dreimal hineingetappt. Der Bestand nutzt dafür **einfach** + gequotete f-Strings (`f'…„{x}"…'`). In dreifach gequoteten Docstrings ist es + unproblematisch. +- **In f-Strings steht in `{...}` CODE, kein Text.** Ein Umlaut-Konverter machte + aus `f"{groesse}"` ein `f"{größe}"`, während die Variable `groesse` hieß — + Ruff fand es als F821. +- **`docker exec` ohne `sh -c` expandiert kein `*`** — ein `du -sh /pfad/*` + liefert dann still nichts und sieht wie „leer" aus. +- **Eine `/proc`-Suche nach „HandBrake" trifft die eigene Shell mit**, weil deren + Kommandozeile das Wort enthält. Zwei Fehlalarme. +- **`pydantic-core` springt lokal wiederholt auf 2.47.0** und bricht damit das + Einsammeln ALLER API-Tests (`SystemError`). Fix: + `python -m pip install "pydantic-core==2.46.4"`. Zweimal nötig gewesen. + +--- + +## Vorheriger Stand: v3.15 — Aufräum-Runde: Tempo, tote Routen, 4K-Entscheidung (25.07.2026, 20:00) > **Deployt und live gegengeprüft.** Auftrag war „bau alles so um, dass es > sauber ist" mit fünf Vorgaben: saubere Codebase, selbsterklärendes UI,