Files
rippy/ROADMAP.md
T
Hitonabi f449c4ee34
Ampel / ampel (push) Successful in 28s
fix(uhd): 4K-UHD geloest - makemkvcon holt Schluessel unter Linux nie
Richtigstellung des Vortags-Befunds. Dort stand, MakeMKVs Schluessel-Kanal
sei abgeschaltet. Das war FALSCH: die Herleitung stuetzte sich auf zwei
Hostnamen aus alten Forumsbeitraegen (hkdata.fairuse.org,
hkdata.crabdance.com), die zwar wirklich nicht mehr aufloesen, von MakeMKV
aber laengst nicht mehr benutzt werden. Aufgedeckt durch den Einwand des
Commanders, unter Windows ginge es sofort.

Gegenprobe mit demselben Laufwerk und derselben Disc (Akira UHD, MKB v76):

                        Linux (Worker)      Windows
  Verbindungen          KEINE EINZIGE       185.84.108.20:443
  Meldung 3338          nie                 "Downloading latest HK"
  _private_data.tar     2048 B, 0 Keys      6,4 MB, 604 Keys
  Disc                  volume key unknown  TCOUNT:5, geht auf

Gegengeprueft mit leerem UND gefuelltem Speicher, mit und ohne --noscan,
mit dev:/dev/sr0 und disc:0, mit geloeschter update.conf. Linux fragt nie.
Die Meldungsvorlage "Downloading latest %1 to %2 ..." steckt sehr wohl im
Linux-Binary - sie loest nur nicht aus. Gleiches Symptom im MakeMKV-Forum,
seit Jahren offen (t=25782, t=34022). Der Dienst lebt; der Worker erreicht
185.84.108.20:443 sogar problemlos.

BEWIESEN: Nach Uebernahme des Windows-Schluesselspeichers oeffnet
makemkvcon auf der VM die Akira-UHD - "Operation successfully completed",
TCOUNT:5, fuenf Titel, identisch zum Windows-Ergebnis. Erster belegter
UHD-Disc-Zugriff auf der Rippy-Maschine.

- makemkv_daten.py (beide Zwillinge): zaehle_schluessel,
  private_data_pruefen, schluesselspeicher_status, private_data_schreiben.
  Die Pruefung lehnt einen Speicher OHNE hkd_*.bin ab - sonst laedt jemand
  den leeren Vorrat einer frischen Installation hoch, nichts aendert sich,
  und niemand versteht warum. Modulkopf komplett neu, inkl. der
  Fehldiagnose als Warnung fuer spaeter.
- API: GET/POST /system/keystore. Der Rohkoerper der Anfrage IST die Datei
  (binaer - JSON/Base64 waere Ballast, Multipart kann die API nicht).
  Groessengrenze 64 MB = client_max_body_size in nginx.conf.
- UI: neuer Block "Disc-Schluessel fuer 4K-UHD" UEBER dem KEYDB-Block, mit
  Schluessel-Anzahl, Upload und Anleitung fuer den Windows-Weg. KEYDB.cfg
  ist jetzt als Notnagel beschriftet. Worker-Plakette zeigt die Anzahl;
  0 heisst sichtbar "4K-UHD scheitert".
- tasks.py: UHD-Fehlertext sagt den Windows-Weg an und nennt die Anzahl
  bekannter Schluessel dieses Workers.
