Files
rippy/ROADMAP.md
T
Hitonabi 0935766f61
Ampel / ampel (push) Successful in 28s
feat(uhd): KEYDB.cfg-Unterstuetzung - MakeMKVs Schluessel-Kanal liefert nichts mehr
4K-UHD scheiterte an "The volume key is unknown for this disc". Am 25.07.2026
im Worker-Container nachgemessen: Laufwerk und MakeMKV sind in Ordnung
(LibreDrive v06.3 / Meldung 1011, Disc wird gelesen, AACS-Dump geschrieben) -
MakeMKV versucht gar nicht erst, online einen Schluessel zu holen. Belege:
_private_data.tar enthaelt nur die Index-Datei und KEINE hkd_*.bin; auch mit
geloeschter update.conf (Meldung 5074 belegt den Web-Kontakt) und mit
app_UpdateEnable="1" kam keiner; hkdata.fairuse.org und hkdata.crabdance.com
loesen weltweit nicht mehr auf (NXDOMAIN gegen Fritz!Box, 8.8.8.8, 1.1.1.1).
Betroffen war Akira UHD (MKB v76, Pressung Dez. 2020) - also gerade KEINE
Neuerscheinung. Der bisherige Fehlertext ("Disc neuer als die
Schluessel-Datenbank, mit einem der naechsten Updates rippbar") war falsch.

Einziger heute funktionierender Weg ist eine vom Nutzer selbst mitgebrachte
KEYDB.cfg. Rippy liefert KEINE Schluessel mit, laedt keine herunter und
verteilt keine - es stellt nur den Platz bereit und zeigt an, was dort liegt.

- Datenverzeichnis persistent gemountet (MAKEMKV_DATA_HOST, Default
  /srv/rippy/makemkv): KEYDB.cfg und AACS-Dumps ueberleben jeden Rebuild.
  Vorher loeschte jeder "up -d --build" beides - inklusive des Dumps, auf den
  die Fehlermeldung selbst verwies.
- entrypoint.sh und tasks.py schreiben settings.conf ergaenzend statt
  zerstoerend. Der entrypoint bricht bei nicht beschreibbarem Verzeichnis
  nicht mehr ab - mit "restart: unless-stopped" waere das ein Crashloop
  gewesen, in dem auch reines DVD-Rippen tot ist.
- Neues Zwillings-Modul makemkv_daten.py (docker/api + docker/worker,
  byteweise identisch; test_zwillinge_sind_byteweise_identisch wacht darueber
  und wurde durch absichtliches Verstellen als wirksam nachgewiesen).
- API: GET/POST/DELETE /system/keydb, GET /system/aacs-dumps(/{dateiname}).
  JSON-Body statt Multipart - python-multipart ist bewusst nicht installiert
  und wuerde die API beim Import toeten. nginx client_max_body_size 64m,
  sonst scheitert der Upload mit 413, bevor die API ihn sieht.
- UI (Einstellungen -> System): Status, Hochladen per Datei-Dialog, Entfernen,
  Dump-Download, KEYDB-Plakette je Worker (nur wo das Verzeichnis wirklich
  gemountet ist - ein Remote-Transcode-Worker truege sonst eine Warnung,
  die ihn nichts angeht).
- parse_msg() + log_cb: MakeMKV-Meldungen landen im Rippy-Log (gedrosselt:
  Code 1003 raus, keine Wiederholungen, max. 40 je Rip). Nebenbei behoben:
  der alte Parser (split(",", 4)[3]) schnitt jede Meldung am ersten Komma ab.
- Fuenf Stellen richtiggestellt, die behaupteten, MakeMKV-Updates braechten
  die neueste Disc-Schluessel-Datenbank mit (UI, Anleitung, README,
  Worker-Dockerfile, makemkv_key.py).

NICHT bewiesen: ein erfolgreicher UHD-Rip - es lag keine KEYDB.cfg mit dem
Akira-Schluessel vor. Belegt sind der Befund und die neue Mechanik. So steht
es auch im SAVEPOINT und in der ROADMAP.

Quellen (AGENTS Regel D):
- Datenverzeichnis + Dateiname GROSS/case-sensitiv:
  https://forum.makemkv.com/forum/viewtopic.php?t=30636
- hkd_*.bin in _private_data.tar:
  https://forum.makemkv.com/forum/viewtopic.php?t=32675
- headless settings.conf / app_UpdateEnable:
  https://forum.makemkv.com/forum/viewtopic.php?t=20364
- KEYDB.cfg-Zeilenformat (libaacs):
  https://github.com/ShiftMediaProject/libaacs/blob/master/KEYDB.cfg
- MSG-/PRGV-Format: https://www.makemkv.com/developers/usage.txt

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 01:26:08 +02:00

23 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.

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.

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.


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.