574354131c
SAVEPOINT bekommt den Stand v3.14: der unwirksame Platten-Schutz zuerst (wichtigster Fund), dann die gemessenen Werte, das Gebaute, die vier toten Endpunkte als Entscheidungsvorlage - und ein Abschnitt "SOFORT ENTSCHEIDEN". Der laufende Akira-Encode wird beim Fertigwerden mit dem DEPLOYTEN, alten Code versuchen, 75 GB in 37 GB zu kopieren. keepOriginal steht auf true, und den Wert hat die Aufgabe beim Start gelesen - jetzt umstellen aendert daran nichts mehr. Der Savepoint nennt die drei Optionen mit Empfehlung. Zwei Richtigstellungen an v3.13, beide durch Messung: - "progress=99 ist ein Altwert aus dem Absturz" war falsch. Beide Startpfade setzen auf 0; der Wert kam frisch vom Scan-Durchlauf. Ein Bug, kein Ueberrest. - Die Erwartung, _original_aufheben werde nur warnen, war falsch - siehe EXDEV-Fund im vorigen Commit. Ehrlich als OFFEN markiert: Was die Platte am 25.07. mittags fuellte, ist NICHT belegt. Es gibt keine Kopier-Reste, kein original-Verzeichnis und keinen einzigen Log-Eintrag von _original_aufheben, das in beiden Zweigen loggt. Der Mechanismus ist jetzt bewiesen, sein Zuschlagen an jenem Tag nicht. Lieber offen lassen als eine dritte Vermutung aufstellen. AGENTS bekommt Etappe 19 und einen neuen Abschnitt, der das wiederkehrende Muster benennt: nicht aus einem Zustandswert auf einen Mechanismus schliessen - vier belegte Faelle. Plus die Umkehrung, die diese Sitzung gekostet hat: gleiches st_dev heisst NICHT gleicher Mount. Was ausprobierbar ist, wird ausprobiert statt vorhergesagt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
849 lines
47 KiB
Markdown
849 lines
47 KiB
Markdown
# SAVEPOINT — Rippy
|
||
|
||
## Aktueller Stand: v3.14 — Durchsicht: vier Placebos und ein unwirksamer Schutz (25.07.2026, 18:40)
|
||
|
||
> Diese Sitzung hat nichts deployt (der Akira-Encode läuft — ein Rebuild
|
||
> schießt ihn ab). Alles unten ist committet und die Ampel ist grün.
|
||
> **Zuerst lesen: „SOFORT ENTSCHEIDEN" ganz unten.**
|
||
|
||
### DER WICHTIGSTE FUND: der Platten-Schutz aus `c065967` greift nicht
|
||
|
||
`_original_aufheben()` entschied per `os.stat().st_dev`, ob umgehängt oder
|
||
kopiert werden muss. Auf der VM gemessen — **beides gleichzeitig wahr**:
|
||
|
||
```
|
||
st_dev /app/temp = 2050
|
||
st_dev /app/media = 2050 → identisch
|
||
os.rename(...) → EXDEV, "Invalid cross-device link"
|
||
```
|
||
|
||
Der Kernel vergleicht bei `rename()` den **Mount**, nicht das Gerät.
|
||
`/app/temp` (Docker-Volume) und `/app/media` (Bind-Mount) sind zwei Mounts
|
||
DERSELBEN ext4-Partition. Die Prüfung sah deshalb „gleiches Dateisystem",
|
||
**übersprang die Platzprüfung**, und `shutil.move` kopierte doch — 75 GB bei
|
||
37 GB frei. Der Schutz hätte genau den Schaden zugelassen, gegen den er
|
||
gebaut wurde.
|
||
|
||
**Behoben:** `os.rename` wird jetzt VERSUCHT statt vorhergesagt. Klappt es,
|
||
ist es umgehängt. Kommt EXDEV, steht die Kopie fest — und erst dann wird der
|
||
Platz geprüft. Vier Tests dazu (`test_original_aufheben.py`), inklusive des
|
||
Falls, der die Platte füllte.
|
||
|
||
### GEMESSEN, Stand 18:30 (alles per Befehl auf der VM geprüft)
|
||
|
||
- **Container:** alle 5 `Up`, api/postgres/redis `healthy`. api/ui/worker seit
|
||
18:00:39 (Deploy von `8bb075c`), postgres/redis älter.
|
||
- **Platte:** 148 G, 105 G belegt, 37 G frei = 75 G Rohschnitt + 4,9 G Medien
|
||
(Evangelion) + ~25 G System. **Keine Kopier-Reste**, kein `original`-Ordner.
|
||
- **Akira-Encode läuft:** HandBrake PID 40 seit 18:01:37, Preset
|
||
`H.265 MKV 2160p60 4K`, **3,84 von 4 Kernen**. Leseposition im Quellstrom
|
||
**1.145.940.149 von 79.604.951.639 Bytes = 1,44 %**.
|
||
- **Restlaufzeit ≈ 28–55 h.** Zwei Messfenster ergaben 395 und 784 KB/s — das
|
||
Tempo schwankt mit der Bildkomplexität, deshalb eine Spanne und keine Zahl.
|
||
- **Die Ursache dafür ist neu und behebbar:** Die VM läuft auf dem generischen
|
||
QEMU-CPU-Modell (`QEMU Virtual CPU version 2.5+`), `grep -c avx2
|
||
/proc/cpuinfo` = **0**, nur bis `sse4_2`. x265 lebt von AVX2. Abhilfe:
|
||
CPU-Typ von VM 106 in Proxmox auf `host` stellen (braucht VM-Neustart).
|
||
- **HandBrake im Worker-Image kann:** `svt_av1`, `x264`, `x265` (je 10/12-bit),
|
||
`mpeg4/2`, `VP8/9`, `theora` — und **keinen einzigen Hardware-Encoder**.
|
||
- **Ampel grün** für `b526a0a` und `8bb075c` (Gitea-API abgefragt).
|
||
|
||
### GEBAUT — vier Placebos entfernt bzw. echt gemacht
|
||
|
||
1. **Fortschritt log statt Wahrheit.** `get_progress_from_line` matchte jede
|
||
Zahl vor einem `%` — also auch HandBrakes **Scan-Durchlauf**, der VOR dem
|
||
Encodieren bis 100 % hochläuft. Dazu warf `if progress > 0` alle echten
|
||
Werte unter 1,00 % weg. Ergebnis: Anzeige klebte stundenlang auf 99 %.
|
||
Jetzt wird nur die `Encoding:`-Zeile gelesen, `task N of M` mitgerechnet,
|
||
und **-1 heißt „keine Angabe"** (Muster von `get_progress_from_prgv`).
|
||
Formatstrings aus dem Binary gelesen, nicht geraten.
|
||
**⚠️ Richtigstellung zu v3.13:** Dort steht, `progress=99` sei ein „Altwert
|
||
aus dem Absturz". Falsch — beide Startpfade setzen auf 0, der Wert war
|
||
frisch vom Scan-Durchlauf geschrieben. Es war ein Bug, kein Überrest.
|
||
2. **„Automatischer Auswurf" tat nichts.** Die Einstellung (Standard: ein)
|
||
wurde von niemandem gelesen: DVD/Blu-ray warfen **nie** aus, Audio-CDs
|
||
**immer**, weil abcde `-x` fest verdrahtet bekam. Jetzt entscheidet die
|
||
Einstellung beides (`wirf_disc_aus()` per CDROMEJECT-ioctl, Linux-guarded).
|
||
3. **„Alle Tracks rippen" konnte nichts bewirken** — abcde bekommt keine
|
||
Track-Auswahl und es gibt keine Oberfläche dafür. Schalter entfernt, an
|
||
seiner Stelle steht jetzt die Wahrheit („wird immer vollständig gerippt").
|
||
4. **Encoder-Auslese behauptete statt zu messen.** `cpu-x264`/`cpu-x265`
|
||
standen fest verdrahtet drin („immer dabei") — ein Rip-Worker **ohne**
|
||
HandBrake behauptete damit, komprimieren zu können. Und `vaapi` wurde
|
||
allein wegen `/dev/dri` gemeldet, ohne zu prüfen, ob HandBrake das kann
|
||
(dieses Image kann es nicht). Jetzt aus `HandBrakeCLI --help` geparst, plus
|
||
**CPU-Modell, Kernzahl und Vektorbefehlsstufe** je Worker — mit sichtbarer
|
||
Warnung im UI, wenn AVX2 fehlt. Genau die Angabe, deren Fehlen den
|
||
55-Stunden-Encode unsichtbar machte.
|
||
|
||
### GEBAUT — Zombie-Erkennung (v3.13 Punkt 2 abgearbeitet)
|
||
|
||
`zombies.py`: Beim Worker-Start werden Jobs, die auf `ripping`/`transcoding`/
|
||
`canceling` stehen, gegen Celerys `active`/`reserved`/`scheduled` gehalten und
|
||
ehrlich auf `failed` gesetzt, wenn niemand daran arbeitet. Drei Sicherungen,
|
||
weil ein falsch getöteter Job teurer ist als eine stehende Leiche:
|
||
|
||
- **nur beim Start** (da ist „es lief nichts" eindeutig),
|
||
- **120 s Gnadenfrist** (Celery stellt unbestätigte Aufgaben erneut zu),
|
||
- **Vollzähligkeit**: antworten weniger Knoten als laut Herzschlag online
|
||
sind, wird NICHTS gewertet — sonst wäre der laufende Job eines
|
||
beschäftigten Remote-Workers eine falsche Leiche.
|
||
|
||
13 Tests, unter anderem: „laufender Job wird nicht angetastet" und
|
||
„schweigender Worker verhindert jedes Urteil".
|
||
|
||
### GEBAUT — Pfad-Prüfung gehärtet
|
||
|
||
Elf Stellen prüften mit nacktem `startswith(MEDIA_ROOT)`. `/app/media-boese/x`
|
||
beginnt mit `/app/media`, liegt aber außerhalb — betroffen waren auch `/browse`
|
||
und `/browse/mkdir`, wo der Pfad vom Nutzer kommt. Neuer Zwillings-Helfer
|
||
`unter_wurzel()` in `api/main.py` und `worker/tasks.py`, alle elf Stellen
|
||
umgestellt, Tests in beiden.
|
||
|
||
Nebenbefund dabei: `_zielbasis()` benutzte `os.path.normpath` — unter Windows
|
||
werden daraus Backslashes und die Prüfung greift nicht mehr; das gewählte Ziel
|
||
wäre still auf den Standard zurückgefallen. Genau die Falle, die
|
||
`_arbeitsverzeichnis()` drei Zeilen weiter dokumentiert und mit `posixpath`
|
||
vermeidet. Live war es nie (nur aus `rip_disc`, das auf Windows verriegelt
|
||
ist), jetzt konsistent.
|
||
|
||
### GEFUNDEN, NICHT ANGETASTET — vier tote Endpunkte
|
||
|
||
Nirgends im UI referenziert (mechanisch gegengeprüft: alle `api.*`-Aufrufe
|
||
gegen alle Routen):
|
||
|
||
| Endpunkt | Lage |
|
||
|---|---|
|
||
| `POST /jellyfin/format` | ersetzt durch `medien.py` im Worker; zieht `nfo_generator.py` + `image_downloader.py` in der API mit, die sonst niemand nutzt |
|
||
| `POST /prescan` | ohne Aufrufer (die `PreScan`-Klasse selbst wird woanders sehr wohl gebraucht) |
|
||
| `GET /stream/jobs` | niemand konsumiert ihn; der Kommentar behauptet einen „Fix 23.07.", der ihn funktionsfähig machte — gebraucht wird er trotzdem nicht |
|
||
| `GET /worker-setup/windows-gui` | seit der `.exe` (v3.9) unreferenziert |
|
||
|
||
Bewusst nicht entfernt: `test_api_smoke.py` prüft `/prescan` als verdrahtete
|
||
Route, und Entfernen ist eine Entscheidung, keine Reparatur. **Der Commander
|
||
entscheidet.**
|
||
|
||
### NOCH OFFEN / EHRLICH UNGEKLÄRT
|
||
|
||
- **Was die Platte am 25.07. mittags füllte, ist nicht belegt.** Es gibt keine
|
||
Kopier-Reste, kein `original`-Verzeichnis und **keinen einzigen Log-Eintrag
|
||
von `_original_aufheben`** — das loggt in beiden Zweigen. Zwischen 10:21:50
|
||
und 17:49 steht überhaupt nichts im Log. Der EXDEV-Mechanismus ist jetzt
|
||
belegt (siehe oben), dass er DAMALS zuschlug, ist es nicht.
|
||
- **`tracks:/dev/sr0` meldet `{"status":"done","tracks":[]}`** — null Titel für
|
||
eine Disc, die MakeMKV mit `TCOUNT:5` öffnet. Nicht weiter verfolgt.
|
||
- **Der Discord-Webhook und der MakeMKV-Key liegen im Klartext** in der
|
||
settings-Tabelle. Für Heimnetz erwartbar, aber der Webhook ist eine echte
|
||
Zugangsberechtigung.
|
||
- **Zwei neue API-Tests laufen nur in der Ampel** — `test_api_smoke.py`
|
||
überspringt sich unter Windows selbst (`main.py` braucht `fcntl`).
|
||
|
||
### SOFORT ENTSCHEIDEN
|
||
|
||
**Der laufende Job wird beim Fertigwerden mit dem DEPLOYTEN (alten) Code
|
||
versuchen, 75 GB in 37 GB zu kopieren.** `keepOriginal` steht auf `true`, und
|
||
den Wert hat die Aufgabe beim Start um 18:01:37 gelesen — ihn jetzt umzustellen
|
||
ändert für diesen Lauf nichts mehr. Der Ablauf wäre: Platte läuft auf 100 %,
|
||
dann ENOSPC, dann räumt der `except`-Zweig die Teilkopie weg. Selbstheilend —
|
||
aber währenddessen ist die Systemplatte voll, und genau daran hat sich heute
|
||
Mittag der Worker-Container verschluckt.
|
||
|
||
Die Optionen, in der Reihenfolge, die ich empfehle:
|
||
|
||
1. **Encode abbrechen, deployen, Kompression neu anstoßen.** Kostet die
|
||
bisherigen ~30 Minuten (der Lauf ist bei 1,44 % — praktisch nichts) und
|
||
bringt sofort alle Fixes live, inklusive des Platten-Schutzes und der
|
||
ehrlichen Fortschrittsanzeige. Wer ohnehin über den CPU-Typ nachdenkt,
|
||
erledigt das im selben Fenster.
|
||
2. **Laufen lassen und in 1–2 Tagen deployen**, vorher die 75 GB von Hand
|
||
wegräumen oder auf die NAS schieben, damit die Kopie nicht anlaufen kann.
|
||
3. **Laufen lassen und den vollen Plattenlauf in Kauf nehmen.**
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.13 — ÜBERGABE (25.07.2026, 18:05)
|
||
|
||
> Dieser Block ist eine Übergabe an die nächste Sitzung. Er trennt bewusst
|
||
> **gemessen** von **vermutet** — in dieser Sitzung wurden zwei Behauptungen
|
||
> aufgestellt, die sich als falsch erwiesen (siehe „Vertrauensnotiz" unten).
|
||
> Im Zweifel: selbst nachmessen, nicht diesem Dokument glauben.
|
||
|
||
### GEMESSEN, Stand 18:05 (alles per Befehl auf der VM geprüft)
|
||
|
||
- **Container:** api/postgres/redis/ui/worker alle `Up`, api + postgres +
|
||
redis `healthy`.
|
||
- **Platte:** `/dev/sda2` 148 G, 105 G belegt, **37 G frei** (75 %).
|
||
- **Läuft gerade:** `HandBrakeCLI --input
|
||
/app/temp/raw/73b89777-…/title_t00.mkv --output
|
||
"/app/media/movies/Akira (1988)/title_t00.mkv" --preset
|
||
"H.265 MKV 2160p60 4K" --all-audio --all-subtitles`
|
||
- **Job `73b89777-a808-426f-8159-d406d27d0ec8`:** `status='transcoding'`,
|
||
`progress=99` (⚠️ **Altwert aus dem Absturz, NICHT der echte Fortschritt** —
|
||
der Lauf hat um 18:02 begonnen), `disc_type='uhd'`,
|
||
`output_path='/app/media/movies/Akira (1988)'`.
|
||
- **Dateien:** `…/Akira (1988)/title_t00.mkv` ist **0 Bytes** (HandBrake hat
|
||
die vorherige 1080p-Fassung beim Start gekürzt und schreibt gerade neu).
|
||
Roh-Rip `/app/temp/raw/73b89777-…/` = **75 GB, unversehrt.**
|
||
- **Git:** `8bb075c` ist HEAD und deployt. Davor `c065967`, `e84afc1`,
|
||
`f449c4e`, `0935766`. Alle Ampeln waren grün.
|
||
- **Schlüsselspeicher:** 604 Disc-Schlüssel, `/system/keystore` antwortet.
|
||
- **NAS:** `//192.168.178.62/rippy` auf `/srv/rippy/media/rippy` gemountet,
|
||
erreichbar, **2311 GB frei**. Wird als Ablageziel gelistet.
|
||
|
||
### NACHTRAG 18:35 — der 4K-Lauf wurde abgebrochen, zwei neue Befunde
|
||
|
||
- **4K-HEVC ist auf dieser CPU nicht machbar.** Gemessen: von 18:02 bis 18:31
|
||
kam der Lauf von 0 auf **1 %** → hochgerechnet **~50 Stunden** für den Film.
|
||
Der Commander hat um 18:31 abgebrochen. **Konsequenz, die noch zu
|
||
entscheiden ist:** entweder UHD gar nicht komprimieren (Roh-MKV behalten,
|
||
`transcodeEnabled` für UHD aus), oder ein Hardware-Encoder (Remote-Worker
|
||
mit GPU, `nvenc`/`vaapi`), oder bewusst bei 1080p bleiben. Das eben
|
||
gebaute Preset-je-Disc-Typ ist damit richtig, aber allein nicht genug.
|
||
- **Abbruch wirkt verzögert (FEHLER, nicht gebaut).** Job steht seit 18:31 auf
|
||
`canceling`, **HandBrake lief um 18:35 immer noch**. Ursache: Der Abbruch
|
||
wird nur in `datei_fortschritt` geprüft, und diese Closure läuft nur, wenn
|
||
sich die PROZENTZAHL ändert (`tasks.py`, `if gesamt == letzter[0]: return`).
|
||
Bei 1 % alle 30 Minuten heißt das: bis zu eine halbe Stunde, in der
|
||
„Abbrechen" für den Nutzer wirkungslos aussieht. Der Abbruch muss unabhängig
|
||
vom Fortschritt geprüft werden (z. B. zeitgesteuert beim Lesen der
|
||
HandBrake-Ausgabe).
|
||
- **Die 1080p-Fassung ist weg.** HandBrake hat sie beim Start auf 0 Bytes
|
||
gekürzt; aktuell liegen dort ~64 MB 4K-Fragment. Der **75-GB-Rohschnitt ist
|
||
unversehrt** — es ist also nichts unwiederbringlich verloren, aber im
|
||
Akira-Ordner liegt gerade eine unbrauchbare Datei.
|
||
|
||
### WAS ALS NÄCHSTES ANSTEHT
|
||
|
||
1. **Ausgang des 4K-Laufs prüfen.** Erwartung, die noch NICHT bewiesen ist:
|
||
Der Job endet **erfolgreich**, und „Original behalten" (Setting steht auf
|
||
`true`) meldet nur eine **Warnung**, weil 75 GB nicht neben 37 GB freien
|
||
Platz passen. Genau dieser Pfad ist neu (`_original_aufheben` in
|
||
`tasks.py`) und in der Praxis noch nie gelaufen. Wenn er hält, ist der
|
||
Ausfall von heute Mittag strukturell behoben.
|
||
2. **Zombie-Erkennung fehlt (gefunden, NICHT gebaut).** Nach dem Absturz stand
|
||
der Job auf `transcoding 96 %`, obwohl weder ein Prozess lief noch etwas in
|
||
den Celery-Queues stand (beide `llen` = 0). Folge: keine Anzeige, kein
|
||
Download, und der „Neu komprimieren"-Knopf fehlt, weil
|
||
`_kann_neu_komprimieren` (main.py) `status == "failed"` verlangt. Der
|
||
Worker sollte beim Start solche Leichen erkennen und ehrlich auf `failed`
|
||
setzen.
|
||
3. **`keepOriginal` steht auf `true`** — von dieser Sitzung gesetzt, um den
|
||
4K-Rohschnitt zu retten. Bewusst entscheiden, ob das so bleibt: mit
|
||
Arbeitsverzeichnis auf der NAS-Freigabe wäre es ein reines Umhängen statt
|
||
einer Vollkopie.
|
||
4. **75 GB Rohschnitt** liegen weiter in `/app/temp/raw/73b89777-…`. Nach
|
||
erfolgreichem 4K-Lauf entscheiden, ob er weg kann.
|
||
|
||
### VERTRAUENSNOTIZ — zwei Fehlschlüsse dieser Sitzung
|
||
|
||
- **„MakeMKVs Schlüssel-Kanal ist abgeschaltet"** — falsch. Stützte sich auf
|
||
zwei tote Hostnamen aus alten Forumsbeiträgen, die MakeMKV längst nicht mehr
|
||
benutzt. Richtig: `makemkvcon` unter **Linux** fragt nie, die
|
||
**Windows**-Version schon. Korrigiert in v3.11.
|
||
- **„Celery hat die Aufgabe nach dem Deploy erneut zugestellt"** — falsch.
|
||
Aus dem Status `transcoding` geraten, ohne Prozesse oder Queues zu prüfen.
|
||
Es war ein Zombie-Eintrag (Punkt 2 oben).
|
||
|
||
Beide Male war das Muster dasselbe: **aus einem Zustandswert auf einen
|
||
Mechanismus geschlossen, statt den Mechanismus zu messen.**
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.12 — Preset je Disc-Typ (25.07.2026)
|
||
|
||
- **Der Fund:** Beim ersten echten UHD-Rip aufgefallen — die Kompression
|
||
fragte den Disc-Typ **gar nicht**: `preset = einstellungen.get(
|
||
"transcodePreset")`, ein globales Preset für alles. Live eingestellt war
|
||
`HQ 1080p30 Surround`. Der laufende Akira-Rip wäre also verlustfrei in 4K
|
||
gerippt und danach **auf 1080p heruntergerechnet** worden — und mit
|
||
`keepOriginal: False` wäre der 4K-Rohschnitt anschließend gelöscht worden.
|
||
Aufgefallen ist es nur, weil der Commander gefragt hat, ob Rippy das
|
||
UHD-Preset automatisch nimmt.
|
||
- **Sofortmaßnahme am laufenden Job:** `keepOriginal` auf `True` gesetzt
|
||
(nur dieses eine Feld, gegengeprüft: kein anderer Schlüssel verändert).
|
||
Damit überlebt der 4K-Rohschnitt die Kompression auf jeden Fall.
|
||
- **Gebaut:** `preset_fuer(disc_type, einstellungen)` in `ripping.py` (pure,
|
||
getestet) plus drei Einstellungen `transcodePresetDvd` / `…Bluray` /
|
||
`…Uhd`. Reihenfolge: Preset des Disc-Typs → allgemeines
|
||
`transcodePreset` → `DEFAULT_HB_PRESET`. **Bestandsinstallationen ändern
|
||
ihr Verhalten nicht**, solange die neuen Felder nicht gespeichert sind.
|
||
`transcode_files` holt den Disc-Typ aus dem Job-Datensatz und schreibt ihn
|
||
mit ins Log.
|
||
- **UI (Einstellungen → Verarbeitung):** drei Auswahlfelder statt einem, mit
|
||
Klartext dazu, warum 4K auf ein 2160p-Preset gehört. Alle Preset-Namen
|
||
stammen aus `HandBrakeCLI --preset-list` im Worker-Image (1.6.1) — nicht
|
||
geraten (AGENTS Regel D).
|
||
- **⚠️ Deploy bewusst zurückgehalten:** `docker compose up -d --build`
|
||
würde den Worker-Container neu erstellen und den **laufenden Akira-Rip
|
||
abbrechen**. Erst deployen, wenn der Job durch ist. Der 4K-Rohschnitt ist
|
||
durch `keepOriginal` geschützt; danach reicht „Neu komprimieren" im UI,
|
||
um mit dem richtigen Preset in 4K zu komprimieren.
|
||
- **Nebenbefund:** `ps` gibt es im Worker-Image nicht (python-slim). Frühere
|
||
Prüfungen auf laufende Rips per `ps | grep` lieferten deshalb still
|
||
„nichts aktiv" — richtig geht es über `/proc`.
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.11 — 4K-UHD GELÖST: Akira geht auf (25.07.2026)
|
||
|
||
- **🎉 Der Durchbruch:** Nach Übernahme des Schlüsselspeichers öffnet
|
||
`makemkvcon` auf der VM die Akira-UHD: „Operation successfully
|
||
completed", **`TCOUNT:5`**, fünf Titel — identisch zum Windows-Ergebnis.
|
||
**Erster belegter UHD-Disc-Zugriff auf der Rippy-Maschine.**
|
||
- **Die echte Ursache — und sie ist eine andere als in v3.10:**
|
||
`makemkvcon` unter **Linux** ruft Disc-Schlüssel **nie** ab. Die
|
||
**Windows**-Version tut es. Gegenprobe mit demselben Laufwerk und
|
||
derselben Disc:
|
||
|
||
| | Linux (Worker) | Windows |
|
||
|---|---|---|
|
||
| Verbindungen beim Disc-Öffnen | **keine einzige** | 185.84.108.20:443 |
|
||
| Meldung 3338 „Downloading latest HK" | nie | ja |
|
||
| `_private_data.tar` | 2048 B, **0** Schlüssel | 6,4 MB, **604** Schlüssel |
|
||
| Disc | „volume key is unknown" | **geht auf** |
|
||
|
||
Gegengeprüft mit leerem UND gefülltem Speicher, mit und ohne `--noscan`,
|
||
mit `dev:/dev/sr0` und `disc:0`, mit gelöschter `update.conf`. Immer:
|
||
keine Verbindung. Die Meldungsvorlage „Downloading latest %1 to %2 ..."
|
||
steckt sehr wohl im Linux-Binary — sie löst nur nie aus. Gleiches
|
||
Symptom im MakeMKV-Forum, seit Jahren offen (t=25782, t=34022).
|
||
- **⚠️ Richtigstellung zu v3.10 (direkt darunter):** Dort steht, MakeMKVs
|
||
Schlüssel-Kanal sei abgeschaltet. **Das war falsch.** Die Herleitung
|
||
stützte sich auf zwei Hostnamen aus alten Forumsbeiträgen
|
||
(`hkdata.fairuse.org`, `hkdata.crabdance.com`), die tatsächlich nicht
|
||
mehr auflösen — MakeMKV benutzt sie aber längst nicht mehr. **Der Dienst
|
||
lebt, der Worker erreicht ihn sogar** (Verbindungstest auf
|
||
185.84.108.20:443 erfolgreich); er wird unter Linux nur nie gefragt.
|
||
Aufgedeckt hat das der Commander mit dem Einwand, unter Windows ginge es
|
||
sofort. Alles in v3.10 Gebaute bleibt richtig und nötig — nur die
|
||
`KEYDB.cfg` ist nicht der Haupt-, sondern der Ersatzweg.
|
||
- **Gebaut — Schlüsselspeicher übernehmbar:** `GET`/`POST
|
||
/system/keystore` plus die Helfer in `makemkv_daten.py` (beide
|
||
Zwillinge). Der Rohkörper der Anfrage IST die Datei — binär, deshalb
|
||
kein JSON und kein Base64. Die Prüfung lehnt einen Speicher **ohne**
|
||
`hkd_*.bin` ab, sonst lädt jemand den leeren Vorrat einer frischen
|
||
Installation hoch und wundert sich, dass nichts passiert.
|
||
- **Gebaut — UI:** neuer Block „Disc-Schlüssel für 4K-UHD" **über** dem
|
||
KEYDB-Block, mit Schlüssel-Anzahl, Upload und der Schritt-für-Schritt-
|
||
Anleitung für den Windows-Umweg. KEYDB.cfg ist jetzt als **Notnagel**
|
||
beschriftet. Die Worker-Plakette zeigt die Anzahl bekannter Schlüssel;
|
||
`0` heißt sichtbar „4K-UHD scheitert".
|
||
- **Gebaut — ehrliche Texte:** Der UHD-Fehlertext nennt jetzt den
|
||
Windows-Weg und die Anzahl der Schlüssel dieses Workers. Alle
|
||
Falschaussagen korrigiert: UI (3 Stellen), Anleitung (2), README (3),
|
||
KONZEPT §8 + §10, Modulkopf von `makemkv_daten.py`, Worker-Dockerfile
|
||
und `makemkv_key.py` (dort stand: „Den AACS-Schlüssel zieht MakeMKV via
|
||
LibreDrive ohnehin selbst aus dem Laufwerk" — gilt für Blu-ray, NICHT
|
||
für UHD).
|
||
- **So hältst du den Vorrat aktuell:** Laufwerk an den Windows-PC, Disc in
|
||
MakeMKV öffnen, dann `_private_data.tar` aus dem MakeMKV-Datenverzeichnis
|
||
(*Preferences → General*) unter Einstellungen → System hochladen. Der
|
||
Speicher der Windows-Installation liegt bereits auf der VM unter
|
||
`/srv/rippy/makemkv/`.
|
||
- **Offen:** Der volle UHD-Rip inklusive Transcode-E2E ist noch nicht
|
||
durch — belegt ist der Disc-Zugriff, nicht die komplette Kette bis zur
|
||
fertigen Datei. Und ob sich der Abruf unter Linux doch anstoßen lässt,
|
||
ist ungeklärt; der Code dafür ist im Binary vorhanden.
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.10 — 4K-UHD: KEYDB.cfg statt Warten auf MakeMKV (25.07.2026)
|
||
|
||
- **Der Befund (am 25.07. live auf der VM im Worker-Container
|
||
nachgemessen — kein Verdacht, alles belegt):** Eine 4K-UHD (Akira,
|
||
MKB v76, Pressung Dezember 2020) scheitert mit „The volume key is
|
||
unknown for this disc". **Laufwerk und MakeMKV sind dabei in Ordnung:**
|
||
makemkvcon meldet „Using LibreDrive mode (v06.3)" und „Using direct
|
||
disc access mode", liest die Disc und legt den AACS-Dump ab
|
||
(Meldung 3332). Der Fehler liegt also NICHT an der Hardware.
|
||
- **Die echte Ursache — MakeMKV fragt gar nicht erst:** Das Debug-Log
|
||
geht ohne einen einzigen Netz-Versuch von „Loaded content hash table"
|
||
direkt auf „The volume key is unknown". **Beweise:**
|
||
`/root/.MakeMKV/_private_data.tar` enthielt nur die Index-Datei und
|
||
KEINE einzige `hkd_*.bin` — es wurde also nie ein Schlüssel geladen.
|
||
Auch mit erzwungener frischer Prüfung (`update.conf` gelöscht,
|
||
Meldung 5074 belegt den Web-Kontakt) und mit `app_UpdateEnable = "1"`
|
||
kam keiner. Und die im MakeMKV-Forum dokumentierten Schlüssel-Server
|
||
`hkdata.fairuse.org` und `hkdata.crabdance.com` lösen weltweit nicht
|
||
mehr auf (NXDOMAIN gegen Fritz!Box, 8.8.8.8 und 1.1.1.1).
|
||
- **Richtigstellung zu v3.3 (weiter unten korrigiert):** Dort stand, die
|
||
Ursache sei „Disc neuer als MakeMKVs Schlüssel-DB" und ein
|
||
MakeMKV-Update werde das lösen. Das ist widerlegt — es gibt keine
|
||
nachladbare Schlüssel-Datenbank mehr. **Warten auf ein MakeMKV-Update
|
||
hilft bei diesem Fehler nicht.**
|
||
- **Der einzige Weg, der heute funktioniert: `KEYDB.cfg`** — GROSS
|
||
geschrieben (unter Linux case-sensitiv) im MakeMKV-Datenverzeichnis.
|
||
Rippy macht diesen Weg jetzt begehbar, statt auf MakeMKV zu warten.
|
||
- **Gebaut — persistentes Datenverzeichnis:** `docker-compose.yml` mountet
|
||
`${MAKEMKV_DATA_HOST:-/srv/rippy/makemkv}` vom Host — im Worker auf
|
||
`/root/.MakeMKV`, in der API auf `/app/makemkv-data`; beide Container
|
||
bekommen `MAKEMKV_DATA_DIR`. Damit überleben `KEYDB.cfg` und die
|
||
AACS-Dumps jeden Rebuild. `entrypoint.sh` schreibt `settings.conf`
|
||
jetzt ergänzend statt zerstörend (sonst hätte der Beta-Key den Rest
|
||
überbügelt) und setzt `app_UpdateEnable = "1"`.
|
||
- **Gebaut — eine einzige Wahrheit über das Verzeichnis:** neues
|
||
Zwillings-Modul `makemkv_daten.py` (identisch in `docker/api/` und
|
||
`docker/worker/`) mit reinen Helfern — Status lesen, Inhalt prüfen,
|
||
atomar schreiben, löschen, AACS-Dumps auflisten. Nur reine Funktionen,
|
||
damit die Ampel sie ohne Postgres/Redis testen kann.
|
||
- **Gebaut — Bedienung im UI:** Einstellungen → System zeigt den
|
||
`KEYDB.cfg`-Status (Pfad, Größe, Anzahl Disc-Einträge, Datum), nimmt die
|
||
Datei über einen ganz normalen Datei-Dialog entgegen (der Browser liest
|
||
sie und schickt den Text als JSON — serverseitig bewusst KEIN
|
||
Multipart-Upload, es gibt kein `python-multipart`, das würde die API
|
||
beim Import töten), lehnt
|
||
unplausiblen Inhalt mit deutschem Klartext ab, kann die Datei wieder
|
||
entfernen und die AACS-Dumps zum Download anbieten.
|
||
- **Gebaut — man sieht endlich, was MakeMKV sagt:** `parse_msg()` in
|
||
`ripping.py` plus Log-Callback in `tasks.py` schreiben MakeMKV-Meldungen
|
||
ins Rippy-Log (gedrosselt: Code 1003 raus, keine Wiederholungen, max. 40
|
||
je Rip). Der UHD-Fehlertext ist ehrlich neu geschrieben. `caps.py`
|
||
meldet zusätzlich `keydb: ja | nein | unbekannt` je Worker.
|
||
- **Abgrenzung, die überall durchscheint:** **Rippy liefert KEINE
|
||
Schlüssel mit, lädt keine herunter und verteilt keine.** Rippy stellt
|
||
nur den Platz für eine Datei bereit, die der Nutzer selbst mitbringt,
|
||
und zeigt ehrlich an, was dort liegt. Genau die Grenze zieht schon
|
||
`docker/api/makemkv_key.py` (Zeile 14) für den Beta-Key: das ist die
|
||
Software-LIZENZ, nicht das Entschlüsseln oder Verteilen von
|
||
Disc-Schlüsseln.
|
||
- **⚠️ NOCH NICHT end-to-end bewiesen — ehrlich gesagt:** Zum Zeitpunkt
|
||
dieser Änderung lag KEINE `KEYDB.cfg` vor, die den Akira-Schlüssel
|
||
enthält. Belegt sind der Befund oben und die neue Mechanik (Mount,
|
||
Modul, Endpunkte, UI) — **nicht** ein erfolgreicher UHD-Rip. Der
|
||
Nachweis steht aus und braucht eine echte Schlüssel-Datei.
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.9 — Windows-Installer als echte .exe (Icon, kein Konsolenfenster) (24.07.2026)
|
||
|
||
- **RippyWorkerSetup.exe** ersetzt den .vbs/.bat-Weg (Commander-Einwand:
|
||
.vbs ist abgekündigt + wird als gefährlich geflaggt). install-gui.ps1 via
|
||
ps2exe kompiliert: eingebettetes Rippy-Disc-Icon, KEIN Konsolenfenster
|
||
(-noConsole), WinForms (-STA). Vorgebaut auf Windows
|
||
(deploy/worker-windows/build-exe.ps1) + committet — Windows-.exe geht
|
||
nicht von Linux (Rippy-Host). API: GET /worker-setup/windows-exe.
|
||
UI (Worker → Windows): „Installer herunterladen (.exe)" als Haupt-Weg.
|
||
**E2E bewiesen**: von der VM geladen → Fenster öffnet, conhost-Zähler
|
||
unverändert (kein Konsolenfenster), Icon eingebettet.
|
||
- **Wichtig — friert nichts ein**: Die .exe holt HandBrake zur Laufzeit
|
||
(GitHub latest) und den Worker-Code live von Rippy. Nur bei Änderung der
|
||
GUI (install-gui.ps1) neu bauen (build-exe.ps1), NICHT bei Tool-Updates.
|
||
- **Update-Story dokumentiert** (Commander-Frage): MakeMKV → .env-Bump +
|
||
Rebuild (Update-Check zeigt es); HandBrake Docker = Debian-stabil,
|
||
native Worker = latest beim Installieren.
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.8 — Grafischer Windows-Installer + Versionslage klar (24.07.2026)
|
||
|
||
- **Grafischer Windows-Installer** (statt CLI): install-gui.ps1 (WinForms,
|
||
ASCII-only) — Fenster mit Feldern (Rippy-IP, Worker-Name, Autostart) +
|
||
Install-Knopf mit Live-Log + „Worker starten". Gleiche Schritte wie der
|
||
CLI-Installer (Worker-Code, HandBrake latest, venv, Tray/Start/Uninstall).
|
||
UI (Worker → Windows): Knopf „Grafischen Installer herunterladen (.bat)" —
|
||
die .bat wird CLIENT-seitig mit der eingetragenen LAN-IP erzeugt,
|
||
Doppelklick lädt+startet die GUI von Rippy (GET /worker-setup/windows-gui).
|
||
CLI-Befehl bleibt als Profi-Alternative. Bewiesen: GUI-Fenster öffnet
|
||
sauber auf dem Commander-PC (Titel „Rippy Encoding-Worker - Installation").
|
||
- **Werkzeug-Versionslage exakt dargestellt** (Commander-Wunsch): System-Tab
|
||
erklärt jetzt klar — MakeMKV aktualisierbar (wichtig wegen Schlüssel-DB),
|
||
HandBrake im Docker-Worker bewusst Debian-stabil (1.6.1, KEIN Alarm mehr),
|
||
native Worker holen die neueste. Update-Check zeigt MakeMKV mit „✓ aktuell"
|
||
bzw. Update-Befehl, HandBrake neutral als Info.
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.7 — Drei Praxis-Bugs (Mounts, HandBrake, Encoder-Wahl) (24.07.2026)
|
||
|
||
Alle drei live auf der VM verifiziert:
|
||
- **Speicher-Mounts robust**: Ein toter CIFS-Mount (NAS weg/Rebuild) war
|
||
mounted:false, verschwand aus „Verfügbare Ziele" und ließ sich nicht neu
|
||
anlegen („Name existiert"). Jetzt: `reachable`-Status (bounded `timeout 3
|
||
ls` — Endpoint lädt in 0,014 s statt 10 s), `umount -l`-Fallback,
|
||
`reparieren()` (lazy abhängen + frisch mounten), Re-Add repariert statt
|
||
409, POST /storage-mounts/{name}/repair, eigene „Netzwerk-Mounts"-Liste im
|
||
UI mit Status + Reparieren/Entfernen. Bewiesen: Reparatur des `rippy`-
|
||
Mounts → mounted:true, writable:true.
|
||
- **HandBrake-Versionen konsistent**: Windows-Installer zieht dynamisch die
|
||
neueste (GitHub latest) — bewiesen: HandBrake 1.11.2 installiert (statt
|
||
fest 1.9.2). Update-UI erklärt: Docker = Debian-stabil (bewusst älter),
|
||
Windows = neueste. Nebenbei ein latenter Installer-Bug gefixt: PowerShell
|
||
5.1 liest .ps1 als ANSI — ein Gedankenstrich zerschoss das Skript →
|
||
install.ps1 ist jetzt ASCII-only.
|
||
- **Encoder-/Worker-Wahl beim Rip**: Celery `worker_direct=True`, gezieltes
|
||
Routing (transcode_queue) mit sicherem Fallback auf die geteilte Queue.
|
||
Bewiesen mit ping_worker: Task landet exakt beim gewählten Node. Dropdown
|
||
im Rip-Dialog ab 2 Online-Workern. Node-Zuordnung disambiguiert bei
|
||
mehreren Workern pro Host. Nebenfund gefixt: DeviceDiscovery leitete die
|
||
Titel-Auswahl (titles) gar nicht weiter.
|
||
⚠️ Gezieltes Routing braucht AKTUELLEN Worker-Code (worker_direct) — ein
|
||
vor dieser Version installierter Remote-Worker pingt zwar, konsumiert aber
|
||
seine Direkt-Queue nicht → neu installieren.
|
||
- **Voller Transcode-E2E weiterhin durch die UHD-Key-Lage blockiert** (keine
|
||
entschlüsselbare Disc) — die Routing-Mechanik ist per ping_worker bewiesen.
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.6 — Design 2.0 gelandet + Ein-Branch-Umstellung (24.07.2026)
|
||
|
||
- **Design 2.0 ist in `main`** (von Gemini umgesetzt): UI von 428
|
||
`theme === 'dark'`-Ternaries auf Tailwind-`dark:` + UI-Primitives
|
||
(`components/ui/`, `lib/design.ts`) umgebaut, „Cinematic Cinema OS"-Look.
|
||
Ampel grün (49 Tests, Ruff, Vite-Build), Live auf der VM.
|
||
- **Nur noch EIN Branch: `main`** (Commander-Entscheid). Der
|
||
`stable`-Zwischenbranch samt Grün-Gate ist abgeschafft — er war
|
||
vestigial, weil die VM ohnehin aus `main` deployt. Konsequenzen:
|
||
- ci.yml: Beförderungs-Schritt raus, die Ampel PRÜFT nur noch.
|
||
- deploy.sh: nutzt `main` statt `stable`.
|
||
- AGENTS §C / README / DESIGN-Briefing entsprechend umgeschrieben.
|
||
- Gelöschte Branches: `stable`, `design-2.0` (gemergt), `kernumbau-2026-07-23` (alt).
|
||
- **Deploy-Weg ab jetzt:** push → Ampel grün prüfen → auf der VM
|
||
`git pull` (in ~/projects/rippy) bzw. `./deploy.sh`.
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.5 — Track-Tabelle, nativer Windows-Worker, Anleitungs-Tab (24.07.2026, Claude)
|
||
|
||
- **Volle Titel-Auswahl vor dem Rip**: „Disc scannen" im Rip-Dialog →
|
||
Worker-Task scan_tracks (makemkvcon info; Ergebnis via settings-Tabelle
|
||
'tracks:<device>', UI pollt) → Tabelle mit Checkbox/Dauer/Größe/Kapiteln,
|
||
Vorauswahl ab 5 min. Gewählte Titel gehen als meta.titles in den Job;
|
||
der Worker rippt sie einzeln (makemkvcon kann pro Aufruf nur einen Titel
|
||
oder all), Fortschritt anteilig. Parser mit Tests (apdefs-Attr 8/9/11).
|
||
- **Nativer Windows-Worker (ohne Docker!)**: Einstellungen → Worker bietet
|
||
jetzt ZWEI Varianten — Linux (Docker, wie gehabt) und Windows (nativ,
|
||
braucht nur Python). Die Rippy-Instanz versorgt sich selbst:
|
||
GET /worker-setup/windows liefert install.ps1, /worker-setup/paket den
|
||
Worker-Code als Zip (beides liegt via api-Dockerfile im Image).
|
||
install.ps1: venv + Abhängigkeiten, HandBrakeCLI 1.9.2 vom offiziellen
|
||
GitHub-Release (URL verifiziert), start-worker.bat (celery -Q transcode
|
||
--pool=solo), optional -Autostart (schtasks onlogon). tasks.py lädt auf
|
||
Windows ohne fcntl (Import-Guard); rip_disc ist dort hart verriegelt.
|
||
Für echte Transcodes übersetzt RIPPY_PATH_MAP die Container-Pfade aufs
|
||
Netzlaufwerk (pfad_lokal, mit Tests) — Voraussetzung bleibt eine
|
||
Freigabe der Rippy-Ablage (derselbe offene Infra-Punkt wie beim
|
||
Linux-Remote-Worker/AI-Box).
|
||
**E2E-BEWEIS (24.07., Commander-PC):** Installer in einem Rutsch
|
||
durchgelaufen (venv, Abhängigkeiten, HandBrakeCLI 1.9.2), Worker
|
||
gestartet und in Rippy erschienen:
|
||
`test-windows-nativ | online: True | HandBrake: 1.9.2 | IP: 192.168.178.98`
|
||
— echte LAN-IP, Celery-Ping grün. Testeintrag danach wieder entfernt.
|
||
- **Tray-Symbol + rückstandsfreie Deinstallation (v3.5.1, bewiesen):**
|
||
tray.py (pystray/Pillow, nur Windows-Worker) — Disc-Symbol neben der
|
||
Uhr mit Status, Start/Stopp, „Rippy öffnen", Log, Beenden; Celery läuft
|
||
als Kind ohne Konsolenfenster. install.ps1 erzeugt start-tray.bat
|
||
(empfohlen), start-worker.bat (Debug) und uninstall.ps1. **E2E bewiesen
|
||
auf dem Commander-PC:** Frisch installiert → Tray + celery-Kind liefen →
|
||
`tray-test` online in Rippy → uninstall.ps1 -Force stoppte alle
|
||
Prozesse, meldete den Worker per DELETE /workers/{name} ab und löschte
|
||
den Ordner restlos (danach: 0 Prozesse, Ordner weg, in Rippy nur noch
|
||
rippy-hauptworker).
|
||
- **Anleitungs-Tab** im UI: kompletter Selbsterklärer (Disc-Weg, Serien,
|
||
NAS, Media-Server, Benachrichtigungen, Key, Worker, Downloads, FAQ).
|
||
- Design 2.0 kommt bewusst in eine FRISCHE Session (Commander-Entscheid) —
|
||
Infrastruktur steht (darkMode 'class'), reine Konvertierungsarbeit.
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.4 — Restefeger: der Ideen-Katalog ist abgearbeitet (24.07.2026, Claude)
|
||
|
||
**Commander-Entscheid: AUTH IST KOMPLETT RAUS** (Heimnetz-only; das UI hatte
|
||
nie einen Login, die Endpoints waren Placebo, passlib/bcrypt brach die Ampel).
|
||
/token + /api-keys + auth.py + Abhängigkeiten entfernt, JWT_SECRET_KEY ist
|
||
keine Pflicht mehr — der Schnellstart läuft ohne .env-Zwang. KONZEPT §10.
|
||
|
||
**Neu in v3.4 (Details in ROADMAP Etappe 15):**
|
||
- **Serien-Flow**: Rip-Dialog fragt Serienname + Staffel → Ablage
|
||
`<Serie>/Season NN`, tvshow.nfo/poster im Serien-Ordner, und die
|
||
**Episoden werden per Laufzeitabgleich (TMDB) erkannt und benannt**
|
||
(„Serie S01E02.mkv") — nur bei eindeutiger Zuordnung, sonst ehrliches Log.
|
||
Komplette Staffel auf einer Disc klappt auch bei uniformen Anime-Laufzeiten.
|
||
- **Jellyfin/Emby-Refresh** nach jedem fertigen Rip (URL/API-Key +
|
||
Test-Knopf in Einstellungen → Ripping) — Disc rein, Film erscheint im
|
||
Server, null Klicks dazwischen.
|
||
- **Duplikat-Warnung** per Disc-Fingerabdruck (Karte zeigt „bereits
|
||
gerippt", Vollautomatik überspringt).
|
||
- **„Nur Hauptfilm" funktioniert jetzt wirklich** (Info-Lauf → längster
|
||
Titel; pro Rip im Dialog wählbar). Vorher wirkungsloses Setting.
|
||
- **OMDb-Treffer werden eingedeutscht** (TMDB /find über die IMDb-ID).
|
||
- Dashboard: **Speicherplatz-Anzeige** (amber < 60 GB) + **CSV-Export**.
|
||
- **Metadaten-Seite entfernt** (Korrektur-Popup ist der einzige Weg) samt
|
||
Placebo-Endpoints; Doppel-Jahr „(2009) (2009)" gefixt.
|
||
- **Remote-Worker-Blocker behoben**: redis/postgres waren NIE veröffentlicht
|
||
— Ports 6379/5432 jetzt offen, API_URL für Worker gesetzt. Damit sind
|
||
AI-Box/Windows-Worker überhaupt erst anschließbar.
|
||
|
||
**Bewusst offen** (ROADMAP „Ideen-Katalog (Rest)"): volle Track-Tabelle,
|
||
nativer Windows-Worker (braucht Testlauf auf Ziel-Hardware), Design-2.0-
|
||
Konvertierung (Infrastruktur steht), AI-Box-NFS-Export, Kodi-Refresh.
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.3 — Praxis-Feedback-Runde (24.07.2026, Claude)
|
||
|
||
**Zwei echte Bugs mit Beweis gefixt:**
|
||
1. **SMB-Mount „Unable to apply new capability set"**: mount.cifs hebt
|
||
CAP_DAC_READ_SEARCH an — die fehlt in Dockers Default-Caps. Auf der VM
|
||
reproduziert (Bounding-Set a82425fb, Bit 2 fehlt) und mit
|
||
`cap_add: DAC_READ_SEARCH` bewiesen behoben (docker-compose.yml).
|
||
2. **TMDB fiel still aus**: Der Client konnte nur v4-Bearer-Tokens — der
|
||
eingetragene übliche v3-Key (32 Hex) bekam still 401, Suche lieferte nur
|
||
OMDb. Jetzt beide Key-Arten (ist_v4_token, mit Tests); Einstellungen →
|
||
APIs hat „Verbindung prüfen" mit Live-Status je Quelle (am Cache vorbei).
|
||
|
||
**Neu in v3.3:**
|
||
- **4K UHD als eigener Disc-Typ** (classify ≥ 55 GiB, beide detection.py,
|
||
Tests): eigene Badge-Farbe überall, Prescan-Label „4K UHD".
|
||
- **UHD-Kette diagnostiziert (Nachtrag, gleicher Tag): Der BU40N-Flash IST
|
||
erledigt** — makemkvcon meldet „Using LibreDrive mode (v06.3)". Der
|
||
Summer-Wars-Fehlschlag lag NICHT am Laufwerk, sondern an „The volume key
|
||
is unknown" — auf der VM mit 1.17.7 UND der aktuellsten 1.18.4
|
||
reproduziert. Konsequenzen:
|
||
MakeMKV auf **1.18.4** gehoben (Scan-Hänger durch überall genutztes
|
||
--noscan umgangen, auf der BU40N sauber gelaufen; URL-Base → /download),
|
||
run_makemkv reicht kritische Meldungen (volume key/Key abgelaufen) in
|
||
den Fehlertext durch, UHD-Klartext unterscheidet jetzt „Laufwerk kann
|
||
kein UHD" von „Disc-Schlüssel fehlt" inkl. Forum-Dump-Hinweis
|
||
(MakeMKV speichert den AACS-Dump automatisch unter /root/.MakeMKV/).
|
||
**⚠️ Korrigiert am 25.07.2026 (siehe v3.10 ganz oben):** Die hier
|
||
ursprünglich genannte Erklärung „die Disc ist neuer als MakeMKVs
|
||
Schlüssel-DB, ein MakeMKV-Update löst das" ist FALSCH. Nachgemessen:
|
||
MakeMKV hat gar keine nachladbare Schlüssel-DB mehr und versucht auch
|
||
keinen Online-Abruf; die alten Schlüssel-Server sind tot. Der Weg zum
|
||
Ziel heißt `KEYDB.cfg`, nicht „warten auf die nächste Version".
|
||
- **Vollautomatik** (Einstellungen → Ripping): Disc erkannt → Rip startet
|
||
ohne Popup in den passenden Schnellwahl-Ordner (Serie/Film/Musik).
|
||
- **Job-Verwaltung**: „Neu komprimieren" nur noch, wenn Rohdaten wirklich
|
||
daliegen (can_retry); Jobs einzeln löschbar (Papierkorb) + „Erledigte
|
||
aufräumen" mit Bestätigungs-Dialog — Dateien bleiben immer liegen.
|
||
- **„Alle herunterladen"** im Job-Detail (gestaffelte Einzel-Downloads —
|
||
bewusst kein Server-seitiges 40-GB-Zip).
|
||
- **Worker zuordenbar**: WORKER_NAME-Env als stabiler Anzeigename (compose:
|
||
rippy-hauptworker; Remote-Worker: frei wählbar) — fixt zugleich die
|
||
Offline-Leichen nach Rebuilds; IP + Container-ID werden mit angezeigt,
|
||
verwaiste Einträge sind löschbar (DELETE /workers/{name}). Online-Abgleich
|
||
läuft jetzt über info.hostname.
|
||
- **Disc-Karte**: „Quelle: TMDB/OMDb/MyAnimeList · xx % sicher" statt des
|
||
nackten „Übereinstimmung xx %"; TMDB-Metadaten sind Deutsch (language=
|
||
de-DE war schon überall dran — sie kamen nur nie an, siehe Key-Bug).
|
||
- **Ripping-Tab nach Medium** gegliedert (Video / Audio-CD / Allgemein) +
|
||
Klartext: alle Tonspuren & Untertitel bleiben erhalten (--all-audio/
|
||
--all-subtitles) — wichtig für Anime.
|
||
- **Ordner-Verwaltung** (Ex-„Dateibrowser") ist jetzt beschriftet, erklärt
|
||
und standardmäßig eingeklappt.
|
||
- **Docker-Pflicht beim Worker**: ehrlich im UI beantwortet; nativer
|
||
Windows-Dienst steht als Ausbaustufe in der ROADMAP (Ideen-Katalog).
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.2 — Universal-Komfort-Runde + Ampel entrostet (24.07.2026, Claude)
|
||
|
||
**Wichtigster Befund zuerst: die Ampel war seit dem 23.07. ROT und `stable`
|
||
hing 10 Commits hinter `main`** — deshalb kam nichts Neues mehr auf die VM.
|
||
Zwei Ursachen, beide behoben:
|
||
1. bcrypt ≥ 4.1 bricht passlib 1.7.4 (`__about__` entfernt → Selbsttest wirft
|
||
„password cannot be longer than 72 bytes") → **bcrypt==4.0.1 gepinnt**.
|
||
2. Der cache_keys-Test kannte den Disc-Fingerprint im Prescan-Key (23.07.)
|
||
nicht → Test an das echte Format angepasst + Fingerprint-Testfall dazu.
|
||
|
||
**Neu in v3.2 (Commander-Sammelauftrag, alles mit Tests / Vite-Build grün):**
|
||
- **Media-Server-Integration**: Setting `mediaServer` (Wizard + Einstellungen →
|
||
Ripping): Zielordner „Titel (Jahr)" statt Job-UUID; für Jellyfin/Emby/Kodi
|
||
zusätzlich movie.nfo/tvshow.nfo + poster.jpg (Worker: medien.py). Plex = nur
|
||
Benennung. Job speichert Disc-Metadaten jetzt mit (jobs.meta, Migration).
|
||
- **Benachrichtigungen ECHT**: notify.py in API+Worker (Discord/Slack/ntfy/
|
||
generisch, Erkennung an der URL) — das Feld war vorher ein Placebo. Meldung
|
||
bei fertig/fehlgeschlagen/abgebrochen; Anleitung + „Test senden" im UI.
|
||
- **SMB-Scan-Fix**: „NT_STATUS_ACCESS_DENIED" heißt jetzt im Klartext „Gast-
|
||
Abfrage verweigert → Benutzer/Passwort eintragen"; Credential-Felder stehen
|
||
im UI VOR dem Auflisten-Knopf. NAS-Ziel-Anlage quittiert per Toast.
|
||
- **4K-UHD-Vorsorge**: Arbeitsverzeichnis `workDir` konfigurierbar (auf
|
||
NAS-Freigabe legbar), Platz-Check per Disc-Größe (ioctl) VOR dem Rip mit
|
||
Klartext-Abbruch statt voller Platte bei 40 GB.
|
||
- **Einstellungen → System**: Werkzeug-Versionen je Worker (MakeMKV/HandBrake,
|
||
ENV MAKEMKV_VERSION im Image), Key-Quelle (ui/env/keiner), freier Platz;
|
||
**MakeMKV-Beta-Key im UI pflegbar** — gilt ab dem nächsten Rip, ohne Rebuild.
|
||
- **Job-Detail-Popup** (Klick auf Titel in „Neueste Jobs"): Poster, Jahr,
|
||
Beschreibung, Genres, Ablagepfad, Fehler (GET /jobs/{id}/detail).
|
||
- **Download fertiger Rips im Browser**: „Download"-Knopf bei fertigen Jobs
|
||
(Aktion-Spalte) → Dateiliste mit Größen im Detail-Popup, Stream via
|
||
GET /jobs/{id}/files/{name} (Pfad-Validierung strikt unter /app/media,
|
||
realpath-Check gegen Symlink-Ausbrüche) — vorher nur per scp erreichbar.
|
||
- **UI-Feedback**: Toast-System (ToastContext, ploppt oben rechts), drehende
|
||
Refresh-Knöpfe, Logs-Pills um Warnung/Fehler ergänzt, Datei-Browser zeigt
|
||
jetzt auch DATEIEN (grau, mit Größe) — der „leere" Bluray-Ordner war voll.
|
||
- **Favicon** (Disc, Indigo-Verlauf) + **Footer** „Created with ❤️ by LucyAI,
|
||
Claude and KrBrZ".
|
||
- **Doku**: README (Media-Server, Benachrichtigungen, UHD-Arbeitsverzeichnis,
|
||
„Rippy woanders bereitstellen"), ROADMAP Etappe 13 + Ideen-Katalog,
|
||
KONZEPT-Fortschreibungen (Abschnitt 10), AGENTS-Stand.
|
||
|
||
**Nächste Schritte:** unverändert die Fäden aus v3.1 (unten) + Ideen-Katalog
|
||
in der ROADMAP (Serien-Flow, Duplikat-Warnung, Jellyfin-Refresh, Auth).
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.1 — E2E BEWIESEN + Universal-Runde (24.07.2026, Claude)
|
||
|
||
**Der Beweis steht: Evangelion 2.22 (BD-50) komplett durch die Kette** —
|
||
erkannt → verlustfrei gerippt (43 GB, LibreDrive) → H.264-komprimiert →
|
||
**4,8 GB Endergebnis** (Hauptfilm 3,3 GB + 4 Extras), Rohdaten automatisch
|
||
gelöscht. Retry-transcode dabei live bewiesen (x265 war auf 4 vCPUs zu lahm
|
||
→ Abbruch + Neustart mit H.264 OHNE Neu-Rip).
|
||
|
||
Seit v3.0 dazugekommen (alles deployt, Ampel grün):
|
||
- **Korrektur-Flow**: „Nicht korrekt?!"-Popup an der Disc-Karte; Suche über
|
||
alle Quellen (GET /metadata/search), Wahl wird 30 Tage per
|
||
Disc-Fingerabdruck gemerkt (POST /metadata/override)
|
||
- **Metadaten-Kette**: BD-Klartext-Titel via ro-Mount (bdmt_*.xml),
|
||
Jikan/MAL (keyless, Ähnlichkeits-Score), OMDb-Qualitäts-Gate,
|
||
Wort-Strip-Degradation, ehrliches Cache-TTL (unknown nie cachen)
|
||
- **Worker-Verwaltung** (Einstellungen → Worker): Live-Erreichbarkeit
|
||
(Celery-Ping + Minuten-Herzschlag), Copy-Paste-Anbindung neuer Maschinen
|
||
- **Speicherziele**: SMB-Freigaben-Auflistung, Schreibtest beim Mount,
|
||
lokaler Ordner-Browser + mkdir; Mounts via UI (CAP_SYS_ADMIN + rshared)
|
||
- **First-Run-Wizard**, Job-Abbruch (kooperativ), Transcode als eigener
|
||
Task auf Queue `transcode` (Basis Remote-GPU-Worker), ruff.toml gepinnt
|
||
|
||
**Nächste Schritte:** AI-Box als VAAPI-Transcode-Worker (VCN4; NFS-Export
|
||
nötig, deploy/remote-transcode-worker.yml) · TMDB-Key eintragen ·
|
||
Arcane-GitSync-Binding auf `stable` (aktuell Notfall-Deploy-Weg) ·
|
||
Metadaten-Seite entfernen, wenn Popup abgenommen · Jellyfin-Postprocessing
|
||
an Worker · Auth vor schreibende Endpoints · MAKEMKV_APP_KEY erneuern
|
||
(~Ende Juli, Forum t=1053).
|
||
|
||
---
|
||
|
||
## Vorheriger Stand: v3.0 — Kernumbau (23.07.2026, Claude)
|
||
|
||
**Der Zweck existiert jetzt wirklich.** Komplett-Audit ergab: „Disc rein →
|
||
gerippt raus" hatte nie einen Code-Pfad (Details in ROADMAP Etappe 11).
|
||
|
||
Kernpunkte des Umbaus:
|
||
- **Rip-Kette komplett neu**: POST /jobs → Celery → Worker (MakeMKV 1.18.4
|
||
verlustfrei, Etappe 10) → Postgres-Job-Status → UI. CD weiter via abcde.
|
||
- **Disc-Erkennung** über Kernel-ioctls (CDROM_DISC_STATUS + Größe), Watcher
|
||
pollt statt udev (im Container gibt es kein udev).
|
||
- **UI**: echter Vite-Build hinter nginx mit /api-Proxy — vorher Dev-Server
|
||
und hartkodiertes localhost:8000 (deshalb waren nie Laufwerke zu sehen).
|
||
- **Compose**: Laufwerk als devices: (Bind-Mounts gaben EPERM), Ausgabe auf
|
||
media-Volume (vorher /output → nicht gemountet + read-only-Falle).
|
||
- **Placebos entfernt**: Mock-Logs, toter SSE-Stream, udevadm-Discovery,
|
||
14 Troubleshooting-Altdateien (ARCAN-*.md, Setup-Skripte, udev-Rules).
|
||
|
||
**Hardware-Kette (23.07.):** Laufwerk (Verbatim 4K BD RW, BU40N 1.05) hängt am
|
||
Proxmox-Host; LPM-Quirk `usbcore.quirks=18a5:0428:k` gefixt die Serien-Disconnects
|
||
(reboot-fest in GRUB). VM 106 bekommt es per USB-Passthrough `host=18a5:0428`.
|
||
⚠️ Firmware 1.05 kann KEIN UHD-Ripping (verschlüsselt) — Crossflash auf 1.03-MK
|
||
ist der dokumentierte Weg, separater Faden. DVD/BD normal geht.
|
||
|
||
**Offen:** E2E mit echter Disc · Jellyfin-Post-Processing an Worker anbinden ·
|
||
Auth vor schreibende Endpoints · MAKEMKV_APP_KEY in Arcane-Env pflegen (monatlich).
|
||
|
||
---
|
||
|
||
## Vorheriger Stand
|
||
|
||
**v1.10 — Complete Dark Mode Implementation (22.07.2026)**
|
||
|
||
Rippy läuft auf Arcane VM (192.168.178.162):
|
||
- ✅ Arcane WebUI: http://192.168.178.162:3552
|
||
- ✅ Rippy UI: http://192.168.178.162:80
|
||
- ✅ Rippy API: http://192.168.178.162:8000
|
||
- ✅ Theme Context ausgelagert (App.tsx → ThemeContext.tsx + useDarkMode.ts)
|
||
- ✅ Config Validation mit TMDB-API-Key Pflicht
|
||
- ✅ Cache Key Centralization (cache/keys.py)
|
||
- ✅ Dark Mode mit Theme-Toggle und localStorage persistence (UI-Only)
|
||
- ✅ **Alle UI-Komponenten komplett auf Dark Mode aktualisiert:**
|
||
- `App.tsx`, `Dashboard.tsx`, `Settings.tsx`, `MetadataPreview.tsx`
|
||
- ✅ Sidebar Navigation mit Dark Mode Support
|
||
- ✅ Einstellungen-Page mit Tab-Struktur
|
||
- ✅ Doppelte Arcane-Einträge behoben (`rippy` statt `Rippy`)
|
||
- ✅ Import-Fixes (relative → absolute Imports)
|
||
- ✅ Git Sync in Arcane konfiguriert
|
||
- ✅ Commit: `d2fb281` — Complete Dark Mode Implementation
|
||
|
||
### Docker-Container
|
||
|
||
| Container | Port | Status |
|
||
|-----------|------|--------|
|
||
| rippy-api | 8000 | Healthy |
|
||
| rippy-worker | - | Running |
|
||
| rippy-ui | 80 | Running |
|
||
| rippy-postgres | 5432 | Healthy |
|
||
| rippy-redis | 6379 | Healthy |
|
||
|
||
### Features
|
||
|
||
- ✅ **Etappe 3**: SQLite-Cache, TMDB/MusicBrainz/TheTVDB Clients, Pre-Scan, Metadaten-Preview
|
||
- ✅ **Etappe 4**: Jellyfin-Formatierung (NFO-Generator, Image-Downloader)
|
||
- ✅ **Etappe 5**: JWT-Auth (15min/7T), Rate-Limiting (100/min), API-Key-Management
|
||
- ✅ **Etappe 6**: Docker read_only, tmpfs, healthchecks, minimale Images
|
||
- ✅ **Etappe 7**: API UI Modernisiert, Import-Fixes, Doppelte Einträge behoben
|
||
- ✅ **Etappe 8**: Dark Mode mit Theme-Toggle, Separation of Concerns
|
||
- ✅ **Etappe 9**: Complete Dark Mode Implementation (alle UI-Komponenten)
|
||
- ✅ **Dokumentation**: README, KONZEPT.md, ROADMAP.md, SAVEPOINT.md
|
||
|
||
### Nächste Schritte
|
||
|
||
- Job-Verlauf UI (aktuell nur leere Listen)
|
||
- TMDB API Schlüssel in Arcane Environment konfigurieren
|
||
- Proxmox LXC Template
|
||
- Ansible Playbooks
|
||
|
||
### SoC Refactoring — Abgeschlossen (Etappe 9)
|
||
|
||
- ✅ **Theme-Context**: Theme-Logik aus App.tsx ausgelagert
|
||
- ✅ **Dark Mode Utility**: useDarkMode Hook implementiert
|
||
- ✅ **Component-Struktur**: Dark Mode props von inneren Komponenten versteckt
|
||
- ✅ **Config Validation**: TMDB-API-Key ist Pflicht
|
||
- ✅ **Cache Key Centralization**: cache/keys.py erstellt
|
||
- ✅ **CD-Ripping**: abcde-Integration implementiert
|
||
|
||
### Git-Log
|
||
|
||
```
|
||
d2fb281 - fix: complete dark mode implementation with all UI components
|
||
43dfce5 - feat(ui): implement dark mode with theme toggle
|
||
rippy-ui-modern - UI Modernisiert & Import-Fixes
|
||
3d87c8c - Dokumentation aktualisiert
|
||
bdb9f8d - SAVEPOINT v1.5: Sicherheit abgeschlossen
|
||
efa642e - Etappe 6: Sicherheit
|
||
```
|
||
|
||
---
|
||
|
||
## v2.0 — Fix-Runde nach externem Code-Review (22.07.2026, Claude)
|
||
|
||
**Alle Befunde des Reviews behoben, echte Tests eingeführt, Ampel-CI aktiv.**
|
||
|
||
Gefixt:
|
||
- **Metadaten-Preview WIEDERHERGESTELLT**: Beim SoC-Refactoring hatte ein Stub-Paket
|
||
die echte prescan-Implementierung überschattet — die Preview lieferte immer
|
||
„Unknown Disc". Echte Logik liegt jetzt im Paket, tote Altmodule (cache.py,
|
||
prescan.py flach) gelöscht.
|
||
- Fortschrittsmeldung: Celery `update_state` statt Aufrufe eines nie existierenden
|
||
Tasks; `self.send_task` (erfundene API) entfernt.
|
||
- abcde-Kommando korrigiert (`-o` war doppelt → CD-Ripping war nie funktionsfähig);
|
||
Zielverzeichnis jetzt via OUTPUTDIR-Config; Kommando-Bau als testbare Funktion.
|
||
- JWT: fester Schlüssel PFLICHT (kein Zufalls-Fallback pro Prozess mehr);
|
||
Logout blacklistet wirklich; Cleanup löscht nur Abgelaufene (vorher: alles).
|
||
- main.py: crashende Endpoints repariert (fehlende Imports Path/secrets,
|
||
nicht existentes api_keys-Dict → ratelimit-Store), Audio-`year`-Bug,
|
||
Admin-Zugang aus .env statt hartkodiert.
|
||
- Ruff komplett grün (29 Funde), package-lock.json committet.
|
||
- Tests: test_auth, test_cache_keys, test_ripping_helpers (der giftige
|
||
test_health-Placebo ist raus).
|
||
|
||
## ✅ ENTSCHIEDEN (22.07. abends): Das KONZEPT gilt — MakeMKV kommt
|
||
|
||
**MakeMKV lossless (Muss-Feature) wird umgesetzt — als eigene Etappe 10 in der
|
||
ROADMAP** (Worker-Container + makemkvcon + Beta-Key, in Zed zu bauen, E2E mit
|
||
echter Disc). Bis dahin bleibt HandBrake als SICHTBARER Übergang aktiv — jede*r
|
||
weiß: aktuell wird transkodiert, nicht verlustfrei gesichert.
|
||
|
||
## Deploy-Weg seit 22.07. abends: GRÜN-GATE (vollautomatisch)
|
||
Push auf `main` → Ampel prüft → grün → CI befördert auf Branch `stable` →
|
||
**Arcane-GitSync zieht `stable` und deployt**. Rot deployt NIE. `./deploy.sh`
|
||
ist nur noch der Notfall-Hebel; SSH zur VM bleibt als Fallback erlaubt.
|