Etappe 10: Worker rippt wirklich — MakeMKV 1.18.4 + ioctl-Disc-Erkennung
Vorher: Dockerfile unbaubar (makepkg ist ein Arch-Paket, existiert in Debian nicht) und KEIN einziges Ripping-Tool im Image — jeder Rip endete sofort. Disc-Erkennung via `file -L` konnte auf Block-Devices strukturell nie etwas erkennen; ihr Test mockte sich die Ausgabe passend. - makemkv-oss/bin 1.18.4 multi-stage (bookworm-gepinnt), EULA via tmp/eula_accepted, Beta-Key aus MAKEMKV_APP_KEY (entrypoint.sh) - makemkvcon-Aufruf + PRGV-Parsing laut makemkv.com/developers/usage.txt (AGENTS Regel D), HandBrake raus aus dem Ripp-Pfad (KONZEPT: lossless=Muss) - detection.py: CDROM_DISC_STATUS + BLKGETSIZE64 (cd/dvd/bluray), pure classify() mit ehrlichen Tests - tasks.py: rip_disc als einziger Celery-Task, schreibt Status/Fortschritt nach Postgres (db.py), Ausgabe auf /app/media (Volume) statt totem /output Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+62
-17
@@ -1,24 +1,69 @@
|
||||
"""Zentraler Rip-Task: erkennt den Disc-Typ, rippt und schreibt Status nach Postgres.
|
||||
|
||||
Die API legt beim POST /jobs die Job-Zeile an und schickt diesen Task los —
|
||||
der Worker hält die Zeile aktuell (running → completed/failed) und schreibt
|
||||
Ereignisse ins Log. Das UI liest beides über die API.
|
||||
"""
|
||||
|
||||
import db
|
||||
from celery_app import celery_app
|
||||
from ripping import rip_dvd, rip_bluray, rip_cd, detect_disc_type
|
||||
from detection import detect_disc_type
|
||||
from ripping import rip_cd, rip_video
|
||||
|
||||
|
||||
@celery_app.task(bind=True, name="worker.tasks.rip_disc")
|
||||
def rip_disc(self, device_path: str, disc_id: str = None):
|
||||
"""Rippt eine Disc basierend auf ihrem Typ."""
|
||||
def rip_disc(self, device_path: str, job_id: str):
|
||||
"""Rippt eine Disc basierend auf ihrem Typ; job_id ist die DB-Zeile der API."""
|
||||
db.init_db()
|
||||
disc_type = detect_disc_type(device_path)
|
||||
|
||||
if not disc_id:
|
||||
disc_id = device_path.replace("/", "_")
|
||||
|
||||
|
||||
if disc_type in ("no_disc", "unknown"):
|
||||
fehler = (
|
||||
"Keine Disc im Laufwerk" if disc_type == "no_disc"
|
||||
else "Disc-Typ nicht erkennbar"
|
||||
)
|
||||
db.update_job(
|
||||
job_id, status="failed", error=fehler, finished_at=db.utcnow()
|
||||
)
|
||||
db.add_log("error", "worker", f"Job {job_id}: {fehler} ({device_path})")
|
||||
return {"status": "error", "error": fehler, "disc_type": disc_type}
|
||||
|
||||
db.update_job(job_id, status="running", disc_type=disc_type)
|
||||
db.add_log("info", "worker", f"Job {job_id}: {disc_type}-Rip gestartet ({device_path})")
|
||||
|
||||
letzter = [-1]
|
||||
|
||||
def fortschritt(progress: int, message: str = ""):
|
||||
# MakeMKV liefert viele PRGV-Zeilen pro Sekunde — DB nur bei Änderung.
|
||||
if progress == letzter[0]:
|
||||
return
|
||||
letzter[0] = progress
|
||||
self.update_state(
|
||||
state="PROGRESS",
|
||||
meta={"progress": progress, "status": "ripping", "message": message},
|
||||
)
|
||||
db.update_job(job_id, progress=progress)
|
||||
|
||||
if disc_type == "cd":
|
||||
return rip_cd(device_path, disc_id)
|
||||
elif disc_type == "dvd":
|
||||
return rip_dvd(device_path, disc_id)
|
||||
elif disc_type == "bluray":
|
||||
return rip_bluray(device_path, disc_id)
|
||||
ergebnis = rip_cd(device_path, job_id, progress_cb=fortschritt)
|
||||
else:
|
||||
return {
|
||||
"status": "error",
|
||||
"message": f"Unbekannter Disc-Typ: {disc_type}",
|
||||
"disc_type": disc_type
|
||||
}
|
||||
ergebnis = rip_video(device_path, job_id, disc_type, progress_cb=fortschritt)
|
||||
if ergebnis.get("status") == "success":
|
||||
db.update_job(
|
||||
job_id,
|
||||
status="completed",
|
||||
progress=100,
|
||||
output_path=ergebnis.get("output_dir"),
|
||||
finished_at=db.utcnow(),
|
||||
)
|
||||
db.add_log("success", "worker", f"Job {job_id}: Rip abgeschlossen → {ergebnis.get('output_dir')}")
|
||||
else:
|
||||
db.update_job(
|
||||
job_id,
|
||||
status="failed",
|
||||
error=ergebnis.get("error", "unbekannter Fehler"),
|
||||
finished_at=db.utcnow(),
|
||||
)
|
||||
db.add_log("error", "worker", f"Job {job_id}: {ergebnis.get('error', 'unbekannter Fehler')}")
|
||||
|
||||
return ergebnis
|
||||
|
||||
Reference in New Issue
Block a user