- caps.py meldet schluessel je Worker.
- Alle Falschaussagen korrigiert: UI (3), Anleitung (2), README (3),
  KONZEPT §8 + §10, Worker-Dockerfile, makemkv_key.py (dort stand "Den
  AACS-Schluessel zieht MakeMKV via LibreDrive ohnehin selbst aus dem
  Laufwerk" - gilt fuer Blu-ray, NICHT fuer UHD).
- SAVEPOINT v3.11, ROADMAP Etappe 18 (Etappe 17 mit Nachtrag), AGENTS.

Offen: voller UHD-Rip inkl. Transcode-E2E; und ob sich der Abruf unter
Linux doch anstossen laesst.

Quellen (AGENTS Regel D):
- Linux laedt keine Hashed Keys, gleiches Symptom:
  https://forum.makemkv.com/forum/viewtopic.php?t=25782
  https://forum.makemkv.com/forum/viewtopic.php?t=34022
- Schluessel als hkd_*.bin in _private_data.tar:
  https://forum.makemkv.com/forum/viewtopic.php?t=32675
- Meldungsformat: https://www.makemkv.com/developers/usage.txt

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 11:18:09 +02:00

26 KiB
Raw Blame History

ROADMAP — Rippy

Meilenstein-Plan für den Bau von Rippy. Jede Etappe ist lauffähig für sich.


Etappe 1: Fundament — Container-Infrastruktur + udev-Erkennung

Ziel: Das System bootet, erkennt eine eingelegte Disc und erstellt einen Job.

Was gebaut wird:

  • Docker Compose mit api, worker, ui, postgres, redis
  • Basis-Dockerfiles für jeden Service (Python/FastAPI, Python/Celery, Node/React, PostgreSQL, Redis)
  • udev-Regel + separater Daemon (Python), der Disc-Einwurf erkennt und Jobs an den Worker sendet
  • Device-Resolver: ermittelt UUID/Serial des Laufwerks, erzeugt Symlink /dev/disc/<uuid>
  • Job-Erstellung in Celery-Queue mit Disc-Typ und Device-Pfad

Fertig wenn:

  • docker compose up startet alle 5 Container
  • udev-Regel erkennt Disc-Einwurf
  • udev-Daemon erstellt Celery-Job
  • Celery-Worker nimmt den Job entgegen und gibt "Disc erkannt: DVD, Device: /dev/disc/xxx" aus

Status: Abgeschlossen


Etappe 2: Ripping-Pipeline — Verlustfreies Extrahieren

Ziel: Disc wird rippt und als rohe Dateien abgelegt.

Was gebaut wird:

  • CD-Ripping via abcde → FLAC, AcoustID-Fingerprinting (chromaprint) + MusicBrainz-Lookup
  • DVD/Blu-ray-Ripping via makejungles (makeMKV-Äquivalent, OpenSource) → MKV, mit --all --progress
  • Ripping im Worker-Container, Read-Only Device-Passthrough
  • Fortschritts-Reporting über Celery-Signale an SSE-Stream

Fertig wenn:

  • CD → FLAC-Dateien + MusicBrainz-Metadaten
  • DVD → MKV mit allen Titeln
  • Blu-ray → MKV mit allen Titeln
  • Fortschritt wird in Echtzeit im UI angezeigt

Etappe 3: Metadaten-Lookup + Pre-Scan

Ziel: Vor dem Ripping wird die Disc identifiziert und der Commander bestätigt.

Was gebaut wird:

  • Pre-Scan-Modul: liest TOC (kein Ripping), extrahiert Titel/Laufzeit/Scene-Labels
  • TMDB-Integration für Film-/Serien-Matching (Confidence-Score)
  • MusicBrainz-Integration für CD-Matching
  • TheTVDB-Fallback für Serien
  • SQLite-Cache für API-Antworten (LRU, 10k Einträge, TTL)
  • Pre-Scan-Latenz: 515s, dokumentiert

Fertig wenn:

  • Nach Disc-Einwurf: Pre-Scan läuft automatisch
  • UI zeigt: Titel, Jahr, Cover, Confidence-Score, Trackliste
  • Commander kann bestätigen oder manuell korrigieren
  • Bestätigte Metadaten werden im Cache persistiert

Status: Abgeschlossen


Etappe 4: Jellyfin-Formatierung + NFO-Generierung

Ziel: Gerippte Dateien liegen in Jellyfin-konformer Ordnerstruktur mit Metadaten.

Was gebaut wird:

  • Ordnerstruktur:
    • Filme: <Filmname> (<Jahr>)/<Filmname>-<title>.mkv
    • Serien: <Serienname>/<Staffel N>/<Serienname> - S{N}E{N} - <Episode>.mkv
    • Musik: <Künstler>/<Album> (<Jahr>)/<Track-Nr>. <Titel>.flac
  • NFO-Generator im Kodi/NFO-Schema:
    • movie.nfo, series.nfo, episode.nfo, album.nfo
    • Alle Metadaten aus Pre-Scan + NFO-Attribution (Source: TMDB)
  • Image-Downloader: poster.jpg (500x750), fanart.jpg, backdrop.jpg (1920x1080+) von TMDB
  • Jellyfin-kompatible Dateibenennung
  • Multi-Disc-Handling: Disc 1.mkv, Disc 2.mkv etc.

Fertig wenn:

  • Gerippte Dateien + NFO + Poster in Jellyfin-Ordnerstruktur
  • Jellyfin scannt und erkennt alles korrekt
  • Multi-Disc-Sets werden als eine Entität angezeigt

Status: Abgeschlossen


Etappe 5: API + Auth + WebUI

Ziel: Vollständiger Web-Dienst mit Echtzeit-Status und Job-Steuerung.

Was gebaut wird:

  • FastAPI mit JWT-Auth (Access 15min, Refresh 7 Tage), Rate-Limiting (100/min/API-Key)
  • REST-Endpoints: Jobs erstellen/listen/abbrechen, Geräte verwalten, Einstellungen
  • SSE-Stream für Echtzeit-Jobstatus
  • React-UI (Vite-Build → statisch via Nginx):
    • Dashboard mit Echtzeit-Kacheln (Job-Status, Queue, Disc-Einwurf)
    • Job-Verlauf mit Fortschrittsbalken
    • Metadaten-Preview mit Bestätigungs-Dialog
    • Job-Detail mit Live-Log
    • Ergebnis-View mit Ordnerstruktur-Preview
    • Einstellungen (API-Keys, Transcoding, Backup-Pfade, Jellyfin-Config)
    • Geräte-Verwaltung

Fertig wenn:

  • Commander kann UI im Browser öffnen und alles bedienen
  • Jobs starten, stoppen, Verlauf einsehen
  • Echtzeit-Updates via SSE funktionieren
  • Alle Einstellungen werden gespeichert

Status: Abgeschlossen


Etappe 6: Sicherheit + Compliance + Hardening

Ziel: Produktionsreif — sicher, compliant, robust.

Was gebaut wird:

  • SELinux/AppArmor Profile pro Container
  • Read-only Bind-Mounts für System-Bibliotheken
  • mTLS zwischen API ↔ Worker
  • Netzwerk-Policy: UI→API (HTTPS), API↔Worker (mTLS), Worker↔Internet (nur API)
  • PostgreSQL mit verschlüsselten Connections
  • Source-Release-Endpoint (GPL-v3-Compliance)
  • Lizenz-Dokumentation (MakeMKV, OpenSource-Komponenten)
  • Backup-Hooks (PBS-Snapshot-Integration)
  • Error-Handling: exponential backoff Retry (max 5), Circuit-Breaker für APIs

Fertig wenn:

  • Alle Container haben Security-Profile
  • Netzwerkverkehr zwischen Containern ist verschlüsselt
  • GPL-v3-Compliance-Checkliste abgehakt
  • Backup-Hooks funktionieren

Status: Abgeschlossen


Etappe 7: API UI Modernisiert

Ziel: Modernes React-UI mit Dark Mode Support.

Was gebaut wird:

  • React UI mit TailwindCSS
  • Sidebar Navigation
  • Einstellungen mit Tab-Struktur
  • Dark Mode mit Theme-Toggle und localStorage persistence
  • Status-Badges und StatCards mit Dark Mode Support

Fertig wenn:

  • UI mit Dark Mode läuft
  • Navigation und Einstellungen funktionieren
  • Commit 43dfce5 — Dark Mode Implementation

Status: Abgeschlossen


Etappe 8: Separation of Concerns (Dark Mode)

Ziel: Code-Qualität durch saubere Trennung.

Was gebaut wird:

  • Theme-Context aus App.tsx auslagern
  • Dark Mode Utility für CSS-Klassen
  • Theme props in Komponenten verstecken
  • Tailwind-Config zentralisieren

Fertig wenn:

  • Theme-Logik in eigenem Context
  • Wiederverwendbare Dark Mode Helper
  • Saubere Komponenten-Struktur

Status: Abgeschlossen (Teil von Etappe 9)


Etappe 9: SoC Refactoring & Config Validation

Ziel: Code-Qualität durch saubere Trennung + Konfigurations-Validierung.

Was gebaut wird:

  • Theme-Context aus App.tsx in eigenes Context auslagern
  • Config Validation mit TMDB-API-Key Pflicht
  • Cache Key Centralization (cache/keys.py)
  • Worker Refactoring für bessere Trennung
  • Docker Compose mit Healthchecks

Fertig wenn:

  • Theme-Logik in eigenem Context (ThemeContext.tsx)
  • Wiederverwendbare Dark Mode Helper (useDarkMode.ts)
  • TMDB-API-Key ist Pflicht (Fehler bei Fallback-UI)
  • Cache-Keys zentral definiert
  • Docker Healthchecks für API

Status: In Arbeit

Etappe 9: Proxmox-Integration

Ziel: Ein-Click-Deploy auf Proxmox LXC.


Offene Punkte (aus KONZEPT.md)

Punkt Etappe Behandlung
TMDB-Matching-Fehler bei Nischentiteln Etappe 3 Pre-Scan Confidence-Score + manueller Korrektur-Mechanismus
NFO-Format-Abhängigkeit von Jellyfin-Version Etappe 4 Kodi/NFO-Schema (stabil, gut dokumentiert)
Pre-Scan-Latenz (515s) Etappe 3 Akzeptabel, Parallelisierung möglich
TMDB-Bildrechte Etappe 4 Gelöst: TMDB API-ToS erlaubt private Nutzung
Hybrid-Discs Etappe 1 MVP erkennt nur Standard; als "Kann" notiert
Redis Single-Instance Etappe 1 MVP reicht; Cluster als "Später"

Etappe 10: MakeMKV-Umstellung — das Muss-Feature „lossless" einlösen

Ziel: DVD/Blu-ray-Ripping auf makemkvcon umstellen (verlustfrei), wie im KONZEPT als Muss definiert. HandBrake fliegt aus dem Ripp-Pfad (bleibt ggf. als optionaler Transcode-Schritt NACH dem verlustfreien Rip).

  • Worker-Dockerfile: makemkv-oss/makemkv-bin 1.18.4 multi-stage gebaut, Beta-Key via MAKEMKV_APP_KEY-Env (entrypoint.sh) — 23.07.
  • ripping.py: auf makemkvcon -r --progress=-same mkv dev:… all umgestellt, PRGV-Fortschritts-Parsing laut makemkv.com/developers/usage.txt, Tests dabei — 23.07.
  • E2E mit echter Disc verifizieren (Commander, Laufwerk nötig) Fertig wenn: eine echte DVD landet verlustfrei als MKV im Output, Ampel grün. Entstanden aus: Review 22.07. — HandBrake-lossy war eine stille Abweichung vom Konzept; Entscheid 22.07. abends: Konzept gilt, Umbau als eigene Etappe.

Etappe 11 (23.07.2026): Kernumbau — der Zweck funktioniert erstmals wirklich

Befund des Komplett-Audits (Claude): Der Kern „Disc rein → gerippt raus" hatte NIE einen Code-Pfad: kein POST /jobs, kein udev-Daemon (das referenzierte udev_daemon.py existierte nirgends), kein Ripping-Tool im Worker-Image, Disc-Erkennung strukturell tot (file -L auf Block-Device), Geräte als Bind-Mounts statt devices: (EPERM), UI rief hartkodiert localhost:8000 auf.

Gebaut:

  • POST /jobs (API → Celery → Worker) + Job-Persistenz in Postgres
  • Disc-Watcher in der API (ioctl-Poll statt udev — Container-tauglich)
  • Disc-Erkennung neu über Kernel-ioctls (detection.py, in API+Worker)
  • /logs-Endpoint + echte Logs-Seite (Mock-Daten raus)
  • /settings-Endpoints (Settings-Seite sprach vorher ins Leere)
  • UI: Vite-Build + nginx mit /api-Proxy statt Dev-Server; relative API-Pfade
  • compose: devices: statt Bind-Mounts; Ausgabe aufs media-Volume
  • Jellyfin-Post-Processing an den Worker anbinden (NFO/Poster nach dem Rip) — 24.07., medien.py: Ordner „Titel (Jahr)" + movie.nfo + poster.jpg, gesteuert übers mediaServer-Setting (Jellyfin/Emby/Kodi/Plex/keins)
  • Auth vor die schreibenden Endpoints (JWT existiert, schützt aber nichts)

Etappe 12: Besser als ARM (aus ARM-Analyse 23.07.2026)

Quelle: Vollanalyse von Automatic Ripping Machine v2.24 (Code, arm.yaml, Wiki, Issues). Was Rippy strukturell schon besser macht: Lossless-first statt Transcode-first (ARMs BD-Default ist ein 1080p30-Downscale!), Celery+Postgres statt Prozess-pro-udev-Event+SQLite (ARM-UI friert beim Rippen ein, #1046), ioctl-Watcher statt fragiler udev-Ketten (ARMs größte Support-Quelle), NFO + Jellyfin-Konvention nativ (ARM kann nur Emby-Refresh, keine NFOs).

Übernehmen (priorisiert):

  • Disc-Fingerprint-DB (selbstlernend) — ARMs beste Idee, besser gemacht: Tabelle disc_fingerprints (DVD-CRC64/MusicBrainz-DiscID/BD-Label-Hash → bestätigte Metadaten). Jede UI-Bestätigung schreibt zurück; zweite Disc derselben Serie wird sofort erkannt. Lokal statt ARMs Crowd-Server (Single Point of Failure auf Free-Hosting).
  • BD-Titel aus BDMV/META/DL/bdmt_eng.xml als Identifikations-Stufe vor den APIs (echter Disc-Titel statt Label-Raterei).
  • Progressive Suchdegradation bei TMDB/OMDb: mit Jahr → ohne Jahr → tokenweises Titel-Stripping; jede Stufe senkt die Confidence.
  • Duplikat-Schutz: Fingerprint-Treffer → „schon gerippt am X — trotzdem?"
  • Track-Auswahl (Manual Mode), besser als ARM: Job-Status awaiting_selection nach makemkvcon-info; Track-Tabelle im UI mit Heuristik-Vorauswahl; Timeout → Weiter mit Default (ARM bricht hart ab, erlaubt nur EINE Auswahl).
  • Min/Max-Titellänge + Extras: Bonusmaterial nach extras/ (versteht Jellyfin nativ) statt alles flach.
  • Benachrichtigungen bei Job-Ende — 24.07., eigenes notify-Modul (Discord/Slack/ntfy/generisches JSON, Dienst-Erkennung an der URL) statt Apprise-Dependency; Test-Knopf im UI. Telegram/Deep-Links offen.
  • Multi-Drive-Verwaltung: drives-Tabelle (Seriennummer, Custom-Name, UHD-fähig-Flag), parallele Rips, Job↔Drive-Zuordnung.
  • Backup-Modus (makemkvcon backup --decrypt) als Plan B für Problem-Discs.
  • Jellyfin-Refresh nach Ablage (POST /Library/Refresh).

ARM schlagen (Alleinstellung):

  • Serien-Episoden-Erkennung — ARMs offene Wunde seit 2019 (#395): TVDB-Episodenlaufzeiten gegen Track-Laufzeiten matchen (±5 %, Reihenfolge-Constraint, Disc-Nr aus Label), Vorschlag „Show/Season 02/Show S02E05.mkv" im Preview bestätigen.
  • Main-Feature per Laufzeitabgleich mit TMDB-Runtime (±3 min) statt ARMs „größte Datei gewinnt" (#1297-Fehlklasse).

Etappe 13 (24.07.2026): Universal-Komfort-Runde — Lücken aus dem Alltag schließen

Quelle: Commander-Sammelauftrag 24.07. — alles, was beim echten Benutzen auffiel, in einem Rutsch. Alles gebaut, Tests dabei, Ampel-Blocker behoben.

Gebaut:

  • Ampel entrostet: bcrypt auf 4.0.1 gepinnt (passlib-1.7.4-Bruch) und cache_keys-Test an das Fingerprint-Format vom 23.07. angepasst — DIE beiden Rot-Ursachen, wegen derer stable 10 Commits zurückhing.
  • Media-Server-Integration: mediaServer-Setting (Wizard + Einstellungen), Zielordner „Titel (Jahr)", movie.nfo/tvshow.nfo + poster.jpg für Jellyfin/Emby/Kodi (medien.py im Worker, mit Tests).
  • Benachrichtigungen echt gemacht: notify.py (API+Worker), Meldung bei fertig/fehlgeschlagen/abgebrochen, Anleitung + Test-Knopf im UI — das Webhook-Feld war vorher ein Placebo, nichts hat je gesendet.
  • SMB-Freigaben-Scan repariert: NT_STATUS-Fehler → Klartext (Gast- Abfrage verweigert ⇒ Benutzer/Passwort nötig), Credential-Felder im UI VOR den „Freigaben auflisten"-Knopf gezogen.
  • 4K-UHD-Platzproblem: Arbeitsverzeichnis konfigurierbar (workDir, z. B. NAS-Freigabe), Platz-Check per Disc-Größe (ioctl) VOR dem Rip.
  • MakeMKV-Key über UI (Einstellungen → System): gilt ab dem nächsten Rip, ohne Rebuild; Worker melden Werkzeug-Versionen + Key-Quelle.
  • Job-Detail-Popup: Klick auf Titel in „Neueste Jobs" → Poster, Jahr, Beschreibung, Ablagepfad, Fehler (Job speichert Metadaten jetzt mit).
  • UI-Feedback überall: Toast-System (reinploppende Meldungen), drehende Refresh-Knöpfe, Logs-Filter um Warnung/Fehler-Pills ergänzt.
  • Datei-Browser zeigt Dateien: Ordner wirkten „leer", weil nur Unterordner gelistet wurden — Dateien erscheinen jetzt grau mit Größe.
  • Favicon (Disc im Logo-Verlauf) + Footer „Created with ❤️ by LucyAI, Claude and KrBrZ".
  • README: Media-Server, Benachrichtigungen, UHD-Arbeitsverzeichnis, „Rippy woanders bereitstellen" (beliebiger Docker-Host).
  • Download-Knopf für fertige Rips (Wunsch aus der Übernahme-Session): GET /jobs/{id}/files (+ Datei-Stream, Pfad-Validierung strikt unter /app/media inkl. realpath-Check), Download-Knopf in der Aktion-Spalte, Dateiliste mit Größen im Job-Detail-Popup — vorher kam man an fertige MKVs nur per scp. nginx hatte proxy_buffering off schon (SSE).

Offen aus dieser Runde: nichts — Rest siehe Etappe 12 und Ideen unten.


Etappe 14 (24.07.2026): Praxis-Feedback-Runde — erste echte Nutzung

Quelle: Commander-Feedback nach dem ersten richtigen Arbeiten mit v3.2.

  • SMB-Mount-Blocker: CAP_DAC_READ_SEARCH für mount.cifs (auf der VM reproduziert + bewiesen), Compose-Fix.
  • TMDB-Key-Falle: v3-Schlüssel wurden still 401 (Client konnte nur v4-Bearer) — beide Arten unterstützt, „Verbindung prüfen" im UI.
  • 4K UHD als eigener Disc-Typ (≥ 55 GiB) mit eigener Farbe + Klartext- Fehler bei Nicht-LibreDrive-Laufwerken.
  • Vollautomatik-Setting (Disc rein → Rip startet ohne Popup).
  • Job-Verwaltung: can_retry (Knopf nur bei vorhandenen Rohdaten), Einzel-Löschen, „Erledigte aufräumen", „Alle herunterladen".
  • Worker: WORKER_NAME-Anzeigename + IP/ID, verwaiste Einträge löschbar.
  • Ripping-Tab nach Medium (Video/Audio/Allgemein), Untertitel-Klartext, CD → Musik-Vorauswahl im Ziel-Dialog, Ordner-Verwaltung eingeklappt.

Etappe 15 (24.07.2026): Restefeger — der Ideen-Katalog wird abgearbeitet

Commander-Auftrag: „Arbeite alles ab, abgesehen von Auth — das ist irrelevant und kann komplett raus."

  • AUTH KOMPLETT ENTFERNT (Commander-Entscheid): /token- und /api-keys-Endpoints, auth.py, test_auth.py, passlib/bcrypt/PyJWT, JWT_SECRET_KEY-Pflicht — alles raus (KONZEPT §10). Der Schnellstart braucht keine .env-Pflichtwerte mehr. Rate-Limit pro IP bleibt.
  • Serien-Staffel-Flow: Im Rip-Dialog Serienname + Staffel → Ablage <Serie>/Season NN; tvshow.nfo + poster.jpg landen im Serien-Ordner (werden bei Staffel 2 nicht überschrieben).
  • Episoden-Erkennung per Laufzeitabgleich (ARM-Wunde #395): Datei-Laufzeiten (HandBrake-Scan) gegen TMDB-Episoden-Laufzeiten, ordnungserhaltend; komplette Staffel auf einer Disc geht auch bei uniformen Laufzeiten. Umbenannt wird NUR bei eindeutiger Zuordnung („Serie S01E02.mkv"), sonst bleiben die Namen + ehrliches Log.
  • Jellyfin/Emby-Bibliotheks-Refresh nach jedem fertigen Rip (POST /Library/Refresh, X-Emby-Token) — URL/Key + Test-Knopf in den Einstellungen. Die Null-Klick-Kette Disc→Bildschirm steht.
  • Duplikat-Warnung: Disc-Fingerabdruck gegen die Job-Historie — Hinweis auf der Disc-Karte, Vollautomatik überspringt Duplikate.
  • „Nur Hauptfilm" ECHT: das Setting war wirkungslos — jetzt Info-Lauf → längster Titel → nur der wird gerippt; pro Rip im Dialog übersteuerbar. (Volle Track-Tabelle bleibt Ausbaustufe.)
  • Deutsche Texte für OMDb-Treffer via TMDB /find (IMDb-ID → de-DE).
  • Speicherplatz in der Dashboard-Leiste (amber unter 60 GB frei).
  • CSV-Export der Job-Historie (Semikolon+BOM, Excel-tauglich).
  • Metadaten-Seite entfernt (+ Placebo-Endpoints /metadata/lookup und /metadata/confirm — lookup scannte ein Dummy-Device).
  • Doppel-Jahr-Fix („X (2009) (2009)" in Log/Ordnernamen).
  • Remote-Worker-Blocker: redis/postgres waren nie veröffentlicht — kein Remote-Worker konnte sich je verbinden. Ports 6379/5432 jetzt offen (Heimnetz-Kompromiss, dokumentiert) + API_URL für Worker.

Etappe 16 (24.07.2026): Track-Tabelle + nativer Windows-Worker + Anleitung

  • Volle Titel-Auswahl vor dem Rip: scan_tracks-Worker-Task, Polling-Endpoints, Tabelle (Dauer/Größe/Kapitel, Vorauswahl ≥ 5 min) im Rip-Dialog, Multi-Titel-Rip (ein makemkvcon-Aufruf je Titel, Fortschritt anteilig). Parser mit Tests.
  • Nativer Windows-Worker ohne Docker: install.ps1 + Worker-Code werden von der Rippy-Instanz selbst serviert (/worker-setup/*); HandBrakeCLI 1.9.2 vom offiziellen GitHub-Release; celery --pool=solo -Q transcode; optional Autostart. UI bietet Linux- und Windows-Variante. E2E auf echtem Windows-PC bewiesen.
  • Anleitungs-Tab: Rippy erklärt sich selbst (Disc-Weg, Serien, NAS, Media-Server, Benachrichtigungen, Key, Worker, FAQ).

Etappe 17 (25.07.2026): 4K-UHD-Schlüssel (KEYDB.cfg)

Quelle: Messung am 25.07. live auf der Rippy-VM im Worker-Container. Eine 4K-UHD (Akira, MKB v76, Pressung Dezember 2020) scheitert an „The volume key is unknown for this disc" — obwohl makemkvcon „Using LibreDrive mode (v06.3)" und „Using direct disc access mode" meldet, die Disc liest und den AACS-Dump ablegt (Meldung 3332). Das Debug-Log geht ohne einen einzigen Netz-Versuch von „Loaded content hash table" direkt auf den Fehler; _private_data.tar enthielt nur die Index-Datei und keine einzige hkd_*.bin; auch mit gelöschter update.conf (Meldung 5074 belegt den Web-Kontakt) und app_UpdateEnable = "1" kam kein Schlüssel; die Forum-Schlüssel-Server hkdata.fairuse.org und hkdata.crabdance.com lösen weltweit nicht mehr auf. Fazit: Ein MakeMKV-Update löst das nicht (das behauptete v3.3 — dort richtiggestellt). Der einzige heute funktionierende Weg ist eine KEYDB.cfg im MakeMKV-Datenverzeichnis.

⚠️ Nachtrag am selben Tag (siehe Etappe 18): Die letzte Folgerung war falsch. Die beiden toten Hostnamen stammen aus alten Forumsbeiträgen und werden von MakeMKV längst nicht mehr benutzt — der Dienst lebt. Richtig ist: makemkvcon unter Linux fragt nie nach Schlüsseln, die Windows-Version schon. Alles hier Gebaute bleibt richtig und nötig, nur die KEYDB.cfg ist nicht der Haupt-, sondern der Ersatzweg.

Gebaut:

  • Persistentes Datenverzeichnis: ${MAKEMKV_DATA_HOST:-/srv/rippy/makemkv} vom Host gemountet — Worker /root/.MakeMKV, API /app/makemkv-data, beide mit MAKEMKV_DATA_DIR. KEYDB.cfg und AACS-Dumps überleben jeden Rebuild. .env.example erklärt die Variable.
  • entrypoint.sh entschärft: settings.conf wird ergänzt statt überschrieben (der Beta-Key hatte sonst alles andere gelöscht), app_UpdateEnable = "1" gesetzt.
  • Zwillings-Modul makemkv_daten.py (identisch in docker/api/ und docker/worker/) als einzige Wahrheit über das Verzeichnis: Status lesen, Inhalt prüfen, atomar schreiben, löschen, Dumps auflisten — alles reine Funktionen, damit die Ampel sie ohne Postgres/Redis testen kann.
  • API: GET/POST/DELETE /system/keydb, GET /system/aacs-dumps und GET /system/aacs-dumps/{dateiname}. Der Inhalt kommt bewusst als JSON-Body — es gibt kein python-multipart, ein Endpunkt mit UploadFile/File() würde die API beim Import töten.
  • UI (Einstellungen → System): Status der KEYDB.cfg (Pfad, Größe, Anzahl Disc-Einträge, Datum), Inhalt einfügen, entfernen, AACS-Dumps herunterladen — ohne SSH auf die VM.
  • MakeMKV redet endlich: parse_msg() in ripping.py + Log-Callback in tasks.py schreiben MakeMKV-Meldungen ins Rippy-Log (gedrosselt: Code 1003 raus, keine Wiederholungen, max. 40 je Rip). UHD-Fehlertext ehrlich neu geschrieben; caps.py meldet keydb: ja | nein | unbekannt.
  • Doku nachgezogen: README (UHD-Voraussetzungen, System-Panel, MAKEMKV_DATA_HOST, Bereitstellung), SAVEPOINT v3.10 inkl. Richtigstellung von v3.3, KONZEPT §8 + §10.

Offen aus dieser Runde:

  • Der Nachweis mit einer echten KEYDB.cfg steht aus. Zum Zeitpunkt der Änderung lag keine Datei vor, die den Akira-Schlüssel enthält — belegt sind der Befund und die Mechanik, NICHT ein erfolgreicher UHD-Rip.
  • Damit bleibt auch der volle Transcode-E2E an einer UHD weiter offen (siehe SAVEPOINT v3.7) — an normalen BD/DVD ist die Kette bewiesen.

Nachtrag zu „Offen": Beide Punkte sind mit Etappe 18 erledigt — Akira ging auf der VM auf, allerdings über den Schlüsselspeicher statt über eine KEYDB.cfg.

Ausdrücklich nicht gebaut (und wird es auch nicht): Rippy liefert keine Disc-Schlüssel mit, lädt keine herunter und verteilt keine. Es stellt nur den Platz für eine Datei bereit, die der Nutzer selbst mitbringt, und zeigt ehrlich an, was dort liegt.


Etappe 18 (25.07.2026): 4K-UHD gelöst — Schlüsselspeicher statt KEYDB.cfg

Quelle: Einwand des Commanders („wenn ich MakeMKV lokal auf meinem Windows-PC installiere, würde es SOFORT gehen — wir übersehen etwas Gewaltiges"). Er hatte recht. Gegenprobe mit demselben Laufwerk und derselben Disc an einem Windows-PC:

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" TCOUNT:5, 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: Linux fragt nie. Die Meldungsvorlage „Downloading latest %1 to %2 ..." steckt sehr wohl im Linux-Binary — sie löst nur nicht aus. Gleiches Symptom im MakeMKV-Forum, seit Jahren offen (t=25782, t=34022). Damit ist die Diagnose aus Etappe 17 („der Schlüssel-Kanal ist tot") widerlegt. Sie stützte sich auf zwei Hostnamen aus alten Forumsbeiträgen, die MakeMKV längst nicht mehr benutzt.

Gebaut:

  • Schlüsselspeicher im Modul: zaehle_schluessel, private_data_pruefen, schluesselspeicher_status, private_data_schreiben in makemkv_daten.py (beide Zwillinge). Die Prüfung lehnt einen Speicher OHNE hkd_*.bin ab — sonst lädt jemand den leeren Vorrat einer frischen Installation hoch, es ändert sich nichts, und niemand versteht warum.
  • API: GET /system/keystore und POST /system/keystore. Der Rohkörper der Anfrage IST die Datei — binär, deshalb kein JSON und kein Base64; Multipart kann die API ohnehin nicht.
  • UI: neuer Block „Disc-Schlüssel für 4K-UHD" ÜBER dem KEYDB-Block, mit Schlüssel-Anzahl, Upload und Schritt-für-Schritt- Anleitung für den Windows-Umweg. KEYDB.cfg ist jetzt als Notnagel beschriftet. Worker-Plakette zeigt die Schlüssel-Anzahl.
  • Fehlertext in tasks.py sagt den Windows-Weg an und nennt die Anzahl bekannter Schlüssel dieses Workers.
  • caps.py meldet schluessel je Worker.
  • Alle Falschaussagen korrigiert: UI (3 Stellen), Anleitung (2), README (3), KONZEPT §8 + §10, makemkv_daten.py-Modulkopf, Worker-Dockerfile, makemkv_key.py.

Bewiesen: Nach Übernahme des Windows-Schlüsselspeichers öffnet makemkvcon auf der VM die Akira-UHD — „Operation successfully completed", TCOUNT:5, fünf Titel, identisch zum Windows-Ergebnis. Das ist der erste belegte UHD-Disc-Zugriff auf der Rippy-Maschine.

Offen aus dieser Runde:

  • Voller UHD-Rip inklusive Transcode-E2E (nur der Disc-Zugriff ist belegt, nicht die komplette Kette bis zur fertigen Datei).
  • Ob sich der Abruf unter Linux doch anstoßen lässt, ist ungeklärt — der Code ist im Binary vorhanden. Bis dahin bleibt der Windows-Umweg.

Ideen-Katalog (Rest) — bewusst offen

  1. Design 2.0 — an Gemini übergeben (24.07.2026). Vollständiges Briefing: docs/DESIGN-2.0-BRIEFING.md. Arbeitsbranch: design-2.0 (deployt bewusst NICHT, nur main wird befördert). Kern: 428 theme === 'dark'-Ternaries → Tailwind-dark: + UI-Primitives, Optik-Modernisierung, ohne Funktions-/Text-Änderungen. Der neue Anleitungs-Tab gehört mit in den Feinschliff.
  2. AI-Box als VAAPI-Transcode-Worker: Ports sind offen, Compose steht (deploy/remote-transcode-worker.yml) — es fehlt nur der NFS/SMB-Export der Rippy-Ablage an die AI-Box (Infra-Entscheid auf der VM).
  3. Kodi-Bibliotheks-Refresh (JSON-RPC VideoLibrary.Scan) analog zu Jellyfin/Emby.
  4. Windows-Worker als echter Dienst (statt start-worker.bat/onlogon): z. B. via NSSM oder PyInstaller-Paket — Komfort-Ausbau der jetzt funktionierenden nativen Variante.