f449c4ee34
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>
116 lines
4.5 KiB
Python
116 lines
4.5 KiB
Python
"""Encoder-Fähigkeiten dieses Workers — ehrlich erkannt, nicht behauptet.
|
|
|
|
Jeder Worker meldet beim Start, was auf SEINER Maschine wirklich verfügbar
|
|
ist (Commander-Anforderung 23.07.: das UI zeigt an, WAS da ist). Ein
|
|
Remote-GPU-Worker meldet sich hier genauso wie der eingebaute CPU-Worker.
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
import shutil
|
|
import subprocess
|
|
|
|
|
|
def erkenne_encoder() -> list:
|
|
"""Liste der verfügbaren Encoder-Backends auf dieser Maschine."""
|
|
gefunden = ["cpu-x264", "cpu-x265"] # HandBrake-Software-Encoder, immer dabei
|
|
|
|
# VAAPI: AMD (VCN) und Intel (QuickSync) melden sich über /dev/dri
|
|
if os.path.exists("/dev/dri/renderD128"):
|
|
gefunden.append("vaapi")
|
|
|
|
# NVENC: NVIDIA-Treiber im Container sichtbar
|
|
if shutil.which("nvidia-smi") or os.path.exists("/usr/lib/x86_64-linux-gnu/libnvidia-encode.so.1"):
|
|
gefunden.append("nvenc")
|
|
|
|
return gefunden
|
|
|
|
|
|
def erkenne_ip() -> str:
|
|
"""Beste erratbare eigene IP (UDP-Route-Trick, KEIN echter Traffic).
|
|
|
|
Ehrlicher Vorbehalt: im Docker-Bridge-Netz ist das die Container-IP —
|
|
für die Maschinen-Zuordnung ist deshalb WORKER_NAME (Anzeigename in
|
|
compose/.env) die verlässliche Größe; die IP ist Zusatz-Indiz.
|
|
"""
|
|
import socket
|
|
|
|
try:
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
try:
|
|
s.connect(("192.0.2.1", 9)) # TEST-NET — nur Routing, kein Paket nötig
|
|
return s.getsockname()[0]
|
|
finally:
|
|
s.close()
|
|
except OSError:
|
|
return ""
|
|
|
|
|
|
def werkzeug_versionen() -> dict:
|
|
"""Kern-Werkzeuge dieses Workers — fürs UI (Einstellungen → System).
|
|
|
|
MakeMKV-Version kommt aus dem Build (ENV MAKEMKV_VERSION im Dockerfile) —
|
|
makemkvcon hat keinen dokumentierten --version-Schalter (usage.txt).
|
|
HandBrakeCLI --version ist dokumentiert (handbrake.fr/docs, CLI Options)
|
|
und gibt z.B. "HandBrake 1.6.1" aus.
|
|
"""
|
|
import socket
|
|
|
|
info = {
|
|
# Zuordnung im UI: hostname (für den Celery-Online-Abgleich) + IP
|
|
"hostname": socket.gethostname(),
|
|
"ip": erkenne_ip(),
|
|
}
|
|
if shutil.which("makemkvcon"):
|
|
info["makemkv"] = os.getenv("MAKEMKV_VERSION") or "installiert"
|
|
if shutil.which("HandBrakeCLI"):
|
|
try:
|
|
aus = subprocess.run(
|
|
["HandBrakeCLI", "--version"],
|
|
capture_output=True, text=True, timeout=15,
|
|
)
|
|
treffer = re.search(r"HandBrake\s+([\w.]+)", (aus.stdout or "") + (aus.stderr or ""))
|
|
info["handbrake"] = treffer.group(1) if treffer else "installiert"
|
|
except (OSError, subprocess.TimeoutExpired):
|
|
info["handbrake"] = "installiert"
|
|
# Woher kommt der MakeMKV-Key? UI-Setting schlägt Env — ehrlich anzeigen.
|
|
try:
|
|
import db
|
|
ui_key = (db.get_settings().get("makemkvAppKey") or "").strip()
|
|
except Exception:
|
|
ui_key = ""
|
|
if ui_key:
|
|
info["makemkv_key"] = "ui"
|
|
elif os.getenv("MAKEMKV_APP_KEY"):
|
|
info["makemkv_key"] = "env"
|
|
else:
|
|
info["makemkv_key"] = "keiner"
|
|
# Sieht DIESER Worker eine KEYDB.cfg? Die API zeigt ihren eigenen Mount —
|
|
# bei einem Remote-Worker kann das etwas ganz anderes sein, und nur das
|
|
# Verzeichnis des rippenden Workers zählt (Befund 25.07.2026).
|
|
#
|
|
# Gemeldet wird die Angabe NUR, wenn das Datenverzeichnis hier wirklich
|
|
# eingehängt ist (os.path.ismount). Ein Remote-Transcode-Worker benutzt
|
|
# dasselbe Image — makemkvcon ist dort also vorhanden und der entrypoint
|
|
# legt den Ordner an —, er bekommt den Mount aber nicht und rippt nie.
|
|
# Ohne diese Prüfung trüge er im UI dauerhaft die Warnung "keine
|
|
# KEYDB.cfg", obwohl ihn das gar nichts angeht.
|
|
try:
|
|
import makemkv_daten
|
|
daten_dir = makemkv_daten.DATEN_DIR
|
|
except Exception:
|
|
daten_dir = ""
|
|
if shutil.which("makemkvcon") and daten_dir and os.path.ismount(daten_dir):
|
|
try:
|
|
info["keydb"] = "ja" if makemkv_daten.keydb_status().get("vorhanden") else "nein"
|
|
except Exception:
|
|
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
|