fix(uhd): 4K-UHD geloest - makemkvcon holt Schluessel unter Linux nie
Ampel / ampel (push) Successful in 28s

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>
This commit is contained in:
Hitonabi
2026-07-25 11:18:09 +02:00
parent 0935766f61
commit f449c4ee34
14 changed files with 828 additions and 163 deletions
+4 -2
View File
@@ -62,6 +62,8 @@ Bibliotheks-APIs: `--help`/Doku prüfen und die Fundstelle im Commit nennen.
echte Benachrichtigungen, SMB-Klartext-Fehler, UHD-Arbeitsverzeichnis, echte Benachrichtigungen, SMB-Klartext-Fehler, UHD-Arbeitsverzeichnis,
MakeMKV-Key via UI, Job-Detail-Popup, Toast-Feedback, Ampel-Blocker behoben MakeMKV-Key via UI, Job-Detail-Popup, Toast-Feedback, Ampel-Blocker behoben
-**Etappe 17 (v3.10):** 4K-UHD-Disc-Schlüssel — persistentes -**Etappe 17 (v3.10):** 4K-UHD-Disc-Schlüssel — persistentes
MakeMKV-Datenverzeichnis + `KEYDB.cfg` im UI (der Nachweis mit einer MakeMKV-Datenverzeichnis + `KEYDB.cfg` im UI
echten Schlüssel-Datei steht noch aus) -**Etappe 18 (v3.11):** 4K-UHD gelöst — `makemkvcon` holt Schlüssel
unter Linux nie, unter Windows schon; Schlüsselspeicher übernehmbar.
Akira-UHD geht auf der VM auf (`TCOUNT:5`, bewiesen)
- 📝 **Details immer in SAVEPOINT.md** — diese Sektion nennt nur die Etappe - 📝 **Details immer in SAVEPOINT.md** — diese Sektion nennt nur die Etappe
+8 -6
View File
@@ -127,7 +127,7 @@ Ein modular aufgebautes System, das bei Disc-Einwurf automatisch den Typ erkennt
| Risiko | Status | Behandlung | | Risiko | Status | Behandlung |
|--------|--------|------------| |--------|--------|------------|
| MakeMKV-Beta-Key-Management | Gelöst | Key-Erneuerung als Cron-Job; DMCA-Ausnahme in DE | | MakeMKV-Beta-Key-Management | Gelöst | Key-Erneuerung als Cron-Job; DMCA-Ausnahme in DE |
| **Disc-Schlüssel für 4K-UHD (AACS 2.0)** | **Offen — durch Rippy nicht lösbar** | Am 25.07.2026 auf der VM gemessen: MakeMKV holt für unbekannte UHD-Discs keinen Schlüssel mehr (kein Netz-Versuch im Log, keine `hkd_*.bin` im `_private_data.tar`), die dokumentierten Schlüssel-Server sind weltweit tot. Rippy stellt NUR ein persistentes Datenverzeichnis für eine vom Nutzer selbst mitgebrachte `KEYDB.cfg` bereit und gibt die AACS-Dumps heraus — es liefert, lädt und verteilt keine Schlüssel. Siehe §10 (25.07.2026) | | **Disc-Schlüssel für 4K-UHD (AACS 2.0)** | **Gelöst mit Handgriff** | Am 25.07.2026 auf beiden Maschinen gemessen: `makemkvcon` unter **Linux** ruft Disc-Schlüssel nie ab (kein einziger Verbindungsversuch, mit leerem wie gefülltem Speicher, mit und ohne `--noscan`, `dev:` wie `disc:`), die **Windows**-Version tut es (Meldung 3338). Rippy stellt ein persistentes Datenverzeichnis bereit und nimmt den Schlüsselspeicher `_private_data.tar` einer Windows-Installation sowie ersatzweise eine `KEYDB.cfg` entgegen; damit ging Akira UHD auf der VM auf. Rippy liefert, lädt und verteilt KEINE Schlüssel. Siehe §10 (25.07.2026) |
| LXC-Device-Node-Änderungen | Gelöst | udev-Resolver (UUID/Serial) | | LXC-Device-Node-Änderungen | Gelöst | udev-Resolver (UUID/Serial) |
| Pending-Queue / State-Manager | Gelöst | Redis mit AOF-Persistence | | Pending-Queue / State-Manager | Gelöst | Redis mit AOF-Persistence |
| Hybrid-Discs | Offen | MVP erkennt nur Standard; als "Kann" notiert | | Hybrid-Discs | Offen | MVP erkennt nur Standard; als "Kann" notiert |
@@ -188,11 +188,13 @@ Ein modular aufgebautes System, das bei Disc-Einwurf automatisch den Typ erkennt
unverändert; ergänzt wird nur ein **persistentes MakeMKV-Datenverzeichnis** unverändert; ergänzt wird nur ein **persistentes MakeMKV-Datenverzeichnis**
(`MAKEMKV_DATA_HOST`, im Worker `/root/.MakeMKV`, in der API (`MAKEMKV_DATA_HOST`, im Worker `/root/.MakeMKV`, in der API
`/app/makemkv-data`) samt Bedienung im UI. Begründung: Am 25.07.2026 auf `/app/makemkv-data`) samt Bedienung im UI. Begründung: Am 25.07.2026 auf
der VM nachgemessen — MakeMKV versucht bei einer unbekannten UHD-Disc gar BEIDEN Maschinen nachgemessen — `makemkvcon` unter Linux ruft Disc-Schlüssel
keinen Online-Abruf mehr, und die früher genutzten Schlüssel-Server sind nie ab, die Windows-Version tut es. (Erste Fassung dieses Eintrags behauptete,
weltweit tot; der einzige heute funktionierende Weg ist eine `KEYDB.cfg` MakeMKVs Schlüssel-Kanal sei abgeschaltet; das war falsch und wurde am selben
im Datenverzeichnis. **Rippy liefert und verteilt KEINE Disc-Schlüssel und Tag richtiggestellt.) Rippy nimmt deshalb den Schlüsselspeicher
lädt auch keine herunter** — es hält nur den Platz für eine Datei bereit, `_private_data.tar` einer MakeMKV-Installation entgegen und ersatzweise eine
`KEYDB.cfg`. **Rippy liefert und verteilt KEINE Disc-Schlüssel und
lädt auch keine herunter** — es hält nur den Platz für Dateien bereit,
die der Nutzer selbst mitbringt, zeigt ehrlich an, was dort liegt, und gibt die der Nutzer selbst mitbringt, zeigt ehrlich an, was dort liegt, und gibt
die AACS-Dumps heraus, die MakeMKV ohnehin selbst schreibt. Das ist genau die AACS-Dumps heraus, die MakeMKV ohnehin selbst schreibt. Das ist genau
die Grenze, die `docker/api/makemkv_key.py` in Zeile 14 zieht: die die Grenze, die `docker/api/makemkv_key.py` in Zeile 14 zieht: die
+52 -33
View File
@@ -78,18 +78,26 @@ NICHT als emuliertes CD-ROM (`media=cdrom`), das kann keine SCSI-Kommandos.
(MakeMKV-Forum: „Ultimate UHD Drives Flashing Guide") **und** einen (MakeMKV-Forum: „Ultimate UHD Drives Flashing Guide") **und** einen
passenden Disc-Schlüssel. Normale BD/DVD gehen mit jedem Laufwerk und passenden Disc-Schlüssel. Normale BD/DVD gehen mit jedem Laufwerk und
ohne Schlüssel-Datei. ohne Schlüssel-Datei.
**Der Schlüssel ist heute die eigentliche Hürde.** Am 25.07.2026 auf **Der Schlüssel ist heute die eigentliche Hürde — und zwar aus einem
der Rippy-VM gemessen (Akira UHD, MKB v76, Pressung Dezember 2020): überraschenden Grund.** Am 25.07.2026 auf beiden Maschinen gemessen
Laufwerk und MakeMKV waren in Ordnung — „Using LibreDrive mode (Akira UHD, MKB v76, Pressung Dezember 2020): Laufwerk und MakeMKV
(v06.3)", die Disc wurde gelesen — und trotzdem kam „The volume key is waren in Ordnung — „Using LibreDrive mode (v06.3)", die Disc wurde
unknown for this disc". MakeMKV versucht dabei **gar nicht mehr**, gelesen — und trotzdem kam „The volume key is unknown for this disc".
online einen Schlüssel zu holen, und die früher genutzten Die Ursache:
Schlüssel-Server (`hkdata.fairuse.org`, `hkdata.crabdance.com`) lösen **`makemkvcon` unter Linux holt Disc-Schlüssel nie aus dem Netz. Die
weltweit nicht mehr auf. Ein MakeMKV-Update ändert daran nichts. Windows-Version tut es.**
Der einzige Weg, der heute funktioniert, ist eine Datei **`KEYDB.cfg`** Gemessen: Linux baute in keinem einzigen Lauf eine Verbindung nach
(GROSS geschrieben — Linux unterscheidet Groß- und Kleinschreibung) im draußen auf — geprüft mit leerem und mit gefülltem Schlüsselspeicher,
MakeMKV-Datenverzeichnis. Die legst du unter **Einstellungen → System** mit und ohne `--noscan`, mit `dev:` und `disc:`, und mit erzwungener
ab (siehe unten). frischer Prüfung. Dieselbe Disc am selben Laufwerk unter Windows: „Lade
aktuelle HK …", Verbindung zum Schlüssel-Server, Disc geht auf.
Ein MakeMKV-Update ändert daran nichts, und es ist kein Fehler in
Rippy.
**Der Weg drumherum:** MakeMKV einmal auf einem Windows-PC die Disc
öffnen lassen und die dabei gefüllte Datei `_private_data.tar` bei
Rippy unter **Einstellungen → System** hochladen (siehe unten). Für
Pressungen, die auch MakeMKV nicht kennt, bleibt die **`KEYDB.cfg`**
als Notnagel.
⚠️ **Rippy liefert keine Schlüssel mit, lädt keine herunter und ⚠️ **Rippy liefert keine Schlüssel mit, lädt keine herunter und
verteilt keine.** Rippy stellt nur den Platz für eine Datei bereit, die verteilt keine.** Rippy stellt nur den Platz für eine Datei bereit, die
du selbst mitbringst, und zeigt dir ehrlich an, was dort liegt. du selbst mitbringst, und zeigt dir ehrlich an, was dort liegt.
@@ -131,26 +139,35 @@ MakeMKV-Beta-Key (wechselt ~monatlich, Forum-Thread t=1053) wird hier im
UI eingetragen und gilt ab dem **nächsten Rip** — ohne Rebuild, ohne UI eingetragen und gilt ab dem **nächsten Rip** — ohne Rebuild, ohne
Neustart; er schlägt den Key aus der `.env`. Neustart; er schlägt den Key aus der `.env`.
**Disc-Schlüssel (`KEYDB.cfg`)** — im selben Tab, nur für 4K-UHD nötig: **Disc-Schlüssel für 4K-UHD** — im selben Tab, nur für UHD nötig. Der
Hauptweg zuerst:
- **Status**: Rippy zeigt, ob eine `KEYDB.cfg` im MakeMKV-Datenverzeichnis - **Schlüsselspeicher (`_private_data.tar`)**: Rippy zeigt, **wie viele
liegt, mit Pfad, Größe, Anzahl der Disc-Einträge und Änderungsdatum. Disc-Schlüssel** dieser Worker kennt. Steht dort 0, scheitert jede
- **Hochladen**: Knopf „KEYDB.cfg hochladen", dann deine eigene Datei im unbekannte UHD-Disc.
Datei-Dialog auswählen — mehr ist nicht zu tun. Rippy prüft den Inhalt **So füllst du ihn:** MakeMKV auf einem Windows-PC installieren
auf Plausibilität und lehnt Unsinn (leere Datei, versehentlich geladene (gleicher Beta-Key), Laufwerk anstecken, Disc einmal öffnen — dabei lädt
HTML-Fehlerseite) mit einer deutschen Klartext-Meldung ab, statt ihn MakeMKV die Schlüssel nach. Dann in MakeMKV unter *Preferences →
stillschweigend zu speichern. General* das „MakeMKV data directory" nachschlagen und die Datei
- **Entfernen**: ein Knopf, die Datei ist wieder weg. `_private_data.tar` daraus hier hochladen. Wirkt ab dem nächsten Rip;
für neue Discs gelegentlich wiederholen.
Rippy prüft die Datei und lehnt sie ab, wenn kein einziger Schlüssel
drinsteckt — sonst ändert sich nichts und niemand versteht, warum.
- **`KEYDB.cfg`** (Notnagel): nur nötig, wenn eine Pressung auch mit
gefülltem Speicher nicht aufgeht, MakeMKV sie also selbst nicht kennt.
Hochladen, Status und Entfernen genau wie oben.
- **AACS-Dumps herunterladen**: MakeMKV legt bei jeder unbekannten Disc - **AACS-Dumps herunterladen**: MakeMKV legt bei jeder unbekannten Disc
selbst einen Dump ab. Genau den braucht man, wenn man im MakeMKV-Forum selbst einen Dump ab. Genau den braucht man, wenn man im MakeMKV-Forum
um den Schlüssel für eine neue Pressung bittet — hier holst du ihn dir um den Schlüssel für eine neue Pressung bittet — hier holst du ihn dir
aus dem Container, ohne SSH. aus dem Container, ohne SSH.
Der Beta-Key ist die **Lizenz für die Software**; die `KEYDB.cfg` sind Der Beta-Key ist die **Lizenz für die Software**, der Schlüsselspeicher
**Disc-Schlüssel** — zwei völlig verschiedene Dinge. **Rippy liefert und und die `KEYDB.cfg` sind **Disc-Schlüssel** — zwei völlig verschiedene
lädt keine Disc-Schlüssel**, es hält nur ein persistentes Verzeichnis Dinge. **Rippy liefert und lädt keine Disc-Schlüssel**, es hält nur ein
dafür bereit (`MAKEMKV_DATA_HOST`, siehe Tabelle unten) — rebuild-fest, persistentes Verzeichnis dafür bereit (`MAKEMKV_DATA_HOST`, siehe Tabelle
damit deine Datei einen `docker compose build` überlebt. unten) — rebuild-fest, damit deine Dateien einen
`docker compose build` überleben. Der Schlüsselspeicher ist der
Zwischenspeicher **deiner eigenen** MakeMKV-Installation.
**Updates:** „Auf Updates prüfen" vergleicht mit makemkv.com und den **Updates:** „Auf Updates prüfen" vergleicht mit makemkv.com und den
offiziellen HandBrake-Releases (12 h gecacht). MakeMKV-Update ohne offiziellen HandBrake-Releases (12 h gecacht). MakeMKV-Update ohne
@@ -158,10 +175,11 @@ Code-Änderung: `MAKEMKV_VERSION=x.y.z` in die `.env`, dann
`docker compose build worker && docker compose up -d worker`. `docker compose build worker && docker compose up -d worker`.
⚠️ **Richtigstellung (25.07.2026):** Hier stand früher, neue MakeMKV- ⚠️ **Richtigstellung (25.07.2026):** Hier stand früher, neue MakeMKV-
Versionen brächten „auch die neueste Disc-Schlüssel-Datenbank mit". Das Versionen brächten „auch die neueste Disc-Schlüssel-Datenbank mit". Das
ist widerlegt — auf der VM nachgemessen: MakeMKV holt für eine unbekannte ist widerlegt — MakeMKV liefert überhaupt keine Disc-Schlüssel mit, es
UHD-Disc keinen Schlüssel mehr, weder mitgeliefert noch aus dem Netz. Ein holt sie zur Laufzeit. Und die Linux-Version holt sie nie. Ein Update
Update lohnt für Programmfehler und neue Laufwerke, hilft aber NICHT lohnt für Programmfehler und neue Laufwerke, hilft aber NICHT gegen „The
gegen „The volume key is unknown". Dafür brauchst du die `KEYDB.cfg`. volume key is unknown". Dafür brauchst du den Schlüsselspeicher (siehe
oben).
HandBrake kommt im Docker-Worker bewusst aus Debian (stabil, hinkt der HandBrake kommt im Docker-Worker bewusst aus Debian (stabil, hinkt der
offiziellen Version hinterher); der native Windows-Worker nutzt die offiziellen Version hinterher); der native Windows-Worker nutzt die
aktuelle Version direkt. aktuelle Version direkt.
@@ -196,7 +214,7 @@ bleibt All-in-one.
| `THETVDB_API_KEY` | optional | Serien-Fallback | | `THETVDB_API_KEY` | optional | Serien-Fallback |
| `MAKEMKV_APP_KEY` | optional | MakeMKV-Beta-Key (Forum); DVDs gehen ohne — bequemer: im UI unter Einstellungen → System pflegen | | `MAKEMKV_APP_KEY` | optional | MakeMKV-Beta-Key (Forum); DVDs gehen ohne — bequemer: im UI unter Einstellungen → System pflegen |
| `MAKEMKV_URL_BASE` | optional | alternative Download-Quelle für den Image-Build | | `MAKEMKV_URL_BASE` | optional | alternative Download-Quelle für den Image-Build |
| `MAKEMKV_DATA_HOST` | optional | Host-Verzeichnis für MakeMKVs Daten (Default `/srv/rippy/makemkv`) — hier liegen deine `KEYDB.cfg` und die AACS-Dumps; persistent, überlebt jeden Rebuild | | `MAKEMKV_DATA_HOST` | optional | Host-Verzeichnis für MakeMKVs Daten (Default `/srv/rippy/makemkv`) — hier liegen dein Schlüsselspeicher `_private_data.tar`, eine etwaige `KEYDB.cfg` und die AACS-Dumps; persistent, überlebt jeden Rebuild |
| `OPTICAL_SR` | je Host | Host-Pfad des CD-ROM-Knotens (Default `/dev/sr0`) — siehe „Laufwerk anpassen" | | `OPTICAL_SR` | je Host | Host-Pfad des CD-ROM-Knotens (Default `/dev/sr0`) — siehe „Laufwerk anpassen" |
| `OPTICAL_SG` | je Host | Host-Pfad des sg-Knotens des Laufwerks (Default `/dev/sg1`; oft `/dev/sg0`) | | `OPTICAL_SG` | je Host | Host-Pfad des sg-Knotens des Laufwerks (Default `/dev/sg1`; oft `/dev/sg0`) |
| `POSTGRES_PASSWORD` | optional | DB-Passwort (Default `rippy`) — für exponierte Umgebungen ein starkes Passwort setzen | | `POSTGRES_PASSWORD` | optional | DB-Passwort (Default `rippy`) — für exponierte Umgebungen ein starkes Passwort setzen |
@@ -228,8 +246,9 @@ Voraussetzungen auf dem Ziel-Host:
4. MakeMKV-Datenverzeichnis anlegen: `mkdir -p /srv/rippy/makemkv` (oder 4. MakeMKV-Datenverzeichnis anlegen: `mkdir -p /srv/rippy/makemkv` (oder
eigenen Pfad über `MAKEMKV_DATA_HOST` in der `.env`). Dort liegen eigenen Pfad über `MAKEMKV_DATA_HOST` in der `.env`). Dort liegen
MakeMKVs Programmzustand, die AACS-Dumps und — falls du 4K-UHD rippst — MakeMKVs Programmzustand, die AACS-Dumps und — falls du 4K-UHD rippst —
deine eigene `KEYDB.cfg`. Das Verzeichnis gehört dem Host, damit ein dein Schlüsselspeicher (`_private_data.tar`) sowie eine etwaige
`docker compose build` deine Datei nicht wegwirft. `KEYDB.cfg`. Das Verzeichnis gehört dem Host, damit ein
`docker compose build` deine Dateien nicht wegwirft.
Dann wie im Schnellstart: klonen, `.env` füllen, `docker compose up -d Dann wie im Schnellstart: klonen, `.env` füllen, `docker compose up -d
--build`, `http://<host>` öffnen — der Einrichtungs-Assistent führt durch --build`, `http://<host>` öffnen — der Einrichtungs-Assistent führt durch
+68
View File
@@ -430,6 +430,13 @@ lösen weltweit nicht mehr auf. **Fazit: Ein MakeMKV-Update löst das
nicht** (das behauptete v3.3 — dort richtiggestellt). Der einzige heute nicht** (das behauptete v3.3 — dort richtiggestellt). Der einzige heute
funktionierende Weg ist eine `KEYDB.cfg` im MakeMKV-Datenverzeichnis. 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:** **Gebaut:**
- [x] **Persistentes Datenverzeichnis**: `${MAKEMKV_DATA_HOST:-/srv/rippy/makemkv}` - [x] **Persistentes Datenverzeichnis**: `${MAKEMKV_DATA_HOST:-/srv/rippy/makemkv}`
vom Host gemountet — Worker `/root/.MakeMKV`, API `/app/makemkv-data`, vom Host gemountet — Worker `/root/.MakeMKV`, API `/app/makemkv-data`,
@@ -466,6 +473,10 @@ funktionierende Weg ist eine `KEYDB.cfg` im MakeMKV-Datenverzeichnis.
- [ ] Damit bleibt auch der volle Transcode-E2E an einer UHD weiter offen - [ ] Damit bleibt auch der volle Transcode-E2E an einer UHD weiter offen
(siehe SAVEPOINT v3.7) — an normalen BD/DVD ist die Kette bewiesen. (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 **Ausdrücklich nicht gebaut (und wird es auch nicht):** Rippy liefert
keine Disc-Schlüssel mit, lädt keine herunter und verteilt keine. Es 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 stellt nur den Platz für eine Datei bereit, die der Nutzer selbst
@@ -473,6 +484,63 @@ 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:**
- [x] **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.
- [x] **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.
- [x] **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.
- [x] **Fehlertext** in `tasks.py` sagt den Windows-Weg an und nennt die
Anzahl bekannter Schlüssel dieses Workers.
- [x] **`caps.py`** meldet `schluessel` je Worker.
- [x] **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 ## Ideen-Katalog (Rest) — bewusst offen
1. **Design 2.0** — an Gemini übergeben (24.07.2026). Vollständiges 1. **Design 2.0** — an Gemini übergeben (24.07.2026). Vollständiges
+64 -1
View File
@@ -1,6 +1,69 @@
# SAVEPOINT — Rippy # SAVEPOINT — Rippy
## Aktueller Stand: v3.10 — 4K-UHD: KEYDB.cfg statt Warten auf MakeMKV (25.07.2026) ## Aktueller 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 - **Der Befund (am 25.07. live auf der VM im Worker-Container
nachgemessen — kein Verdacht, alles belegt):** Eine 4K-UHD (Akira, nachgemessen — kein Verdacht, alles belegt):** Eine 4K-UHD (Akira,
+57
View File
@@ -1288,6 +1288,63 @@ async def delete_keydb():
return status return status
@app.get("/system/keystore")
async def get_keystore():
"""Wie viele Disc-Schlüssel kennt diese Rippy-Installation?
Der Schlüsselspeicher (_private_data.tar) ist MakeMKVs eigener Vorrat.
Unter Windows füllt MakeMKV ihn selbst; unter Linux nie — deshalb muss er
hier von Hand hereingereicht werden (Befund 25.07.2026, siehe
makemkv_daten.py). Fehlt er, ist das der Normalfall: 200 mit
vorhanden=false, nie 404.
"""
def sammle():
return makemkv_daten.schluesselspeicher_status()
return await asyncio.to_thread(sammle)
@app.post("/system/keystore")
async def set_keystore(request: Request):
"""Nimmt den Schlüsselspeicher einer MakeMKV-Installation entgegen.
Der Rohkörper der Anfrage IST die Datei — bewusst kein Multipart-Upload
(python-multipart fehlt) und bewusst kein JSON: _private_data.tar ist
binär, und Base64 würde sie nur unnötig aufblähen.
Wirkt ab dem NÄCHSTEN Rip: makemkvcon liest den Speicher beim Start.
"""
rohdaten = await request.body()
def pruefe_und_schreibe():
# Prüfung liest ein mehrere MB grosses tar — gehört deshalb mit in
# den Thread und nicht in die Ereignisschleife.
fehler = makemkv_daten.private_data_pruefen(rohdaten)
if fehler:
return fehler, None
return "", makemkv_daten.private_data_schreiben(rohdaten)
try:
fehler, status = await asyncio.to_thread(pruefe_und_schreibe)
except OSError as e:
raise HTTPException(
status_code=500,
detail=(
f"Schlüsselspeicher konnte nicht geschrieben werden: {e}. "
"Prüfe, ob das MakeMKV-Datenverzeichnis auf der VM existiert "
"und beschreibbar ist (Standard: /srv/rippy/makemkv)."
),
)
if fehler:
raise HTTPException(status_code=422, detail=fehler)
await asyncio.to_thread(
db.add_log, "success", "makemkv-keydb",
f"Schlüsselspeicher übernommen: {status['schluessel']} Disc-Schlüssel, "
f"{status['groesse_bytes']} Bytes. Wirkt ab dem NÄCHSTEN Rip.",
)
return status
@app.get("/system/aacs-dumps") @app.get("/system/aacs-dumps")
async def get_aacs_dumps(): async def get_aacs_dumps():
"""AACS-Dumps, die MakeMKV selbst abgelegt hat (neueste zuerst). """AACS-Dumps, die MakeMKV selbst abgelegt hat (neueste zuerst).
+157 -24
View File
@@ -1,35 +1,51 @@
"""MakeMKV-Datenverzeichnis: KEYDB.cfg, AACS-Dumps, settings.conf. """MakeMKV-Datenverzeichnis: Schluesselspeicher, KEYDB.cfg, AACS-Dumps.
WARUM ES DIESE DATEI GIBT (Befund 25.07.2026, live im Worker nachgemessen): WARUM ES DIESE DATEI GIBT (Befund 25.07.2026, auf BEIDEN Maschinen gemessen):
Bei 4K-UHD-Discs meldet MakeMKV "The volume key is unknown for this disc". 4K-UHD-Discs scheiterten mit "The volume key is unknown for this disc". Die
Das Laufwerk ist dabei in Ordnung makemkvcon meldet "Using LibreDrive mode Ursache ist weder die Disc noch das Laufwerk LibreDrive v06.3 laeuft und
(v06.3)" und liest die Disc — MakeMKV kennt nur den Schluessel DIESER Pressung MakeMKV liest die Disc sondern:
nicht. Und es holt ihn NICHT mehr online nach:
* /root/.MakeMKV/_private_data.tar enthielt ausser der Index-Datei keine makemkvcon unter LINUX ruft die Disc-Schluessel nie ab.
einzige hkd_*.bin, also nie einen heruntergeladenen Schluessel; Die Windows-Version tut es.
* auch mit erzwungener frischer Pruefung (update.conf geloescht, Meldung
5074 belegt den Web-Kontakt) und mit app_UpdateEnable = "1" kam keiner;
* die im MakeMKV-Forum dokumentierten Schluessel-Server hkdata.fairuse.org
und hkdata.crabdance.com loesen weltweit nicht mehr auf (gegen Fritz!Box,
8.8.8.8 und 1.1.1.1 geprueft: NXDOMAIN).
Betroffen war Akira UHD (MKB v76, Pressung von Dezember 2020) also gerade Gemessen, nicht vermutet:
KEINE Neuerscheinung. Die bisherige Fehlermeldung ("Disc neuer als die * Linux: in KEINEM Lauf auch nur eine Verbindung nach draussen. Geprueft mit
Schluessel-Datenbank, mit einem der naechsten Updates rippbar") war damit leerem UND mit gefuelltem Schluesselspeicher, mit und ohne --noscan, mit
schlicht falsch. dev:/dev/sr0 und mit disc:0, und mit erzwungener frischer Pruefung
(update.conf geloescht, Meldung 5074 belegt den Web-Kontakt). Immer:
keine Verbindung, kein Schluessel.
* Windows, dieselbe Disc, dasselbe Laufwerk: Meldung 3338 "Downloading
latest HK to ...", Verbindung nach 185.84.108.20:443
(web33.majordomo.ru), _private_data.tar waechst und die Disc geht auf
(TCOUNT:5, "Operation successfully completed").
* Der Code dafuer steckt auch im Linux-Binary: die Meldungsvorlage
"Downloading latest %1 to %2 ..." steht in makemkvcon. Sie loest nur nie
aus. Gleiches Symptom im Forum, seit Jahren offen und unbeantwortet.
Der einzige heute funktionierende Weg ist eine KEYDB.cfg im FRUEHERE FEHLDIAGNOSE, bewusst festgehalten: An dieser Stelle stand zuerst,
MakeMKV-Datenverzeichnis. Rippy liefert KEINE Schluessel mit, laedt keine MakeMKVs Schluessel-Kanal sei abgeschaltet. Das war FALSCH. Die Herleitung
herunter und verteilt keine es stellt nur den Platz dafuer bereit und zeigt stuetzte sich auf zwei Hostnamen aus alten Forumsbeitraegen
ehrlich an, was dort liegt. Die Datei bringt der Nutzer selbst mit. (hkdata.fairuse.org, hkdata.crabdance.com), die tatsaechlich nicht mehr
aufloesen MakeMKV benutzt sie aber laengst nicht mehr. Der Dienst lebt, der
Worker erreicht ihn sogar; er wird unter Linux nur nie gefragt.
WAS DARAUS FOLGT: Der Schluesselspeicher (_private_data.tar) muss von einer
MakeMKV-Installation kommen, die ihn wirklich abruft praktisch von Windows.
Rippy nimmt ihn unter Einstellungen -> System entgegen. Die KEYDB.cfg bleibt
der Notnagel fuer Pressungen, die auch MakeMKV selbst nicht kennt.
Rippy liefert KEINE Schluessel mit, laedt keine herunter und verteilt keine.
Es verwaltet nur, was der Nutzer selbst mitbringt.
QUELLEN (AGENTS Regel D externe Schnittstellen nie aus dem Kopf): QUELLEN (AGENTS Regel D externe Schnittstellen nie aus dem Kopf):
* Datenverzeichnis und Dateiname GROSS geschrieben (unter Linux * Linux laedt keine Hashed Keys dasselbe Symptom, mehrfach berichtet:
https://forum.makemkv.com/forum/viewtopic.php?t=25782
https://forum.makemkv.com/forum/viewtopic.php?t=34022
* Schluessel liegen als hkd_*.bin in _private_data.tar:
https://forum.makemkv.com/forum/viewtopic.php?t=32675
* Datenverzeichnis und Dateiname KEYDB.cfg GROSS geschrieben (unter Linux
case-sensitiv), dort geloest mit "cp KEYDB.cfg ~/.MakeMKV/": case-sensitiv), dort geloest mit "cp KEYDB.cfg ~/.MakeMKV/":
https://forum.makemkv.com/forum/viewtopic.php?t=30636 https://forum.makemkv.com/forum/viewtopic.php?t=30636
* Heruntergeladene Schluessel liegen als hkd_*.bin in _private_data.tar:
https://forum.makemkv.com/forum/viewtopic.php?t=32675
* Zeilenformat der KEYDB.cfg (libaacs): Disc-Kennung = 40 Hex-Zeichen, * Zeilenformat der KEYDB.cfg (libaacs): Disc-Kennung = 40 Hex-Zeichen,
optional mit 0x-Praefix, dann "= Titel", danach optionale Felder wie optional mit 0x-Praefix, dann "= Titel", danach optionale Felder wie
"| V | <32 Hex>"; Zeilen ab ";" sind Kommentare: "| V | <32 Hex>"; Zeilen ab ";" sind Kommentare:
@@ -42,8 +58,10 @@ Images brauchen sie, ein gemeinsames Paket gibt es in diesem Projekt nicht
(gleiche Lage wie bei db.py). Aenderungen IMMER in BEIDEN Dateien nachziehen. (gleiche Lage wie bei db.py). Aenderungen IMMER in BEIDEN Dateien nachziehen.
""" """
import io
import os import os
import re import re
import tarfile
from datetime import datetime, timezone from datetime import datetime, timezone
# Container-Pfad aus der Umgebung: /root/.MakeMKV im Worker (nur dort sucht # Container-Pfad aus der Umgebung: /root/.MakeMKV im Worker (nur dort sucht
@@ -226,6 +244,121 @@ def dumps_auflisten(daten_dir: str = None) -> list:
return liste return liste
# --- Schluesselspeicher (_private_data.tar) -------------------------------
#
# Das ist MakeMKVs eigener Speicher fuer die "Hashed Keys": ein tar-Archiv mit
# hkd_*.bin-Eintraegen. Unter Windows fuellt MakeMKV es selbst (Meldung 3338),
# unter Linux nie — siehe Modul-Kopf. Rippy nimmt die Datei deshalb entgegen
# und legt sie ins Datenverzeichnis; MakeMKV liest sie beim naechsten Start.
PRIVATE_DATA_NAME = "_private_data.tar"
# Der Speicher lag am 25.07.2026 bei rund 6 MB und waechst mit jeder neuen
# Pressung. 64 MB sind reichlich Luft — und derselbe Wert wie
# client_max_body_size in docker/ui/nginx.conf: waere die Grenze hier hoeher,
# wuerde nginx den Upload abweisen, bevor die API ihn ueberhaupt sieht.
MAX_PRIVATE_DATA_BYTES = 64 * 1024 * 1024
def private_data_pfad(daten_dir: str = None) -> str:
"""Voller Pfad zum Schluesselspeicher im Datenverzeichnis."""
return os.path.join(daten_dir or DATEN_DIR, PRIVATE_DATA_NAME)
def zaehle_schluessel(rohdaten: bytes) -> int:
"""Anzahl der hkd_*.bin-Eintraege im Archiv (pure Funktion, testbar).
Das ist die ehrliche Kennzahl fuer "wie viele Disc-Schluessel kennt diese
Installation". Ein frischer, leerer Speicher enthaelt nur eine
Index-Datei und kommt hier auf 0 genau der Zustand, in dem jede
unbekannte UHD-Disc scheitert.
"""
try:
with tarfile.open(fileobj=io.BytesIO(rohdaten)) as archiv:
return sum(1 for name in archiv.getnames() if name.startswith("hkd_"))
except (tarfile.TarError, OSError, EOFError):
return 0
def private_data_pruefen(rohdaten: bytes) -> str:
"""Prueft hochgeladene Rohdaten; deutscher Fehlertext oder "".
Faengt die beiden Bedienfehler ab, die sonst still danebengehen: eine
voellig andere Datei hochladen, oder den Speicher einer Installation, die
selbst noch keine Schluessel geholt hat (dann aendert sich nichts, und
niemand versteht warum).
"""
if not rohdaten:
return "Die Datei ist leer."
if len(rohdaten) > MAX_PRIVATE_DATA_BYTES:
return (
"Die Datei ist groesser als "
f"{MAX_PRIVATE_DATA_BYTES // (1024 * 1024)} MB — das ist kein "
"MakeMKV-Schluesselspeicher."
)
try:
with tarfile.open(fileobj=io.BytesIO(rohdaten)) as archiv:
namen = archiv.getnames()
except (tarfile.TarError, OSError, EOFError):
return (
"Das ist kein tar-Archiv. Erwartet wird die Datei "
f"{PRIVATE_DATA_NAME} aus dem MakeMKV-Datenverzeichnis."
)
if not any(name.startswith("hkd_") for name in namen):
return (
"In dieser Datei steckt kein einziger Schluessel (kein hkd_*.bin). "
"Sie stammt vermutlich von einer MakeMKV-Installation, die selbst "
"noch keine geholt hat — oeffne dort erst einmal eine Disc."
)
return ""
def schluesselspeicher_status(daten_dir: str = None) -> dict:
"""Zustand des Schluesselspeichers. Fehlt er, ist das kein Fehler."""
pfad = private_data_pfad(daten_dir)
try:
angaben = os.stat(pfad)
with open(pfad, "rb") as datei:
schluessel = zaehle_schluessel(datei.read())
except OSError:
return {
"vorhanden": False,
"pfad": pfad,
"groesse_bytes": 0,
"schluessel": 0,
"geaendert": "",
}
return {
"vorhanden": True,
"pfad": pfad,
"groesse_bytes": angaben.st_size,
"schluessel": schluessel,
"geaendert": _iso(angaben.st_mtime),
}
def private_data_schreiben(rohdaten: bytes, daten_dir: str = None) -> dict:
"""Legt den Schluesselspeicher atomar ab und meldet den neuen Zustand.
Atomar aus demselben Grund wie bei der KEYDB.cfg: waehrend ein Rip laeuft,
darf makemkvcon nie ein halb geschriebenes Archiv sehen.
"""
pfad = private_data_pfad(daten_dir)
os.makedirs(os.path.dirname(pfad), exist_ok=True)
neben = pfad + ".neu"
try:
with open(neben, "wb") as datei:
datei.write(rohdaten)
os.replace(neben, pfad)
except OSError:
try:
os.remove(neben)
except OSError:
pass
raise
return schluesselspeicher_status(daten_dir)
def settings_conf_zusammenfuehren(inhalt: str, key: str) -> str: def settings_conf_zusammenfuehren(inhalt: str, key: str) -> str:
"""app_Key setzen, ohne den Rest der settings.conf zu verlieren (pure). """app_Key setzen, ohne den Rest der settings.conf zu verlieren (pure).
+3
View File
@@ -24,6 +24,9 @@ def test_main_importierbar_und_routen_verdrahtet():
# Schlüsseldatei (Befund 25.07.2026 — MakeMKV holt UHD-Schlüssel nicht # Schlüsseldatei (Befund 25.07.2026 — MakeMKV holt UHD-Schlüssel nicht
# mehr online nach). Ohne diese Routen ist die Seite im UI tot. # mehr online nach). Ohne diese Routen ist die Seite im UI tot.
"/system/keydb", "/system/aacs-dumps", "/system/aacs-dumps/{dateiname}", "/system/keydb", "/system/aacs-dumps", "/system/aacs-dumps/{dateiname}",
# Der Hauptweg fuer 4K-UHD (25.07.2026): makemkvcon holt Disc-Schluessel
# unter Linux nie selbst, sie kommen von Hand ueber diesen Endpunkt.
"/system/keystore",
): ):
assert pfad in routen, f"Route {pfad} fehlt" assert pfad in routen, f"Route {pfad} fehlt"
+22 -18
View File
@@ -141,8 +141,8 @@ export default function AnleitungPage() {
HandBrake-Releases. Gibt es ein MakeMKV-Update, zeigt Rippy den fertigen HandBrake-Releases. Gibt es ein MakeMKV-Update, zeigt Rippy den fertigen
Update-Befehl an neue Versionen bringen bessere Laufwerks-Unterstützung und Update-Befehl an neue Versionen bringen bessere Laufwerks-Unterstützung und
Fehlerbehebungen. <span className={fett}>Disc-Schlüssel für 4K-UHD kommen dagegen nicht Fehlerbehebungen. <span className={fett}>Disc-Schlüssel für 4K-UHD kommen dagegen nicht
aus einem Update</span>, sondern nur aus der Datei <code>KEYDB.cfg</code>, die du selbst aus einem Update</span> die holt MakeMKV zur Laufzeit, und die Linux-Version tut das
unter Einstellungen System hochlädst (mehr dazu unter Häufige Fragen"). nie. Wie du sie trotzdem bekommst, steht unter Häufige Fragen".
</p> </p>
</Abschnitt> </Abschnitt>
@@ -161,30 +161,34 @@ export default function AnleitungPage() {
Fingerabdruck. Nochmal rippen geht trotzdem der Hinweis verhindert nur Versehen. Fingerabdruck. Nochmal rippen geht trotzdem der Hinweis verhindert nur Versehen.
</p> </p>
{/* {/*
25.07.2026 auf der Rippy-VM nachgemessen und komplett neu geschrieben: 25.07.2026 auf BEIDEN Maschinen nachgemessen und erneut korrigiert. Es
Hier stand vorher, ein MakeMKV-Update mache die Disc rippbar. Das stimmt stand hier nacheinander zweierlei Falsches: erst "ein MakeMKV-Update macht
nicht MakeMKV versucht bei einer unbekannten UHD-Pressung gar nicht mehr, die Disc rippbar", dann "MakeMKVs Schluessel-Kanal ist tot". Richtig ist:
online einen Schluessel zu holen, und die dokumentierten Schluessel-Server makemkvcon unter Linux ruft die Schluessel nie ab, die Windows-Version
(hkdata.fairuse.org, hkdata.crabdance.com) loesen weltweit nicht mehr auf. schon (Meldung 3338, Verbindung nach 185.84.108.20:443).
*/} */}
<p> <p>
<span className={fett}>4K-UHD schlägt fehl mit volume key is unknown"?</span> Das Laufwerk <span className={fett}>4K-UHD schlägt fehl mit volume key is unknown"?</span> Das Laufwerk
liest die Disc einwandfrei (LibreDrive) MakeMKV fehlt nur der Schlüssel dieser Pressung. liest die Disc einwandfrei (LibreDrive) MakeMKV fehlt nur der Schlüssel dieser Pressung.
Früher holte MakeMKV solche Schlüssel selbst aus dem Netz; dieser Kanal liefert heute nichts Der Grund liegt nicht bei dir und nicht bei Rippy: <span className={fett}>die Linux-Version
mehr, und ein MakeMKV-Update ändert daran nichts. von MakeMKV holt Disc-Schlüssel nie selbst aus dem Netz</span>. Die Windows-Version tut es.
Ein MakeMKV-Update ändert daran nichts.
</p> </p>
<p> <p>
Der einzige Weg, der heute funktioniert, ist eine Datei namens <code>KEYDB.cfg</code> <span className={fett}>Der Weg drumherum:</span> MakeMKV einmalig auf einem Windows-PC
eine Textliste mit Disc-Schlüsseln, die du selbst mitbringst. Unter Einstellungen System installieren (gleicher Beta-Key), das Laufwerk dort anstecken, die Disc öffnen MakeMKV
hochladen, sie wirkt ab dem nächsten Rip. <span className={fett}>Rippy liefert keine lädt die Schlüssel dabei nach. Dann in MakeMKV unter <em>Preferences General</em> das
Schlüssel mit und lädt auch keine herunter</span> Rippy stellt nur den Platz für deine MakeMKV data directory" nachschlagen und die Datei <code>_private_data.tar</code> daraus
Datei bereit und zeigt dir an, was dort liegt. bei Rippy unter Einstellungen System hochladen. Wirkt ab dem nächsten Rip. Für neue
Discs gelegentlich wiederholen der Block dort zeigt dir, wie viele Schlüssel Rippy kennt.
</p> </p>
<p> <p>
Der <span className={fett}>AACS-Dump</span> zu einer gescheiterten Disc bleibt jetzt Geht eine Pressung auch damit nicht auf, kennt MakeMKV sie selbst nicht. Dann bleiben zwei
erhalten und steht unter Einstellungen System zum Herunterladen. Ihn kannst du im Dinge: eine <code>KEYDB.cfg</code> (ebenfalls dort hochladbar, der Notnagel), oder den
MakeMKV-Forum im Bereich Ultra HD Blu-ray" einreichen daraus lässt sich der Schlüssel <span className={fett}> AACS-Dump</span> im MakeMKV-Forum im Bereich Ultra HD Blu-ray"
für deine Pressung ermitteln, den du dann in deine <code>KEYDB.cfg</code> einträgst. einreichen der bleibt jetzt erhalten und steht unter Einstellungen System zum
Herunterladen. <span className={fett}>Rippy liefert keine Schlüssel mit und lädt keine
herunter</span> es verwaltet nur, was du selbst mitbringst.
</p> </p>
<p> <p>
<span className={fett}>Neu komprimieren" fehlt bei einem Fehl-Job?</span> Der Knopf <span className={fett}>Neu komprimieren" fehlt bei einem Fehl-Job?</span> Der Knopf
+142 -32
View File
@@ -77,6 +77,15 @@ interface KeydbStatus {
geaendert: string geaendert: string
} }
// Antwort von GET/POST /system/keystore — MakeMKVs eigener Schluesselvorrat.
interface KeystoreStatus {
vorhanden: boolean
pfad: string
groesse_bytes: number
schluessel: number
geaendert: string
}
// Ein AACS-Dump aus GET /system/aacs-dumps. // Ein AACS-Dump aus GET /system/aacs-dumps.
interface AacsDump { interface AacsDump {
name: string name: string
@@ -130,6 +139,9 @@ export default function SettingsPage() {
const [keydbBusy, setKeydbBusy] = useState(false) const [keydbBusy, setKeydbBusy] = useState(false)
const [dumps, setDumps] = useState<AacsDump[]>([]) const [dumps, setDumps] = useState<AacsDump[]>([])
const keydbInput = useRef<HTMLInputElement>(null) const keydbInput = useRef<HTMLInputElement>(null)
const [keystore, setKeystore] = useState<KeystoreStatus | null>(null)
const [keystoreBusy, setKeystoreBusy] = useState(false)
const keystoreInput = useRef<HTMLInputElement>(null)
const { toast } = useToast() const { toast } = useToast()
@@ -155,6 +167,7 @@ export default function SettingsPage() {
// nicht das, was wir gerade hochgeschickt haben. // nicht das, was wir gerade hochgeschickt haben.
const keydbLaden = () => { const keydbLaden = () => {
api.get('/system/keydb').then(r => setKeydb(r.data)).catch(() => setKeydb(null)) api.get('/system/keydb').then(r => setKeydb(r.data)).catch(() => setKeydb(null))
api.get('/system/keystore').then(r => setKeystore(r.data)).catch(() => setKeystore(null))
api.get('/system/aacs-dumps').then(r => setDumps(r.data?.dumps || [])).catch(() => setDumps([])) api.get('/system/aacs-dumps').then(r => setDumps(r.data?.dumps || [])).catch(() => setDumps([]))
// Die Worker-Plaketten oben kommen aus /capabilities und stammen aus dem // Die Worker-Plaketten oben kommen aus /capabilities und stammen aus dem
// letzten Herzschlag des Workers (minuetlich) — ohne dieses Nachladen // letzten Herzschlag des Workers (minuetlich) — ohne dieses Nachladen
@@ -180,6 +193,25 @@ export default function SettingsPage() {
} }
} }
const keystoreHochladen = async (datei: File) => {
setKeystoreBusy(true)
try {
// Die Datei wandert als roher Anfrage-Körper zur API — _private_data.tar
// ist binär, JSON oder Base64 wäre nur unnötiger Ballast, und Multipart
// kann die API nicht (kein python-multipart).
await api.post('/system/keystore', datei, {
headers: { 'Content-Type': 'application/octet-stream' },
})
keydbLaden()
toast('success', 'Schlüsselspeicher übernommen — wirkt ab dem nächsten Rip.')
} catch (e: any) {
toast('error', e?.response?.data?.detail
|| 'Übernahme fehlgeschlagen — ist das wirklich die Datei _private_data.tar, und läuft die API?')
} finally {
setKeystoreBusy(false)
}
}
const keydbEntfernen = async () => { const keydbEntfernen = async () => {
setKeydbBusy(true) setKeydbBusy(true)
try { try {
@@ -221,6 +253,9 @@ export default function SettingsPage() {
api.get('/system/keydb') api.get('/system/keydb')
.then(r => setKeydb(r.data)) .then(r => setKeydb(r.data))
.catch(() => setKeydb(null)) .catch(() => setKeydb(null))
api.get('/system/keystore')
.then(r => setKeystore(r.data))
.catch(() => setKeystore(null))
api.get('/system/aacs-dumps') api.get('/system/aacs-dumps')
.then(r => setDumps(r.data?.dumps || [])) .then(r => setDumps(r.data?.dumps || []))
.catch(() => setDumps([])) .catch(() => setDumps([]))
@@ -726,20 +761,24 @@ export default function SettingsPage() {
HandBrake {w.info.handbrake} HandBrake {w.info.handbrake}
</span> </span>
)} )}
{/* Nur das Verzeichnis des rippenden Workers zaehlt — deshalb je Worker. */} {/*
{w.info?.keydb === 'ja' && ( Nur das Verzeichnis des rippenden Workers zaehlt deshalb je Worker.
Die Zahl der Disc-Schluessel ist die entscheidende Angabe fuer 4K-UHD:
0 heisst, dass JEDE unbekannte UHD-Disc scheitert.
*/}
{w.info?.schluessel && w.info.schluessel !== '0' && w.info.schluessel !== 'unbekannt' && (
<span className="text-xs px-2.5 py-0.5 rounded-md font-medium bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 border border-emerald-500/30"> <span className="text-xs px-2.5 py-0.5 rounded-md font-medium bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 border border-emerald-500/30">
KEYDB.cfg vorhanden {w.info.schluessel} Disc-Schlüssel
</span> </span>
)} )}
{w.info?.keydb === 'nein' && ( {w.info?.schluessel === '0' && (
<span className="text-xs px-2.5 py-0.5 rounded-md font-medium bg-amber-500/15 text-amber-600 dark:text-amber-400 border border-amber-500/30"> <span className="text-xs px-2.5 py-0.5 rounded-md font-medium bg-amber-500/15 text-amber-600 dark:text-amber-400 border border-amber-500/30">
keine KEYDB.cfg keine Disc-Schlüssel 4K-UHD scheitert
</span> </span>
)} )}
{w.info?.keydb === 'unbekannt' && ( {w.info?.keydb === 'ja' && (
<span className="text-xs px-2.5 py-0.5 rounded-md font-medium bg-slate-200 dark:bg-slate-800 text-slate-500 dark:text-slate-400 border border-slate-300 dark:border-slate-700"> <span className="text-xs px-2.5 py-0.5 rounded-md font-medium bg-slate-200 dark:bg-slate-800 text-slate-500 dark:text-slate-400 border border-slate-300 dark:border-slate-700">
KEYDB.cfg unbekannt + KEYDB.cfg
</span> </span>
)} )}
</div> </div>
@@ -747,19 +786,17 @@ export default function SettingsPage() {
)} )}
{/* {/*
Bis 25.07.2026 stand hier, MakeMKV-Updates braechten die neueste Bis 25.07.2026 stand hier, MakeMKV-Updates braechten die neueste
Disc-Schluessel-Datenbank mit. Auf der Rippy-VM nachgemessen: falsch. Disc-Schluessel-Datenbank mit. Nachgemessen: falsch MakeMKV liefert
MakeMKV hat gar keine mitgelieferte Schluessel-Datenbank, und der gar keine Schluessel mit, es holt sie zur Laufzeit. Und die
Online-Kanal liefert nichts mehr (die Server hkdata.fairuse.org und Linux-Version holt sie nie (kein einziger Verbindungsversuch, auf
hkdata.crabdance.com loesen weltweit nicht mehr auf). Updates bringen beiden Maschinen verglichen). Deshalb der Schluesselspeicher unten.
Laufwerks-Firmware-Unterstuetzung und Fehlerbehebungen Schluessel
fuer neue UHD-Pressungen kommen ausschliesslich aus der KEYDB.cfg.
*/} */}
<p className="text-xs mt-3 pt-3 border-t border-slate-200/60 dark:border-slate-800 text-slate-500 dark:text-slate-400"> <p className="text-xs mt-3 pt-3 border-t border-slate-200/60 dark:border-slate-800 text-slate-500 dark:text-slate-400">
<strong className="text-slate-700 dark:text-slate-300">MakeMKV</strong> lässt sich aktuell halten <strong className="text-slate-700 dark:text-slate-300">MakeMKV</strong> lässt sich aktuell halten
(Update-Check unten; Version über <code>MAKEMKV_VERSION</code> + Rebuild) neue Versionen bringen (Update-Check unten; Version über <code>MAKEMKV_VERSION</code> + Rebuild) neue Versionen bringen
vor allem Laufwerks-Unterstützung und Fehlerbehebungen. <strong>Disc-Schlüssel für neue vor allem Laufwerks-Unterstützung und Fehlerbehebungen. <strong>Disc-Schlüssel für 4K-UHD kommen
4K-UHD-Pressungen kommen dagegen NICHT aus einem Update</strong>, sondern nur aus der KEYDB.cfg NICHT aus einem Update</strong> die holt MakeMKV zur Laufzeit, und die Linux-Version tut das
im Block darunter. nie. Deshalb der Block Disc-Schlüssel für 4K-UHD" weiter unten.
{' '}<strong className="text-slate-700 dark:text-slate-300">HandBrake</strong> im eingebauten {' '}<strong className="text-slate-700 dark:text-slate-300">HandBrake</strong> im eingebauten
Docker-Worker ist bewusst die stabile <strong>Debian-Version</strong> für die Kompression völlig Docker-Worker ist bewusst die stabile <strong>Debian-Version</strong> für die Kompression völlig
ausreichend und wird <strong>nicht separat aktualisiert</strong>. Native Worker (Windows) holen ausreichend und wird <strong>nicht separat aktualisiert</strong>. Native Worker (Windows) holen
@@ -776,18 +813,91 @@ export default function SettingsPage() {
/> />
{/* {/*
MakeMKV-Schluessel (KEYDB.cfg) Befund vom 25.07.2026 auf der Rippy-VM: Schluesselspeicher der Hauptweg fuer 4K-UHD (Befund 25.07.2026,
MakeMKV versucht bei einer unbekannten UHD-Pressung gar nicht mehr, online auf beiden Maschinen gemessen): makemkvcon holt Disc-Schluessel
einen Schluessel zu holen, und die dokumentierten Schluessel-Server sind tot. unter Linux NIE selbst, die Windows-Version tut es (Meldung 3338,
Der einzige heute funktionierende Weg ist eine Datei KEYDB.cfg (GROSS Verbindung nach 185.84.108.20:443). Deshalb wird der Vorrat hier
geschrieben, unter Linux case-sensitiv) im MakeMKV-Datenverzeichnis. von Hand hereingereicht. Frueher stand an dieser Stelle die These,
Rippy stellt nur den Platz dafuer bereit mitgeliefert wird nichts. MakeMKVs Schluessel-Kanal sei abgeschaltet das war falsch.
*/}
<div className="p-4 rounded-xl border border-slate-200/80 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-950/80 space-y-3">
<div className="flex items-center justify-between">
<p className="text-sm font-semibold text-slate-900 dark:text-slate-200 flex items-center gap-2">
<Database size={16} className="text-amber-500" />
Disc-Schlüssel für 4K-UHD
</p>
<div className="flex items-center gap-2">
<input
type="file"
className="hidden"
ref={keystoreInput}
accept=".tar"
onChange={(e) => {
const datei = e.target.files?.[0]
e.target.value = ''
if (datei) keystoreHochladen(datei)
}}
/>
<Button
variant="amber"
size="sm"
onClick={() => keystoreInput.current?.click()}
disabled={keystoreBusy}
>
<Upload size={14} />
{keystoreBusy ? 'Übernehme…' : '_private_data.tar übernehmen'}
</Button>
</div>
</div>
{keystore?.vorhanden && keystore.schluessel > 0 ? (
<div className="p-3 rounded-lg text-sm bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 border border-emerald-500/30">
<p className="font-semibold">{keystore.schluessel} Disc-Schlüssel vorhanden.</p>
<p className="text-xs mt-1">
{bytesLesbar(keystore.groesse_bytes)} · zuletzt geändert {zeitLesbar(keystore.geaendert)}
</p>
</div>
) : (
<div className="p-3 rounded-lg text-sm bg-amber-500/15 text-amber-600 dark:text-amber-400 border border-amber-500/30">
<p className="font-semibold">Kein einziger Disc-Schlüssel vorhanden.</p>
<p className="text-xs mt-1">
DVDs und normale Blu-rays laufen trotzdem. 4K-UHD-Discs scheitern dagegen mit
The volume key is unknown for this disc" solange hier nichts liegt, jede einzelne.
</p>
</div>
)}
<p className="text-xs text-slate-500 dark:text-slate-400">
<strong className="text-slate-700 dark:text-slate-300">Warum das nötig ist:</strong> MakeMKV
holt sich diese Schlüssel eigentlich selbst aus dem Netz. Die <strong>Linux-Version tut das
nicht</strong> am 25.07.2026 nachgemessen: sie baut dabei nicht eine einzige Verbindung auf.
Die Windows-Version schon. Ein MakeMKV-Update ändert daran nichts, es ist kein Fehler in Rippy.
</p>
<p className="text-xs text-slate-500 dark:text-slate-400">
<strong className="text-slate-700 dark:text-slate-300">So füllst du den Vorrat:</strong> MakeMKV
auf einem Windows-PC installieren (gleicher Beta-Key), das Laufwerk dort anstecken und die Disc
einmal öffnen. MakeMKV lädt die Schlüssel dabei nach. Danach unter <em>Preferences General</em>
das MakeMKV data directory" nachschlagen, die Datei <code>_private_data.tar</code> daraus hier
hochladen fertig. Für neue Discs von Zeit zu Zeit wiederholen.
</p>
<p className="text-xs text-slate-500 dark:text-slate-400">
Das ist der Zwischenspeicher <strong className="text-slate-700 dark:text-slate-300">deiner
eigenen</strong> MakeMKV-Installation, über MakeMKVs offiziellen Weg mit deiner eigenen Lizenz
geholt. Rippy liefert keine Schlüssel mit und lädt keine herunter.
</p>
</div>
{/*
KEYDB.cfg der NOTNAGEL, nicht der Hauptweg. Sie hilft bei Pressungen,
die auch MakeMKV selbst nicht kennt. Der Regelfall laeuft ueber den
Schluesselspeicher im Block darueber. Dateiname GROSS geschrieben, unter
Linux case-sensitiv. Rippy stellt nur den Platz bereit.
*/} */}
<div className="p-4 rounded-xl border border-slate-200/80 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-950/80 space-y-3"> <div className="p-4 rounded-xl border border-slate-200/80 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-950/80 space-y-3">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<p className="text-sm font-semibold text-slate-900 dark:text-slate-200 flex items-center gap-2"> <p className="text-sm font-semibold text-slate-900 dark:text-slate-200 flex items-center gap-2">
<KeyRound size={16} className="text-amber-500" /> <KeyRound size={16} className="text-amber-500" />
MakeMKV-Schlüssel (KEYDB.cfg) KEYDB.cfg (Notnagel)
</p> </p>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{/* {/*
@@ -834,20 +944,20 @@ export default function SettingsPage() {
<p className="text-xs mt-1 font-mono opacity-80">{keydb.pfad}</p> <p className="text-xs mt-1 font-mono opacity-80">{keydb.pfad}</p>
</div> </div>
) : ( ) : (
<div className="p-3 rounded-lg text-sm bg-amber-500/15 text-amber-600 dark:text-amber-400 border border-amber-500/30"> <div className="p-3 rounded-lg text-sm bg-slate-200 dark:bg-slate-800 text-slate-500 dark:text-slate-400 border border-slate-300 dark:border-slate-700">
<p className="font-semibold">Es liegt keine KEYDB.cfg bereit.</p> <p className="font-semibold">Keine KEYDB.cfg hinterlegt.</p>
<p className="text-xs mt-1"> <p className="text-xs mt-1">
DVDs und normale Blu-rays laufen trotzdem. Nur bei 4K-UHD-Discs, deren Schlüssel MakeMKV Das ist normal und meistens auch nicht nötig der Regelfall läuft über den
nicht kennt, bricht der Rip mit The volume key is unknown for this disc" ab. Schlüsselspeicher oben.
</p> </p>
</div> </div>
)} )}
<p className="text-xs text-slate-500 dark:text-slate-400"> <p className="text-xs text-slate-500 dark:text-slate-400">
Die <strong className="text-slate-700 dark:text-slate-300">KEYDB.cfg</strong> ist eine reine Die <strong className="text-slate-700 dark:text-slate-300">KEYDB.cfg</strong> ist eine reine
Textdatei mit Disc-Schlüsseln für 4K-UHD-Blu-rays. MakeMKV holte solche Schlüssel früher selbst Textdatei mit Disc-Schlüsseln. Sie ist der <strong className="text-slate-700 dark:text-slate-300">
aus dem Netz das funktioniert heute nicht mehr, die alten Schlüssel-Server sind abgeschaltet. Notnagel</strong> für den Fall, dass eine Pressung selbst über den Schlüsselspeicher nicht
Ein MakeMKV-Update hilft dagegen nicht. aufgeht also auch MakeMKV sie nicht kennt. Zuerst immer den Weg darüber versuchen.
</p> </p>
<p className="text-xs text-slate-500 dark:text-slate-400"> <p className="text-xs text-slate-500 dark:text-slate-400">
<strong className="text-slate-700 dark:text-slate-300">Wichtig:</strong> Rippy liefert keine <strong className="text-slate-700 dark:text-slate-300">Wichtig:</strong> Rippy liefert keine
@@ -926,9 +1036,9 @@ export default function SettingsPage() {
<p className="text-xs mt-1"> <p className="text-xs mt-1">
Update verfügbar in der .env <code>MAKEMKV_VERSION={updates.makemkv.verfuegbar}</code> setzen, Update verfügbar in der .env <code>MAKEMKV_VERSION={updates.makemkv.verfuegbar}</code> setzen,
dann auf der Rippy-Maschine <code>docker compose build worker &amp;&amp; docker compose up -d worker</code>. dann auf der Rippy-Maschine <code>docker compose build worker &amp;&amp; docker compose up -d worker</code>.
{/* 25.07.2026 richtiggestellt: ein Update bringt KEINE Schluessel — die kommen nur aus der KEYDB.cfg. */} {/* 25.07.2026 richtiggestellt: ein Update bringt KEINE Disc-Schluessel mit. */}
Neue Versionen bringen Laufwerks-Unterstützung und Fehlerbehebungen aber Neue Versionen bringen Laufwerks-Unterstützung und Fehlerbehebungen aber
<strong> keine Disc-Schlüssel</strong>: die kommen ausschließlich aus deiner KEYDB.cfg. <strong> keine Disc-Schlüssel</strong>: die kommen aus dem Schlüsselspeicher.
</p> </p>
) )
: <span className="text-xs ml-1 text-emerald-600 dark:text-emerald-400"> aktuell</span>} : <span className="text-xs ml-1 text-emerald-600 dark:text-emerald-400"> aktuell</span>}
+7
View File
@@ -105,4 +105,11 @@ def werkzeug_versionen() -> dict:
info["keydb"] = "ja" if makemkv_daten.keydb_status().get("vorhanden") else "nein" info["keydb"] = "ja" if makemkv_daten.keydb_status().get("vorhanden") else "nein"
except Exception: except Exception:
info["keydb"] = "unbekannt" info["keydb"] = "unbekannt"
# Die entscheidende Zahl für 4K-UHD: wie viele Disc-Schlüssel kennt
# dieser Worker? 0 heißt, dass jede unbekannte UHD-Disc scheitert —
# makemkvcon holt sie unter Linux nie selbst (Befund 25.07.2026).
try:
info["schluessel"] = str(makemkv_daten.schluesselspeicher_status().get("schluessel", 0))
except Exception:
info["schluessel"] = "unbekannt"
return info return info
+157 -24
View File
@@ -1,35 +1,51 @@
"""MakeMKV-Datenverzeichnis: KEYDB.cfg, AACS-Dumps, settings.conf. """MakeMKV-Datenverzeichnis: Schluesselspeicher, KEYDB.cfg, AACS-Dumps.
WARUM ES DIESE DATEI GIBT (Befund 25.07.2026, live im Worker nachgemessen): WARUM ES DIESE DATEI GIBT (Befund 25.07.2026, auf BEIDEN Maschinen gemessen):
Bei 4K-UHD-Discs meldet MakeMKV "The volume key is unknown for this disc". 4K-UHD-Discs scheiterten mit "The volume key is unknown for this disc". Die
Das Laufwerk ist dabei in Ordnung makemkvcon meldet "Using LibreDrive mode Ursache ist weder die Disc noch das Laufwerk LibreDrive v06.3 laeuft und
(v06.3)" und liest die Disc — MakeMKV kennt nur den Schluessel DIESER Pressung MakeMKV liest die Disc sondern:
nicht. Und es holt ihn NICHT mehr online nach:
* /root/.MakeMKV/_private_data.tar enthielt ausser der Index-Datei keine makemkvcon unter LINUX ruft die Disc-Schluessel nie ab.
einzige hkd_*.bin, also nie einen heruntergeladenen Schluessel; Die Windows-Version tut es.
* auch mit erzwungener frischer Pruefung (update.conf geloescht, Meldung
5074 belegt den Web-Kontakt) und mit app_UpdateEnable = "1" kam keiner;
* die im MakeMKV-Forum dokumentierten Schluessel-Server hkdata.fairuse.org
und hkdata.crabdance.com loesen weltweit nicht mehr auf (gegen Fritz!Box,
8.8.8.8 und 1.1.1.1 geprueft: NXDOMAIN).
Betroffen war Akira UHD (MKB v76, Pressung von Dezember 2020) also gerade Gemessen, nicht vermutet:
KEINE Neuerscheinung. Die bisherige Fehlermeldung ("Disc neuer als die * Linux: in KEINEM Lauf auch nur eine Verbindung nach draussen. Geprueft mit
Schluessel-Datenbank, mit einem der naechsten Updates rippbar") war damit leerem UND mit gefuelltem Schluesselspeicher, mit und ohne --noscan, mit
schlicht falsch. dev:/dev/sr0 und mit disc:0, und mit erzwungener frischer Pruefung
(update.conf geloescht, Meldung 5074 belegt den Web-Kontakt). Immer:
keine Verbindung, kein Schluessel.
* Windows, dieselbe Disc, dasselbe Laufwerk: Meldung 3338 "Downloading
latest HK to ...", Verbindung nach 185.84.108.20:443
(web33.majordomo.ru), _private_data.tar waechst und die Disc geht auf
(TCOUNT:5, "Operation successfully completed").
* Der Code dafuer steckt auch im Linux-Binary: die Meldungsvorlage
"Downloading latest %1 to %2 ..." steht in makemkvcon. Sie loest nur nie
aus. Gleiches Symptom im Forum, seit Jahren offen und unbeantwortet.
Der einzige heute funktionierende Weg ist eine KEYDB.cfg im FRUEHERE FEHLDIAGNOSE, bewusst festgehalten: An dieser Stelle stand zuerst,
MakeMKV-Datenverzeichnis. Rippy liefert KEINE Schluessel mit, laedt keine MakeMKVs Schluessel-Kanal sei abgeschaltet. Das war FALSCH. Die Herleitung
herunter und verteilt keine es stellt nur den Platz dafuer bereit und zeigt stuetzte sich auf zwei Hostnamen aus alten Forumsbeitraegen
ehrlich an, was dort liegt. Die Datei bringt der Nutzer selbst mit. (hkdata.fairuse.org, hkdata.crabdance.com), die tatsaechlich nicht mehr
aufloesen MakeMKV benutzt sie aber laengst nicht mehr. Der Dienst lebt, der
Worker erreicht ihn sogar; er wird unter Linux nur nie gefragt.
WAS DARAUS FOLGT: Der Schluesselspeicher (_private_data.tar) muss von einer
MakeMKV-Installation kommen, die ihn wirklich abruft praktisch von Windows.
Rippy nimmt ihn unter Einstellungen -> System entgegen. Die KEYDB.cfg bleibt
der Notnagel fuer Pressungen, die auch MakeMKV selbst nicht kennt.
Rippy liefert KEINE Schluessel mit, laedt keine herunter und verteilt keine.
Es verwaltet nur, was der Nutzer selbst mitbringt.
QUELLEN (AGENTS Regel D externe Schnittstellen nie aus dem Kopf): QUELLEN (AGENTS Regel D externe Schnittstellen nie aus dem Kopf):
* Datenverzeichnis und Dateiname GROSS geschrieben (unter Linux * Linux laedt keine Hashed Keys dasselbe Symptom, mehrfach berichtet:
https://forum.makemkv.com/forum/viewtopic.php?t=25782
https://forum.makemkv.com/forum/viewtopic.php?t=34022
* Schluessel liegen als hkd_*.bin in _private_data.tar:
https://forum.makemkv.com/forum/viewtopic.php?t=32675
* Datenverzeichnis und Dateiname KEYDB.cfg GROSS geschrieben (unter Linux
case-sensitiv), dort geloest mit "cp KEYDB.cfg ~/.MakeMKV/": case-sensitiv), dort geloest mit "cp KEYDB.cfg ~/.MakeMKV/":
https://forum.makemkv.com/forum/viewtopic.php?t=30636 https://forum.makemkv.com/forum/viewtopic.php?t=30636
* Heruntergeladene Schluessel liegen als hkd_*.bin in _private_data.tar:
https://forum.makemkv.com/forum/viewtopic.php?t=32675
* Zeilenformat der KEYDB.cfg (libaacs): Disc-Kennung = 40 Hex-Zeichen, * Zeilenformat der KEYDB.cfg (libaacs): Disc-Kennung = 40 Hex-Zeichen,
optional mit 0x-Praefix, dann "= Titel", danach optionale Felder wie optional mit 0x-Praefix, dann "= Titel", danach optionale Felder wie
"| V | <32 Hex>"; Zeilen ab ";" sind Kommentare: "| V | <32 Hex>"; Zeilen ab ";" sind Kommentare:
@@ -42,8 +58,10 @@ Images brauchen sie, ein gemeinsames Paket gibt es in diesem Projekt nicht
(gleiche Lage wie bei db.py). Aenderungen IMMER in BEIDEN Dateien nachziehen. (gleiche Lage wie bei db.py). Aenderungen IMMER in BEIDEN Dateien nachziehen.
""" """
import io
import os import os
import re import re
import tarfile
from datetime import datetime, timezone from datetime import datetime, timezone
# Container-Pfad aus der Umgebung: /root/.MakeMKV im Worker (nur dort sucht # Container-Pfad aus der Umgebung: /root/.MakeMKV im Worker (nur dort sucht
@@ -226,6 +244,121 @@ def dumps_auflisten(daten_dir: str = None) -> list:
return liste return liste
# --- Schluesselspeicher (_private_data.tar) -------------------------------
#
# Das ist MakeMKVs eigener Speicher fuer die "Hashed Keys": ein tar-Archiv mit
# hkd_*.bin-Eintraegen. Unter Windows fuellt MakeMKV es selbst (Meldung 3338),
# unter Linux nie — siehe Modul-Kopf. Rippy nimmt die Datei deshalb entgegen
# und legt sie ins Datenverzeichnis; MakeMKV liest sie beim naechsten Start.
PRIVATE_DATA_NAME = "_private_data.tar"
# Der Speicher lag am 25.07.2026 bei rund 6 MB und waechst mit jeder neuen
# Pressung. 64 MB sind reichlich Luft — und derselbe Wert wie
# client_max_body_size in docker/ui/nginx.conf: waere die Grenze hier hoeher,
# wuerde nginx den Upload abweisen, bevor die API ihn ueberhaupt sieht.
MAX_PRIVATE_DATA_BYTES = 64 * 1024 * 1024
def private_data_pfad(daten_dir: str = None) -> str:
"""Voller Pfad zum Schluesselspeicher im Datenverzeichnis."""
return os.path.join(daten_dir or DATEN_DIR, PRIVATE_DATA_NAME)
def zaehle_schluessel(rohdaten: bytes) -> int:
"""Anzahl der hkd_*.bin-Eintraege im Archiv (pure Funktion, testbar).
Das ist die ehrliche Kennzahl fuer "wie viele Disc-Schluessel kennt diese
Installation". Ein frischer, leerer Speicher enthaelt nur eine
Index-Datei und kommt hier auf 0 genau der Zustand, in dem jede
unbekannte UHD-Disc scheitert.
"""
try:
with tarfile.open(fileobj=io.BytesIO(rohdaten)) as archiv:
return sum(1 for name in archiv.getnames() if name.startswith("hkd_"))
except (tarfile.TarError, OSError, EOFError):
return 0
def private_data_pruefen(rohdaten: bytes) -> str:
"""Prueft hochgeladene Rohdaten; deutscher Fehlertext oder "".
Faengt die beiden Bedienfehler ab, die sonst still danebengehen: eine
voellig andere Datei hochladen, oder den Speicher einer Installation, die
selbst noch keine Schluessel geholt hat (dann aendert sich nichts, und
niemand versteht warum).
"""
if not rohdaten:
return "Die Datei ist leer."
if len(rohdaten) > MAX_PRIVATE_DATA_BYTES:
return (
"Die Datei ist groesser als "
f"{MAX_PRIVATE_DATA_BYTES // (1024 * 1024)} MB — das ist kein "
"MakeMKV-Schluesselspeicher."
)
try:
with tarfile.open(fileobj=io.BytesIO(rohdaten)) as archiv:
namen = archiv.getnames()
except (tarfile.TarError, OSError, EOFError):
return (
"Das ist kein tar-Archiv. Erwartet wird die Datei "
f"{PRIVATE_DATA_NAME} aus dem MakeMKV-Datenverzeichnis."
)
if not any(name.startswith("hkd_") for name in namen):
return (
"In dieser Datei steckt kein einziger Schluessel (kein hkd_*.bin). "
"Sie stammt vermutlich von einer MakeMKV-Installation, die selbst "
"noch keine geholt hat — oeffne dort erst einmal eine Disc."
)
return ""
def schluesselspeicher_status(daten_dir: str = None) -> dict:
"""Zustand des Schluesselspeichers. Fehlt er, ist das kein Fehler."""
pfad = private_data_pfad(daten_dir)
try:
angaben = os.stat(pfad)
with open(pfad, "rb") as datei:
schluessel = zaehle_schluessel(datei.read())
except OSError:
return {
"vorhanden": False,
"pfad": pfad,
"groesse_bytes": 0,
"schluessel": 0,
"geaendert": "",
}
return {
"vorhanden": True,
"pfad": pfad,
"groesse_bytes": angaben.st_size,
"schluessel": schluessel,
"geaendert": _iso(angaben.st_mtime),
}
def private_data_schreiben(rohdaten: bytes, daten_dir: str = None) -> dict:
"""Legt den Schluesselspeicher atomar ab und meldet den neuen Zustand.
Atomar aus demselben Grund wie bei der KEYDB.cfg: waehrend ein Rip laeuft,
darf makemkvcon nie ein halb geschriebenes Archiv sehen.
"""
pfad = private_data_pfad(daten_dir)
os.makedirs(os.path.dirname(pfad), exist_ok=True)
neben = pfad + ".neu"
try:
with open(neben, "wb") as datei:
datei.write(rohdaten)
os.replace(neben, pfad)
except OSError:
try:
os.remove(neben)
except OSError:
pass
raise
return schluesselspeicher_status(daten_dir)
def settings_conf_zusammenfuehren(inhalt: str, key: str) -> str: def settings_conf_zusammenfuehren(inhalt: str, key: str) -> str:
"""app_Key setzen, ohne den Rest der settings.conf zu verlieren (pure). """app_Key setzen, ohne den Rest der settings.conf zu verlieren (pure).
+24 -23
View File
@@ -455,33 +455,34 @@ def rip_disc(self, device_path: str, job_id: str, target_dir: str = None):
if ergebnis.get("status") == "error": if ergebnis.get("status") == "error":
fehler_text = ergebnis.get("error") or "" fehler_text = ergebnis.get("error") or ""
if "volume key is unknown" in fehler_text: if "volume key is unknown" in fehler_text:
# Befund 25.07.2026, im Worker nachgemessen (Akira UHD, MKB v76, # Befund 25.07.2026, auf BEIDEN Maschinen gemessen: Laufwerk und
# Pressung Dez. 2020): Laufwerk und MakeMKV sind in Ordnung — # MakeMKV sind in Ordnung. makemkvcon unter Linux ruft die
# MakeMKV fragt online gar nicht erst nach einem Schlüssel, und # Disc-Schlüssel schlicht nie ab — die Windows-Version tut es
# der Online-Kanal liefert auch nichts mehr. Der alte Text hier # (Meldung 3338). Hier stand vorher erst "Disc zu neu" und danach
# ("Disc neuer als die Schlüssel-Datenbank, mit einem der # "der Schlüssel-Kanal ist tot"; beides war falsch und hat in die
# nächsten Updates rippbar") war schlicht falsch und hat in die # Irre geschickt. Herleitung im Kopf von makemkv_daten.py.
# falsche Richtung geschickt. Details: makemkv_daten.py. speicher = makemkv_daten.schluesselspeicher_status()
keydb = makemkv_daten.keydb_status() anzahl = speicher.get("schluessel", 0)
ergebnis["error"] += ( ergebnis["error"] += (
" — Klartext: Laufwerk und Rippy sind in Ordnung, MakeMKV " " — Klartext: Laufwerk und Rippy sind in Ordnung, MakeMKV "
"liest die Disc. Es kennt nur den Schlüssel dieser Pressung " "liest die Disc. Es fehlt nur der Schlüssel dieser Pressung. "
"nicht und holt ihn auch nicht mehr online nach — MakeMKVs " "Der Grund: makemkvcon holt Schlüssel unter Linux nie selbst "
"Schlüssel-Kanal liefert nichts mehr (am 25.07.2026 im " "nach — die Windows-Version schon. "
"Worker nachgemessen). Abhilfe: eine KEYDB.cfg unter "
"Einstellungen → System hochladen; sie wirkt ab dem nächsten "
"Rip. "
+ ( + (
"Aktuell liegt dort keine KEYDB.cfg." "Dieser Worker kennt aktuell GAR KEINEN Disc-Schlüssel. "
if not keydb.get("vorhanden") if not anzahl
else "Es liegt bereits eine KEYDB.cfg dort — sie kennt " else f"Dieser Worker kennt {anzahl} Disc-Schlüssel, "
"diese Pressung offenbar nicht; eine neuere Fassung " "diese Pressung ist nicht dabei. "
"kann helfen."
) )
+ " Den AACS-Dump dieser Disc bewahrt Rippy jetzt dauerhaft " + "Abhilfe: MakeMKV auf einem Windows-PC installieren, die "
"auf; er steht unter Einstellungen → System zum Download " "Disc dort einmal öffnen, dann die Datei _private_data.tar "
"bereit (für die Einreichung im MakeMKV-Forum, Bereich " "aus dem MakeMKV-Datenverzeichnis unter Einstellungen → "
"'Ultra HD Blu-ray')." "System hochladen. Wirkt ab dem nächsten Rip. Klappt auch "
"das nicht, kennt MakeMKV die Pressung selbst nicht — dann "
"hilft nur eine KEYDB.cfg (ebenfalls dort hochladbar) oder "
"das Einreichen des AACS-Dumps im MakeMKV-Forum, Bereich "
"'Ultra HD Blu-ray'. Der Dump steht unter Einstellungen → "
"System zum Download bereit."
) )
elif disc_type == "uhd" and "Failed to open disc" in fehler_text: elif disc_type == "uhd" and "Failed to open disc" in fehler_text:
ergebnis["error"] += ( ergebnis["error"] += (
@@ -42,6 +42,69 @@ ist_aacs_dump = _modul.ist_aacs_dump
keydb_pruefen = _modul.keydb_pruefen keydb_pruefen = _modul.keydb_pruefen
settings_conf_zusammenfuehren = _modul.settings_conf_zusammenfuehren settings_conf_zusammenfuehren = _modul.settings_conf_zusammenfuehren
zaehle_disc_eintraege = _modul.zaehle_disc_eintraege zaehle_disc_eintraege = _modul.zaehle_disc_eintraege
private_data_pruefen = _modul.private_data_pruefen
zaehle_schluessel = _modul.zaehle_schluessel
def _tar_mit(namen):
"""Baut ein tar-Archiv im Speicher — so sieht MakeMKVs Schluesselspeicher aus.
Echte Eintragsnamen aus dem Speicher der Windows-Installation vom
25.07.2026: hkd_<8 Hex>.bin fuer die Schluessel, dazu Index-Dateien.
"""
import io
import tarfile
puffer = io.BytesIO()
with tarfile.open(fileobj=puffer, mode="w") as archiv:
for name in namen:
eintrag = tarfile.TarInfo(name)
eintrag.size = 3
archiv.addfile(eintrag, io.BytesIO(b"abc"))
return puffer.getvalue()
def test_zaehle_schluessel_zaehlt_nur_hkd_eintraege():
# Nur hkd_*.bin sind Disc-Schluessel. Index- und sdf-Dateien gehoeren zum
# Speicher dazu, sind aber keine Schluessel — sonst meldete das UI
# "1 Schluessel vorhanden" fuer einen komplett leeren Vorrat.
voll = _tar_mit([
"hkd_00000059.bin",
"hkd_0000005a.bin",
"sdf_000000a6.bin",
"--index-A2E950B3C3FC57DA9CB856DCAFBA5275F40423DB.bin",
])
assert zaehle_schluessel(voll) == 2
def test_zaehle_schluessel_leerer_speicher_ist_null():
# Genau dieser Zustand lag am 25.07.2026 auf der VM vor: ein Archiv mit
# ausschliesslich der Index-Datei. Jede unbekannte UHD-Disc scheitert dann.
leer = _tar_mit(["--index-4EF73C3560D489497ACE763962A7F07A4A1545C4.bin"])
assert zaehle_schluessel(leer) == 0
def test_zaehle_schluessel_bei_muell_kein_absturz():
# Darf niemals werfen — die Zahl landet im Worker-Herzschlag.
assert zaehle_schluessel(b"") == 0
assert zaehle_schluessel(b"das ist kein tar") == 0
def test_private_data_pruefen_nimmt_echten_speicher_an():
assert private_data_pruefen(_tar_mit(["hkd_00000059.bin"])) == ""
def test_private_data_pruefen_lehnt_leere_und_falsche_dateien_ab():
assert "leer" in private_data_pruefen(b"")
assert "tar-Archiv" in private_data_pruefen(b"<html>Fehlerseite</html>")
def test_private_data_pruefen_lehnt_speicher_ohne_schluessel_ab():
# Der teuerste Bedienfehler: den Speicher einer Installation hochladen,
# die selbst noch nie Schluessel geholt hat. Ohne diese Pruefung aendert
# sich nichts und niemand versteht, warum.
leer = _tar_mit(["--index-4EF73C3560D489497ACE763962A7F07A4A1545C4.bin"])
assert "kein einziger Schluessel" in private_data_pruefen(leer)
def test_zwillinge_sind_byteweise_identisch(): def test_zwillinge_sind_byteweise_identisch():