docs(savepoint): v3.16 Uebergabe - externes Encoden konnte nie funktionieren
Ampel / ampel (push) Successful in 27s
Ampel / ampel (push) Successful in 27s
Diese Sitzung endete wegen vollem Kontext. Der Savepoint ist so geschrieben, dass die naechste ohne Nachfragen weitermachen kann. ZUSTAND, den man kennen MUSS: Repofd1feaamit gruener Ampel, aber die VM laeuft noch61c38a0- die letzten zwei Commits sind NICHT deployt, und der Windows-Worker des Commanders laeuft mit altem Code. Der 80-GB-Rohschnitt liegt intakt auf der NAS, "Neu komprimieren" genuegt also, sobald der Blocker faellt. DER KERNBEFUND aus dem fehlgeschlagenen Test-Rip, mit Messung statt Vermutung: Das gezielte Routing funktionierte einwandfrei - sein PC nahm die Aufgabe an und lehnte sie 182 ms spaeter ab. Drei Ursachen griffen ineinander, zwei sind behoben, eine bleibt der Blocker (RIPPY_PATH_MAP wird von niemandem gesetzt). Die offenen Punkte stehen nach Prioritaet, jeweils MIT dem Kontext, der zum Weiterarbeiten fehlt: Format von pfad_lokal fuer Punkt 1, warum Punkt 2 nicht ohne die Preset-Liste vom Worker geht (AGENTS Regel D - Namen erfinden hat das Projekt zweimal teuer bezahlt), welcher Messpunkt sich fuer die ETA bewaehrt hat (/proc/<pid>/fdinfo statt Fortschrittsanzeige), und welche Datei jeweils dran ist. Dazu ein eigener Abschnitt "Fallen, die diese Sitzung gekostet haben" - deutsche Anfuehrungszeichen in doppelt gequoteten Python-Strings (dreimal), Code in f-String-Einsetzungen, docker exec ohne sh -c verschluckt Globs, /proc-Suche trifft die eigene Shell, und pydantic-core springt lokal wiederholt zurueck. Alles auch in den Memory-Notizen, damit es nicht wieder entdeckt werden muss. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+165
-1
@@ -1,6 +1,170 @@
|
|||||||
# SAVEPOINT — Rippy
|
# 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/<pid>/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
|
> **Deployt und live gegengeprüft.** Auftrag war „bau alles so um, dass es
|
||||||
> sauber ist" mit fünf Vorgaben: saubere Codebase, selbsterklärendes UI,
|
> sauber ist" mit fünf Vorgaben: saubere Codebase, selbsterklärendes UI,
|
||||||
|
|||||||
Reference in New Issue
Block a user