0935766f61
Ampel / ampel (push) Successful in 28s
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>
492 lines
23 KiB
Markdown
492 lines
23 KiB
Markdown
# 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: 5–15s, 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 (5–15s) | 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).
|
||
- [x] Worker-Dockerfile: makemkv-oss/makemkv-bin 1.18.4 multi-stage gebaut,
|
||
Beta-Key via MAKEMKV_APP_KEY-Env (entrypoint.sh) — 23.07.
|
||
- [x] 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:**
|
||
- [x] POST /jobs (API → Celery → Worker) + Job-Persistenz in Postgres
|
||
- [x] Disc-Watcher in der API (ioctl-Poll statt udev — Container-tauglich)
|
||
- [x] Disc-Erkennung neu über Kernel-ioctls (detection.py, in API+Worker)
|
||
- [x] /logs-Endpoint + echte Logs-Seite (Mock-Daten raus)
|
||
- [x] /settings-Endpoints (Settings-Seite sprach vorher ins Leere)
|
||
- [x] UI: Vite-Build + nginx mit /api-Proxy statt Dev-Server; relative API-Pfade
|
||
- [x] compose: devices: statt Bind-Mounts; Ausgabe aufs media-Volume
|
||
- [x] 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.
|
||
- [x] **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:**
|
||
- [x] **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.
|
||
- [x] **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).
|
||
- [x] **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.
|
||
- [x] **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.
|
||
- [x] **4K-UHD-Platzproblem**: Arbeitsverzeichnis konfigurierbar (workDir,
|
||
z. B. NAS-Freigabe), Platz-Check per Disc-Größe (ioctl) VOR dem Rip.
|
||
- [x] **MakeMKV-Key über UI** (Einstellungen → System): gilt ab dem nächsten
|
||
Rip, ohne Rebuild; Worker melden Werkzeug-Versionen + Key-Quelle.
|
||
- [x] **Job-Detail-Popup**: Klick auf Titel in „Neueste Jobs" → Poster, Jahr,
|
||
Beschreibung, Ablagepfad, Fehler (Job speichert Metadaten jetzt mit).
|
||
- [x] **UI-Feedback überall**: Toast-System (reinploppende Meldungen), drehende
|
||
Refresh-Knöpfe, Logs-Filter um Warnung/Fehler-Pills ergänzt.
|
||
- [x] **Datei-Browser zeigt Dateien**: Ordner wirkten „leer", weil nur
|
||
Unterordner gelistet wurden — Dateien erscheinen jetzt grau mit Größe.
|
||
- [x] Favicon (Disc im Logo-Verlauf) + Footer „Created with ❤️ by LucyAI,
|
||
Claude and KrBrZ".
|
||
- [x] README: Media-Server, Benachrichtigungen, UHD-Arbeitsverzeichnis,
|
||
„Rippy woanders bereitstellen" (beliebiger Docker-Host).
|
||
- [x] **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.
|
||
|
||
- [x] SMB-Mount-Blocker: CAP_DAC_READ_SEARCH für mount.cifs (auf der VM
|
||
reproduziert + bewiesen), Compose-Fix.
|
||
- [x] TMDB-Key-Falle: v3-Schlüssel wurden still 401 (Client konnte nur
|
||
v4-Bearer) — beide Arten unterstützt, „Verbindung prüfen" im UI.
|
||
- [x] 4K UHD als eigener Disc-Typ (≥ 55 GiB) mit eigener Farbe + Klartext-
|
||
Fehler bei Nicht-LibreDrive-Laufwerken.
|
||
- [x] Vollautomatik-Setting (Disc rein → Rip startet ohne Popup).
|
||
- [x] Job-Verwaltung: can_retry (Knopf nur bei vorhandenen Rohdaten),
|
||
Einzel-Löschen, „Erledigte aufräumen", „Alle herunterladen".
|
||
- [x] Worker: WORKER_NAME-Anzeigename + IP/ID, verwaiste Einträge löschbar.
|
||
- [x] 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."
|
||
|
||
- [x] **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.
|
||
- [x] **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).
|
||
- [x] **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.
|
||
- [x] **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.
|
||
- [x] **Duplikat-Warnung**: Disc-Fingerabdruck gegen die Job-Historie —
|
||
Hinweis auf der Disc-Karte, Vollautomatik überspringt Duplikate.
|
||
- [x] **„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.)
|
||
- [x] **Deutsche Texte für OMDb-Treffer** via TMDB /find (IMDb-ID → de-DE).
|
||
- [x] **Speicherplatz in der Dashboard-Leiste** (amber unter 60 GB frei).
|
||
- [x] **CSV-Export** der Job-Historie (Semikolon+BOM, Excel-tauglich).
|
||
- [x] **Metadaten-Seite entfernt** (+ Placebo-Endpoints /metadata/lookup
|
||
und /metadata/confirm — lookup scannte ein Dummy-Device).
|
||
- [x] **Doppel-Jahr-Fix** („X (2009) (2009)" in Log/Ordnernamen).
|
||
- [x] **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
|
||
|
||
- [x] **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.
|
||
- [x] **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.
|
||
- [x] **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:**
|
||
- [x] **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.
|
||
- [x] **entrypoint.sh entschärft**: `settings.conf` wird ergänzt statt
|
||
überschrieben (der Beta-Key hatte sonst alles andere gelöscht),
|
||
`app_UpdateEnable = "1"` gesetzt.
|
||
- [x] **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.
|
||
- [x] **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.
|
||
- [x] **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.
|
||
- [x] **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`.
|
||
- [x] **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.
|