Speicherziel-Wahl: Rip-Ziel pro Job frei waehlbar (Etappe 16 / Task 16)
Ampel / ampel (push) Successful in 28s
Ampel / ampel (push) Successful in 28s
- POST /jobs nimmt target_dir (validiert unter /app/media, .. fliegt raus) - GET /storage-targets: Verzeichnisse unter /app/media inkl. Mount-Flag und freiem Platz — NFS/SMB-Shares unter /srv/rippy/media erscheinen dank rslave-Bind automatisch - jobs.target_dir (Mini-Migration via ADD COLUMN IF NOT EXISTS) - Worker: rip_disc(target_dir) mit eigener Validierung; CD/Video/ Transcode-Pfade legen im gewaehlten Ziel ab - UI: "Rippen starten" oeffnet den Ziel-Dialog (Filme/Serien/Musik oder eigener Pfad); Modal-Bugfix: customPath wurde still ignoriert Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -235,7 +235,7 @@ def rip_video(device_path: str, disc_id: str, disc_type: str = "dvd", progress_c
|
||||
return run_makemkv(device_path, output_dir, progress_cb=progress_cb)
|
||||
|
||||
|
||||
def rip_cd(device_path: str, disc_id: str, progress_cb=None) -> dict:
|
||||
def rip_cd(device_path: str, disc_id: str, progress_cb=None, output_dir: str = None) -> dict:
|
||||
"""Rippt eine CD mit abcde (FLAC)."""
|
||||
if not check_abcde_installed():
|
||||
return {
|
||||
@@ -248,7 +248,8 @@ def rip_cd(device_path: str, disc_id: str, progress_cb=None) -> dict:
|
||||
"error": "cdparanoia ist nicht installiert. Installiere abcde und cdparanoia für CD-Ripping."
|
||||
}
|
||||
|
||||
output_dir = os.path.join(RIP_OUTPUT_DIR, "cd", disc_id)
|
||||
if output_dir is None:
|
||||
output_dir = os.path.join(RIP_OUTPUT_DIR, "cd", disc_id)
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
def melde(progress: int, message: str = ""):
|
||||
|
||||
+27
-7
@@ -27,9 +27,25 @@ from ripping import (
|
||||
RAW_DIR = os.getenv("RAW_DIR", "/app/temp/raw")
|
||||
|
||||
|
||||
MEDIA_ROOT = "/app/media"
|
||||
|
||||
|
||||
def _zielbasis(target_dir, disc_type: str) -> str:
|
||||
"""Ablagebasis: vom Nutzer gewähltes Ziel (validiert) oder Standard."""
|
||||
if target_dir:
|
||||
normalisiert = os.path.normpath(target_dir)
|
||||
if normalisiert.startswith(MEDIA_ROOT):
|
||||
return normalisiert
|
||||
return os.path.join(RIP_OUTPUT_DIR, disc_type)
|
||||
|
||||
|
||||
@celery_app.task(bind=True, name="worker.tasks.rip_disc")
|
||||
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."""
|
||||
def rip_disc(self, device_path: str, job_id: str, target_dir: str = None):
|
||||
"""Rippt eine Disc basierend auf ihrem Typ; job_id ist die DB-Zeile der API.
|
||||
|
||||
target_dir (optional): vom Nutzer gewähltes Ablageziel unter /app/media —
|
||||
dort eingehängte Shares (NFS/SMB) sind damit direkt wählbar.
|
||||
"""
|
||||
db.init_db()
|
||||
disc_type = detect_disc_type(device_path)
|
||||
|
||||
@@ -66,8 +82,10 @@ def rip_disc(self, device_path: str, job_id: str):
|
||||
and einstellungen.get("transcodeEnabled", True)
|
||||
)
|
||||
|
||||
final_dir = os.path.join(_zielbasis(target_dir, disc_type), job_id)
|
||||
|
||||
if disc_type == "cd":
|
||||
ergebnis = rip_cd(device_path, job_id, progress_cb=fortschritt)
|
||||
ergebnis = rip_cd(device_path, job_id, progress_cb=fortschritt, output_dir=final_dir)
|
||||
elif transcode_an:
|
||||
# Stufe 1: Roh-Rip nach /app/temp (wird nach der Kompression gelöscht)
|
||||
ergebnis = rip_video(
|
||||
@@ -76,10 +94,13 @@ def rip_disc(self, device_path: str, job_id: str):
|
||||
output_dir=os.path.join(RAW_DIR, job_id),
|
||||
)
|
||||
else:
|
||||
ergebnis = rip_video(device_path, job_id, disc_type, progress_cb=fortschritt)
|
||||
ergebnis = rip_video(
|
||||
device_path, job_id, disc_type,
|
||||
progress_cb=fortschritt, output_dir=final_dir,
|
||||
)
|
||||
|
||||
if ergebnis.get("status") == "success" and transcode_an:
|
||||
ergebnis = _komprimiere(job_id, disc_type, ergebnis, einstellungen)
|
||||
ergebnis = _komprimiere(job_id, final_dir, ergebnis, einstellungen)
|
||||
|
||||
if ergebnis.get("status") == "success":
|
||||
db.update_job(
|
||||
@@ -102,7 +123,7 @@ def rip_disc(self, device_path: str, job_id: str):
|
||||
return ergebnis
|
||||
|
||||
|
||||
def _komprimiere(job_id: str, disc_type: str, rip_ergebnis: dict, einstellungen: dict) -> dict:
|
||||
def _komprimiere(job_id: str, final_dir: str, rip_ergebnis: dict, einstellungen: dict) -> dict:
|
||||
"""Stufe 2: HandBrake komprimiert die Roh-MKVs auf Arbeitsgröße.
|
||||
|
||||
Erst wenn ALLE Dateien sauber komprimiert sind, wird das Roh-Verzeichnis
|
||||
@@ -110,7 +131,6 @@ def _komprimiere(job_id: str, disc_type: str, rip_ergebnis: dict, einstellungen:
|
||||
liegen (kein Datenverlust wie bei ARMs berüchtigtem Move-Bug #1530).
|
||||
"""
|
||||
quellen = rip_ergebnis.get("files", [])
|
||||
final_dir = os.path.join(RIP_OUTPUT_DIR, disc_type, job_id)
|
||||
os.makedirs(final_dir, exist_ok=True)
|
||||
preset = einstellungen.get("transcodePreset") or DEFAULT_HB_PRESET
|
||||
original_behalten = einstellungen.get("keepOriginal", False)
|
||||
|
||||
Reference in New Issue
Block a user