Commit Graph

16 Commits

Author SHA1 Message Date
Hitonabi 8394de6926 fix(transcode): "Abbrechen" wirkt sofort statt erst beim naechsten Prozent
Ampel / ampel (push) Failing after 28s
Fund des Commanders am laufenden Akira-Job (Nachtrag im vorigen Savepoint):
Job stand auf 'canceling', HandBrake lief weiter. Gemessen 3,4 Minuten
zwischen Anforderung (18:30:17) und Bestaetigung (18:33:38) - bei langsamerem
Fortschritt entsprechend mehr.

Ursache genau wie dort beschrieben: Der Abbruch wurde nur in
datei_fortschritt geprueft, und diese Closure stieg oben sofort wieder aus,
wenn sich die Prozentzahl nicht geaendert hatte ("if gesamt == letzter[0]:
return"). Bei einem Prozent je halber Stunde hing der Abbruch also an einem
Ereignis, das eine halbe Stunde lang nicht eintrat.

run_handbrake bekommt jetzt einen eigenen abbruch_cb neben progress_cb -
dasselbe Muster, das run_makemkv schon fuer log_cb benutzt, und aus
demselben Grund: der Fortschritts-Kanal verwirft Aufrufe. Er wird bei JEDER
Ausgabezeile aufgerufen und im Worker auf 5 s gedrosselt.

Nebeneffekt, der genauso wichtig ist: Er greift auch waehrend des
Scan-Durchlaufs, der ueberhaupt keine Encode-Prozente liefert. Dort war ein
Abbruch vorher grundsaetzlich unmoeglich - und seit die Prozent-Regex den
Scan korrekt ignoriert, waere das sonst sogar schlimmer geworden.

Die Leseschleife ist als _handbrake_schleife() herausgezogen, damit die
Reihenfolge (Abbruch VOR Fortschritt) ohne echtes HandBrake pruefbar ist.
Der Test belegt: zwei Scan-Zeilen genuegen fuer den Abbruch, es muss NICHT
auf eine Encode-Zeile gewartet werden.

Savepoint nachgezogen: Der Encode laeuft nicht mehr, ein Deploy ist
gefahrlos moeglich, und die alte "SOFORT ENTSCHEIDEN"-Passage (Platte
laeuft voll, wenn der Job fertig wird) ist damit gegenstandslos. Neu darin:
die drei Wege fuer UHD, und die Warnung, dass eine /proc-Suche nach
"HandBrake" die eigene Shell mittrifft - zwei Fehlalarme in dieser Sitzung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 21:10:03 +02:00
Hitonabi ef0a574a70 fix(worker,api): Platten-Schutz griff nicht, Fortschritt log, Auswurf tat nichts
Vier Funde aus der Durchsicht, alle auf der VM gemessen.

1. DER PLATTEN-SCHUTZ AUS c065967 WAR WIRKUNGSLOS

_original_aufheben() entschied per os.stat().st_dev, ob umgehaengt oder
kopiert werden muss. Im Worker-Container gemessen - beides gleichzeitig wahr:

    st_dev /app/temp  = 2050
    st_dev /app/media = 2050        → identisch
    os.rename(...)    → EXDEV, "Invalid cross-device link"

Der Kernel vergleicht bei rename() den MOUNT, nicht das Geraet. /app/temp
(Docker-Volume) und /app/media (Bind-Mount) sind zwei Mounts DERSELBEN
ext4-Partition. Die Pruefung sah "gleiches Dateisystem", uebersprang die
Platzpruefung, und shutil.move kopierte doch - 75 GB bei 37 GB frei. Der
Schutz haette genau den Schaden zugelassen, gegen den er gebaut wurde.

Jetzt wird os.rename VERSUCHT statt vorhergesagt: klappt es, ist es
umgehaengt und fertig; kommt EXDEV, steht die Kopie fest und ERST DANN wird
der Platz geprueft. Das ist keine Vermutung mehr, sondern die Antwort des
Kernels. Vier Tests in test_original_aufheben.py, darunter genau der Fall,
der die Platte fuellte. Die zwei alten Tests in test_medien.py sind dorthin
gewandert - sie taeuschten per gefaelschtem os.stat "verschiedene
Dateisysteme" vor, also genau die Annahme, an der der Schutz scheiterte.

2. DIE FORTSCHRITTSANZEIGE ZEIGTE DEN SCAN, NICHT DEN ENCODE

get_progress_from_line matchte jede Zahl vor einem Prozentzeichen. HandBrake
gibt Prozente aber in drei Phasen aus (Formatstrings aus dem Binary gelesen):

    Scanning title %d of %d, preview %d, %.2f %%          → laeuft VOR dem
                                                            Encode bis 100 %
    Encoding: task %d of %d, %.2f %%       (%.2f fps, avg  → der echte Wert
    Encoding: task %d of %d, Searching for start time, ... → Vorlauf

Dazu warf `if progress > 0` im Aufrufer jeden Wert unter 1,00 % weg. Live
beobachtet: Anzeige stand auf 99 %, der Encode bei 1,06 %; sie fiel erst auf
1, als der Encode die 1-%-Marke ueberschritt. Jetzt wird nur die
Encoding-Zeile gelesen, `task N of M` mitgerechnet (sonst springt die
Anzeige bei Zwei-Pass-Presets mitten in der Datei zurueck), und -1 heisst
"keine Angabe" - dasselbe Muster wie bei get_progress_from_prgv.

3. "AUTOMATISCHER AUSWURF" WURDE VON NIEMANDEM GELESEN

Die Einstellung (Standard: ein, "Disc nach erfolgreichem Ripping automatisch
auswerfen") kam in keiner Zeile Backend-Code vor. DVD/Blu-ray warfen deshalb
NIE aus, Audio-CDs IMMER, weil abcde `-x` fest verdrahtet bekam. Jetzt
entscheidet die Einstellung beides: wirf_disc_aus() per CDROMEJECT-ioctl
(fcntl-guarded, der native Windows-Worker laedt das Modul auch) und `-x` nur
noch, wenn gewuenscht.

4. PFAD-PRUEFUNG FIEL AUF PRAEFIX-NAMEN HEREIN

Elf Stellen prueften mit nacktem startswith(MEDIA_ROOT). "/app/media-boese/x"
beginnt mit "/app/media", liegt aber ausserhalb - betroffen waren auch
/browse und /browse/mkdir, wo der Pfad vom Nutzer kommt. Neuer
Zwillings-Helfer unter_wurzel() in api/main.py und worker/tasks.py, alle elf
Stellen umgestellt, Tests in beiden.

Nebenbefund: _zielbasis() benutzte os.path.normpath - unter Windows werden
daraus Backslashes, die MEDIA_ROOT-Pruefung greift nicht mehr, und das
gewaehlte Ziel faellt still auf den Standard zurueck. Genau die Falle, die
_arbeitsverzeichnis() drei Zeilen weiter dokumentiert und mit posixpath
vermeidet. Live war es nie (nur aus rip_disc, das auf Windows verriegelt
ist), jetzt konsistent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 21:05:11 +02:00
Hitonabi e84afc1718 feat(transcode): ein HandBrake-Preset je Disc-Typ statt eines fuer alles
Ampel / ampel (push) Successful in 29s
Rueckfrage des Commanders beim ersten echten UHD-Rip: "merkt Rippy, dass es
eine UHD ist, und nimmt direkt das 4K-Preset?" Antwort war nein. Die
Kompression fragte den Disc-Typ ueberhaupt nicht:

    preset = einstellungen.get("transcodePreset") or DEFAULT_HB_PRESET

Live eingestellt war "HQ 1080p30 Surround". Der gerade laufende Akira-Rip
waere also verlustfrei in 4K gerippt und danach auf 1080p heruntergerechnet
worden - und mit keepOriginal=False waere der 4K-Rohschnitt danach geloescht
worden. Umgekehrt wurde eine DVD auf 1080p hochskaliert, was nichts bringt.

- preset_fuer(disc_type, einstellungen) in ripping.py, pure und getestet.
  Reihenfolge: Preset des Disc-Typs -> allgemeines transcodePreset ->
  DEFAULT_HB_PRESET. Bestandsinstallationen aendern ihr Verhalten NICHT,
  solange die neuen Felder nicht gespeichert sind.
- Drei Einstellungen: transcodePresetDvd / transcodePresetBluray /
  transcodePresetUhd. transcodePreset bleibt als Rueckfall bestehen.
- transcode_files holt den Disc-Typ aus dem Job-Datensatz und schreibt ihn
  mit ins Log ("Disc-Typ 'uhd', Preset '...'").
- UI: drei Auswahlfelder statt einem, mit Klartext dazu, warum eine 4K-UHD
  auf ein 2160p-Preset gehoert.

Preset-Namen stammen aus "HandBrakeCLI --preset-list" im Worker-Image
(HandBrake 1.6.1) - nicht aus dem Kopf (AGENTS Regel D):
H.265 MKV 2160p60 4K, HQ 2160p60 4K HEVC Surround,
Super HQ 2160p60 4K HEVC Surround, H.265 MKV 1080p30, HQ 1080p30 Surround,
Super HQ 1080p30 Surround, H.265 MKV 576p25, H.265 MKV 480p30,
HQ 576p25 Surround.

Sofortmassnahme am laufenden Job (auf Ansage des Commanders): keepOriginal
auf True gesetzt - nur dieses eine Feld, gegengeprueft dass kein anderer
Schluessel veraendert wurde. Damit ueberlebt der 4K-Rohschnitt die
Kompression.

ACHTUNG - Deploy bewusst NICHT ausgefuehrt: docker compose up -d --build
wuerde den Worker-Container neu erstellen und den laufenden Akira-Rip
abbrechen. Erst nach Abschluss des Jobs deployen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 11:38:52 +02:00
Hitonabi 0935766f61 feat(uhd): KEYDB.cfg-Unterstuetzung - MakeMKVs Schluessel-Kanal liefert nichts mehr
Ampel / ampel (push) Successful in 28s
4K-UHD scheiterte an "The volume key is unknown for this disc". Am 25.07.2026
im Worker-Container nachgemessen: Laufwerk und MakeMKV sind in Ordnung
(LibreDrive v06.3 / Meldung 1011, Disc wird gelesen, AACS-Dump geschrieben) -
MakeMKV versucht gar nicht erst, online einen Schluessel zu holen. Belege:
_private_data.tar enthaelt nur die Index-Datei und KEINE hkd_*.bin; auch mit
geloeschter update.conf (Meldung 5074 belegt den Web-Kontakt) und mit
app_UpdateEnable="1" kam keiner; hkdata.fairuse.org und hkdata.crabdance.com
loesen weltweit nicht mehr auf (NXDOMAIN gegen Fritz!Box, 8.8.8.8, 1.1.1.1).
Betroffen war Akira UHD (MKB v76, Pressung Dez. 2020) - also gerade KEINE
Neuerscheinung. Der bisherige Fehlertext ("Disc neuer als die
Schluessel-Datenbank, mit einem der naechsten Updates rippbar") war falsch.

Einziger heute funktionierender Weg ist eine vom Nutzer selbst mitgebrachte
KEYDB.cfg. Rippy liefert KEINE Schluessel mit, laedt keine herunter und
verteilt keine - es stellt nur den Platz bereit und zeigt an, was dort liegt.

- Datenverzeichnis persistent gemountet (MAKEMKV_DATA_HOST, Default
  /srv/rippy/makemkv): KEYDB.cfg und AACS-Dumps ueberleben jeden Rebuild.
  Vorher loeschte jeder "up -d --build" beides - inklusive des Dumps, auf den
  die Fehlermeldung selbst verwies.
- entrypoint.sh und tasks.py schreiben settings.conf ergaenzend statt
  zerstoerend. Der entrypoint bricht bei nicht beschreibbarem Verzeichnis
  nicht mehr ab - mit "restart: unless-stopped" waere das ein Crashloop
  gewesen, in dem auch reines DVD-Rippen tot ist.
- Neues Zwillings-Modul makemkv_daten.py (docker/api + docker/worker,
  byteweise identisch; test_zwillinge_sind_byteweise_identisch wacht darueber
  und wurde durch absichtliches Verstellen als wirksam nachgewiesen).
- API: GET/POST/DELETE /system/keydb, GET /system/aacs-dumps(/{dateiname}).
  JSON-Body statt Multipart - python-multipart ist bewusst nicht installiert
  und wuerde die API beim Import toeten. nginx client_max_body_size 64m,
  sonst scheitert der Upload mit 413, bevor die API ihn sieht.
- UI (Einstellungen -> System): Status, Hochladen per Datei-Dialog, Entfernen,
  Dump-Download, KEYDB-Plakette je Worker (nur wo das Verzeichnis wirklich
  gemountet ist - ein Remote-Transcode-Worker truege sonst eine Warnung,
  die ihn nichts angeht).
- parse_msg() + log_cb: MakeMKV-Meldungen landen im Rippy-Log (gedrosselt:
  Code 1003 raus, keine Wiederholungen, max. 40 je Rip). Nebenbei behoben:
  der alte Parser (split(",", 4)[3]) schnitt jede Meldung am ersten Komma ab.
- Fuenf Stellen richtiggestellt, die behaupteten, MakeMKV-Updates braechten
  die neueste Disc-Schluessel-Datenbank mit (UI, Anleitung, README,
  Worker-Dockerfile, makemkv_key.py).

NICHT bewiesen: ein erfolgreicher UHD-Rip - es lag keine KEYDB.cfg mit dem
Akira-Schluessel vor. Belegt sind der Befund und die neue Mechanik. So steht
es auch im SAVEPOINT und in der ROADMAP.

Quellen (AGENTS Regel D):
- Datenverzeichnis + Dateiname GROSS/case-sensitiv:
  https://forum.makemkv.com/forum/viewtopic.php?t=30636
- hkd_*.bin in _private_data.tar:
  https://forum.makemkv.com/forum/viewtopic.php?t=32675
- headless settings.conf / app_UpdateEnable:
  https://forum.makemkv.com/forum/viewtopic.php?t=20364
- KEYDB.cfg-Zeilenformat (libaacs):
  https://github.com/ShiftMediaProject/libaacs/blob/master/KEYDB.cfg
- MSG-/PRGV-Format: https://www.makemkv.com/developers/usage.txt

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 01:26:08 +02:00
Hitonabi 3a4eb25392 Track-Auswahl-Tabelle, nativer Windows-Worker (via UI angeboten), Anleitungs-Tab
Ampel / ampel (push) Successful in 29s
Volle Titel-Auswahl vor dem Rip (Etappe-12-Rest):
- worker.tasks.scan_tracks: makemkvcon info -> Titel-Liste (Dauer/Groesse/
  Kapitel, apdefs-Attr 8/9/11) in die settings-Tabelle 'tracks:<device>';
  API: POST /devices/{n}/scan-tracks + GET /devices/{n}/tracks (Polling).
- Rip-Dialog: 'Disc scannen' -> Tabelle mit Checkboxen, Vorauswahl ab
  5 min, Groessen-Summe; gewaehlte Titel als meta.titles in den Job.
- rip_titel_auswahl: ein makemkvcon-Aufruf je Titel (mkv kann nur einen
  Titel oder all), Fortschritt anteilig. Parser-Tests dabei.

Nativer Windows-Worker OHNE Docker (Commander-Wunsch):
- Die Rippy-Instanz versorgt sich selbst: GET /worker-setup/windows
  liefert install.ps1, /worker-setup/paket den Worker-Code als Zip
  (api-Dockerfile kopiert docker/worker/*.py als worker_dist/ ins Image).
- install.ps1: Python-Check, venv + requirements, HandBrakeCLI 1.9.2 vom
  offiziellen GitHub-Release (URL per HEAD verifiziert), start-worker.bat
  mit celery -Q transcode --pool=solo (Celery-Doku: Windows nur solo),
  optional -Autostart via schtasks onlogon.
- tasks.py laedt jetzt auch ohne fcntl (Import-Guard) — rip_disc ist auf
  solchen Workern hart verriegelt (Klartext-Fehler statt Crash).
- Einstellungen -> Worker: Varianten-Umschalter Linux(Docker)/Windows(nativ)
  mit passenden Copy-Paste-Befehlen.

Anleitungs-Tab: Rippy erklaert sich selbst (Disc-Weg, Serien, NAS,
Media-Server, Benachrichtigungen, Key, Worker, Downloads, FAQ).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 15:18:08 +02:00
Hitonabi 8eb5653848 Restefeger: Auth komplett raus, Serien-Flow + Episoden-Matching, Jellyfin-Refresh, Duplikat-Warnung, echtes Nur-Hauptfilm
Ampel / ampel (push) Successful in 55s
AUTH ENTFERNT (Commander-Entscheid 24.07., KONZEPT §10): /token- und
/api-keys-Endpoints, auth.py, test_auth.py, passlib/bcrypt/PyJWT/
python-multipart, JWT_SECRET_KEY-Pflicht. Heimnetz-only, das UI hatte nie
einen Login — die Auth-Oberflaeche war Placebo und die passlib/bcrypt-
Falle brach die Ampel. Rate-Limit pro IP bleibt. Schnellstart laeuft
jetzt ganz ohne .env-Pflichtwerte.

Serien-Flow (Etappe-12-Kern, ARM-Wunde #395):
- Rip-Dialog: Serienname + Staffel -> Ablage <Serie>/Season NN
  (jellyfin.org/docs Naming-Schema); tvshow.nfo + poster.jpg im
  Serien-Ordner, bei Staffel 2 nicht ueberschrieben.
- Episoden-Matching per Laufzeitabgleich: HandBrakeCLI --scan
  ('+ duration:', handbrake.fr/docs) je MKV gegen TMDB-Staffel-Laufzeiten
  (GET /metadata/tv/{id}/season/{n}; tv-season-details-API).
  Ordnungserhaltend; komplette Staffel auf einer Disc klappt auch bei
  uniformen Anime-Laufzeiten (Sequenz-Stufe). Umbenannt wird NUR bei
  eindeutiger Zuordnung — sonst ehrliches Log. Mit Tests.

Weitere Punkte:
- Jellyfin/Emby-Bibliotheks-Refresh nach jedem fertigen Rip
  (POST /Library/Refresh, X-Emby-Token lt. jellyfin.org/docs) —
  URL/Key + Test-Knopf in Einstellungen -> Ripping.
- Duplikat-Warnung: Disc-Fingerabdruck (jetzt Teil des Prescan-Ergebnisses
  + der Job-Metadaten) gegen die Historie; Karte zeigt 'bereits gerippt',
  Vollautomatik ueberspringt Duplikate.
- 'Nur Hauptfilm' ECHT: makemkvcon info -> TINFO-Attr-9-Laufzeiten
  (usage.txt) -> laengster Titel -> mkv dev:X <nr>. Vorher wirkungsloses
  Setting; pro Rip im Dialog uebersteuerbar. Mit Tests.
- OMDb-Treffer eingedeutscht via TMDB /find (external_source=imdb_id,
  de-DE; find-by-id-API).
- Dashboard: Speicherplatz-Anzeige (amber < 60 GB) + CSV-Export
  (GET /jobs/export, Semikolon+BOM fuer deutsches Excel).
- Metadaten-Seite entfernt (Abnahme durch Commander-Auftrag) inkl.
  Placebo-Endpoints /metadata/lookup (scannte Dummy-Device) und
  /metadata/confirm (schrieb nie gelesenen Cache-Key).
- Doppel-Jahr-Fix: 'X (2009) (2009)' in Log und Ordnernamen.
- Remote-Worker-Blocker: redis (6379) + postgres (5432) waren NIE
  veroeffentlicht — kein Remote-Worker konnte sich je verbinden. Ports
  jetzt offen (Heimnetz-Kompromiss, kommentiert) + API_URL fuer Worker.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 14:22:19 +02:00
Hitonabi c9270d08e1 MakeMKV 1.18.4 + UHD-Fehler-Ursachen im Klartext (Laufwerk ist geflasht — Disc-Key war das Problem)
Ampel / ampel (push) Successful in 29s
Diagnose auf der VM (Summer-Wars-UHD, MKB v82):
- 'Using LibreDrive mode (v06.3)' — der BU40N-Crossflash IST erledigt,
  das Laufwerk liest UHD. Der Fehlschlag kam von 'The volume key is
  unknown for this disc': die Disc ist neuer als MakeMKVs
  Schluessel-Datenbank — mit 1.17.7 UND der aktuellsten 1.18.4 bewiesen
  (beide Versionen live gegen die Disc getestet).

Konsequenzen:
- MakeMKV-Pin von 1.17.7 auf 1.18.4 gehoben: der 1.18er Scan-Haenger
  (Forum t=38128) wird ueberall mit --noscan umgangen (info-Lauf mit
  1.18.4 auf der BU40N sauber durchgelaufen), die Flash-Faehigkeit von
  1.17.7 wird nicht mehr gebraucht. Aktuelle Version = aktuellste
  AACS-Key-DB. URL-Base -> /download (dort liegt nur die aktuelle).
- run_makemkv reicht KRITISCHE Meldungen (volume key unknown, Key
  abgelaufen, too old version) in den Fehlertext durch — vorher stand
  da nur die nichtssagende letzte Zeile 'Failed to open disc'.
- UHD-Klartext in tasks.py unterscheidet jetzt die zwei Faelle:
  volume-key-unknown (MakeMKV/Disc-Alter, AACS-Dump aus /root/.MakeMKV/
  im MakeMKV-Forum einreichen) vs. Failed-to-open ohne LibreDrive
  (Firmware-Hinweis).
- SAVEPOINT: Flash-Status korrigiert (war als offen dokumentiert).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 13:44:42 +02:00
Hitonabi 07be54e62a Jikan/MAL-Quelle + Job-Titel + Abbrechen-Knopf + Dark-Hover + Ordner-Verwaltung
Ampel / ampel (push) Failing after 38s
Commander-Befunde (Screenshots 23.07. abends):
- Jikan (MyAnimeList, kostenlos OHNE Key) als Anime-Quelle vor OMDb —
  waehlt per Titel-Aehnlichkeit (SequenceMatcher, Schwelle 0.55) statt
  blind Treffer 1; damit trifft "Evangelion 2.22" den exakten Film
- Job-Titel: POST /jobs uebernimmt den erkannten Disc-Titel aus dem
  DISC_CACHE — Schluss mit "Unbekannt" in der Queue
- Kooperativer Job-Abbruch: POST /jobs/{id}/cancel setzt canceling,
  der Worker prueft das Flag bei jedem Fortschritts-Update und killt
  den Encoder-Prozess sauber (RipAbbruch); UI-Knopf "Abbrechen" fuer
  laufende, Status-Badge "Wird abgebrochen"
- Dark-Mode: Job-Zeilen-Hover war hart hell (hover:bg-slate-50)
- Speicherziele: lokaler Ordner-Browser mit "Ordner anlegen"
  (GET /browse + POST /browse/mkdir, nur unter /app/media)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 21:22:57 +02:00
Hitonabi dfef585ec8 Speicherziel-Wahl: Rip-Ziel pro Job frei waehlbar (Etappe 16 / Task 16)
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>
2026-07-23 16:20:36 +02:00
Hitonabi 2474b683e2 Transcode-Stufe: HandBrake komprimiert NACH dem MakeMKV-Rip + --noscan-Fix
Ampel / ampel (push) Successful in 34s
Commander-Entscheid 23.07.: 40-GB-Rohdateien sind kein brauchbares
Endprodukt. Architektur bleibt zweistufig, weil HandBrake AACS nicht
lesen kann: MakeMKV rippt verlustfrei nach /app/temp/raw, HandBrake
macht daraus x265 auf Arbeitsgroesse in /app/media, Roh-Verzeichnis
wird erst NACH komplettem Erfolg geloescht (keepOriginal behaelt es).

- Worker: handbrake-cli im Image, run_handbrake + _komprimiere,
  Job-Status "transcoding", Settings aus Postgres (transcodeEnabled/
  Preset/keepOriginal), Fortschritt je Datei aggregiert
- makemkvcon: --noscan im Kommando verankert — der Geraete-Scan haengt
  (1.18.4) bzw. crasht (1.17.7) im Container, mit --noscan + dev:-Pfad
  laeuft es (Befund 23.07., DRV-Zeile beweist Laufwerks-Erkennung)
- UI: Settings-Tab "Verarbeitung" (Toggle/Preset/Original behalten),
  Status-Badge "Komprimieren", LiveLog erkennt transcoding als aktiv
- KONZEPT/ROADMAP entsprechend aktualisiert; Tests fuer HandBrake-Cmd
  (arbeitet auf DATEI, nie am Geraet) und Progress-Regex

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 15:56:37 +02:00
Hitonabi 780d114fe4 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>
2026-07-23 15:02:13 +02:00
Hitonabi ad48276fdd Fix: Fortschritts-Regex toleriert Leerzeichen vor % (Testfund)
Ampel / ampel (push) Failing after 14m47s
Echtes HandBrake schreibt "45.50 %" mit Leerzeichen - die alte Regex
hat aus echter Ausgabe NIE einen Fortschritt geparst. Der neue Test
mit realistischer Zeile hat es sofort gefangen.
2026-07-22 19:39:35 +02:00
Hitonabi 0ea5f10b31 Fix-Runde nach Review: alle Befunde behoben + echte Tests
Ampel / ampel (push) Failing after 12m31s
- Metadaten-Preview WIEDERHERGESTELLT (Stub ueberschattete echte
  prescan-Implementierung), tote Altmodule geloescht
- Celery update_state statt Phantom-Task/erfundener API
- abcde-Kommando korrigiert (CD-Ripping war nie funktionsfaehig)
- JWT: fester Schluessel Pflicht, echtes Logout, Cleanup nur Abgelaufene
- main.py: crashende Endpoints (Path/secrets/api_keys), year-Bug,
  Admin-Login aus .env
- Ruff gruen (29 Funde), Tests: auth/cache_keys/ripping_helpers,
  Placebo-test_health raus
- SAVEPOINT: offene MakeMKV-Entscheidung SICHTBAR gemacht (Regel B)
2026-07-22 19:31:48 +02:00
Hitonabi 95c1f9b105 feat(ui): SoC Refactoring & Config Validation
- Theme Context ausgelagert (ThemeContext.tsx + useDarkMode.ts)
- Config Validation mit TMDB-API-Key Pflicht (config_validation.py)
- Cache Key Centralization (cache/keys.py)
- CD-Ripping mit abcde implementiert (Worker)
- Docker Compose mit Healthchecks & LOG_LEVEL
- ROADMAP.md & SAVEPOINT.md aktualisiert
2026-07-22 16:38:19 +02:00
Hitonabi 42f19a0806 ripping.py: HandBrakeCLI-Check + Typ-Erkennung 2026-07-21 16:48:32 +02:00
Hitonabi 9e73d065f9 Etappe 2: Ripping-Pipeline — Erste Implementierung
- DockerfileWorker: abcde, flac, ffmpeg, handbrake-cli installiert
- ripping.py: Ripping-Module für DVD/Blu-ray mit HandBrake
- tasks.py: Disc-Typ-Erkennung + passendes Ripping-Modul
- docker-compose.yml: Output-Verzeichnis /output hinzugefügt
- output/ Verzeichnis erstellt

WIP: CD-Ripping mit abcde noch nicht implementiert
2026-07-21 16:47:50 +02:00