4343b0901d802a610adf8ede41edc068fd329483
24 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e165e2a0d3 |
feat: Komplettierung der aktuellen Rippy-Etappe
Ampel / ampel (push) Failing after 29s
- Versionsanzeige für den Windows-Worker im UI inkl. Prüfung - Absicherung der install.sh gegen fehlendes systemd - Serien-Episoden-Erkennung und Laufzeitabgleich anhand TMDB-Daten (Heuristik) - Umstellung der Windows-Worker-Installation auf SchTasks (Dienst-Ersatz) - Kodi-Bibliotheks-Refresh über JSON-RPC integriert |
||
|
|
d15900d1eb |
fix(audio): nur die beste Tonspur pro Sprache verlustfrei kopieren
Ampel / ampel (push) Failing after 29s
|
||
|
|
6438beec05 |
fix(worker): kein CMD-Blitzen mehr - und die 7200-Sekunden-Meldung ist erklaert
Ampel / ampel (push) Successful in 31s
Zwei Meldungen, beide auf dieselbe Wurzel zurueckgefuehrt: Der Worker startet
Konsolenprogramme, und das hat unter Windows Nebenwirkungen.
1. "Es geht immer alle paar Sekunden ne CMD auf." Kein Geist, sondern der
HERZSCHLAG. Der Worker laeuft als pythonw.exe, also ohne eigene Konsole. Wer
ohne Konsole ein Konsolenprogramm startet, bekommt von Windows eine NEUE - und
die ist sichtbar. `capture_output=True` hilft nicht: es leitet die Datenstroeme
um, unterdrueckt aber kein Fenster. Und caps.py fragt jede Minute
`HandBrakeCLI --help`, `--preset-list` und `--version` ab, dazu makemkvcon aus
der Schluessel-Automatik: vier bis fuenf Fenster pro Minute, in Schueben.
Neues winlauf.py haelt CREATE_NO_WINDOW an EINER Stelle; alle elf Aufrufe in
caps.py, ripping.py und schluessel.py benutzen es. Auf Linux ist der Wert 0 und
creationflags=0 eine Nulloperation - im Worker-Container gegengeprueft, damit
derselbe Code auf beiden Seiten laeuft.
2. Die 7200 Sekunden sind CELERYS EIGENE UMRECHNUNG, nicht die Uhren. Erst fiel
auf, dass die Sekundenbruchteile nur 40 ms auseinanderliegen (.177269 vs
.134799) - derselbe Augenblick, zweimal verschieden gerechnet. Die Quelle sagt
warum (celery/utils/time.py):
def utcoffset(): # Sekunden WEST von UTC, in Stunden
return time.altzone // 3600 # CEST -> -2 ; UTC -> 0
def adjust_timestamp(ts, offset, here=utcoffset):
return ts - (offset - here()) * 3600
Absender VM (offset 0), Empfaenger Windows-PC (here() = -2):
ts - (0 - (-2)) * 3600 = ts - 7200. Celery verschiebt den empfangenen Stempel
also selbst und vergleicht ihn dann mit der eigenen Uhr. Die Annahme dahinter -
Ereignisse truegen Ortszeit - stimmt nicht, `Event()` stempelt Epoch.
Abhilfe gemessen, nicht geraten: Mit TZ=UTC meldet Windows utcoffset 0
(timezone=0, isdst=0 - auf dem Commander-PC geprueft), damit wird die
Umrechnung zur Nulloperation. Beide .bat-Dateien setzen es jetzt. Nebeneffekt
ist erwuenscht: Der Worker rechnet dann in derselben Zone wie die VM und wie
Rippys UI.
Fuer Rippy war die Meldung ohnehin folgenlos - /capabilities fragt per
Celery-Ping (Frage/Antwort, ohne Zeitstempel), nicht ueber die
Gossip-Ereignisse. Aber eine Warnung, die bei jedem Blick ins Log steht und
nichts bedeutet, kostet Vertrauen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
148ac494c2 |
feat(sprachen): Rippy fragt vor dem Rip, welche Sprachen du willst
Ampel / ampel (push) Successful in 29s
Commander-Anforderung: "Die Disc hat Material in X Sprachen und X Untertiteln -
Rippy muss VOR dem Rip fragen: Was genau willst du haben? In der Automatik muss
das ebenfalls einstellbar sein."
Die Auskunft lag laengst vor und wurde weggeworfen: Derselbe Titel-Scan, der die
Titel-Tabelle fuellt, liefert in derselben makemkvcon-Ausgabe die Streams mit.
Ein zweiter Info-Lauf haette eine Minute Wartezeit gekostet - jetzt kommt beides
aus einem Aufruf.
Format an der Akira-Blu-ray im Laufwerk gemessen (AGENTS Regel D):
SINFO:<titel>,<stream>,<attribut>,<code>,"<wert>"
1 = Typ ("Audio"/"Subtitles"), 3 = Sprachcode, 4 = Sprachname,
6 = Codec, 14 = Kanaele, 30 = Beschreibung
DIE FALLE dabei: Die Sprache steht in 3/4, NICHT in 28/29. Die tragen auf JEDEM
Stream "eng"/"English" - auch auf einer deutschen Tonspur und auf dem
Videostream; das ist MakeMKVs eigene Anzeigesprache. Wer 28 nimmt, haelt jede
Disc fuer englisch. Ein Test haelt das fest.
Angewendet wird die Wahl bei der KOMPRESSION, nicht beim Rippen - drei Gruende:
der Rip bleibt vollstaendig und verlustfrei (Muss-Feature laut KONZEPT); HandBrake
hat dafuer dokumentierte Schalter (--audio-lang-list / --subtitle-lang-list, die
genau die ISO-639-2-Codes nehmen, die MakeMKV liefert - beides gegengeprueft);
und wer spaeter andere Sprachen will, komprimiert neu statt die Disc wieder
einzulegen. Genau das sagt der Dialog auch, sonst glaubt man, es werde
unvollstaendig gerippt.
Nichts angeklickt heisst "alles behalten" - das Verhalten von vorher. Auch die
Einstellung ist bewusst LEER vorbelegt: Ein stilles "deu" wuerde bei einem
japanischen Original die Originaltonspur wegwerfen, ohne dass jemand gefragt hat.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
be04a9772e |
fix(auswurf): CDROMEJECT meldete Erfolg und tat nichts - erst entriegeln
Ampel / ampel (push) Successful in 29s
Commander-Meldung: "Den Button gibt es in den Settings, aber es passiert nicht,
das Laufwerk geht nicht auf." Am laufenden System nachgestellt, mit der Disc, die
gerade drin lag:
wirf_disc_aus("/dev/sr0") -> True
CDROM_DRIVE_STATUS danach -> 4 (Disc drin)
Das ioctl wird also ANGENOMMEN und tut nichts. Ursache: MakeMKV verriegelt
waehrend des Rips die Laufwerkstuer (CDROM_LOCKDOOR 1) und entriegelt sie nicht
wieder. Ein verriegeltes Laufwerk quittiert den Auswurf trotzdem mit Erfolg.
Gegenprobe an derselben Disc:
CDROM_LOCKDOOR 0 + CDROMEJECT -> Status 2 (SCHUBLADE OFFEN)
Genau das macht das Werkzeug `eject` immer: erst entriegeln, dann auswerfen.
Zweite Haelfte des Fixes, und die wichtigere: Das Ergebnis wird GEPRUEFT statt
geglaubt. Bisher gab wirf_disc_aus True zurueck, sobald das ioctl nicht geworfen
hatte - und ins Log kam "Disc ausgeworfen", waehrend die Schublade zu blieb.
Deshalb ist der Fehler in v3.14 durchgerutscht: Dort wurde richtig festgestellt,
dass die Einstellung von niemandem gelesen wurde, und danach WURDE sie gelesen -
ausgeworfen wurde weiterhin nicht. Jetzt wird das Laufwerk gefragt (bis zu 5 s,
die Schublade braucht ein bis zwei), und "kein Datentraeger" zaehlt mit, weil ein
Slot-Laufwerk keine Schublade hat.
Dieselbe Luecke steckte im Auswurf-Knopf der API (devices.eject) - dort mit
Klartext-Fehler, wenn die Disc drin bleibt.
Der Auswurf sitzt uebrigens schon an der richtigen Stelle: nach dem Rip, VOR dem
Einreihen der Kompression. Und das Laufwerk ist waehrend `transcoding` frei -
has_active_job blockiert nur bei pending/running, der Worker laeuft mit 4 Slots.
Die zweite Disc parallel war also nur am nicht aufgehenden Laufwerk gescheitert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
4195854bf8 |
feat(bausteine): Preset-Liste, Pfad-Vorschlag und Restzeit - alles gemessen
Vier neue reine Bausteine, jeder mit Tests. Sie beantworten Fragen, die Rippy bisher geraten oder gar nicht gestellt hat. 1. caps.parse_preset_liste - die Preset-NAMEN, die das HandBrake DIESES Workers wirklich kennt (`--preset-list`, Format im Worker-Image gemessen). Damit endet das Raten: die Namen unterscheiden sich je HandBrake-Version, und ein erfundener Name laesst die Kompression scheitern. Richtigstellung zum SAVEPOINT v3.16: Dort galt es als unmoeglich, die Hardware-Preset-Namen auf der Rippy-VM zu ermitteln, weil dort kein Hardware-Encoder laeuft. Gemessen ist das falsch - die Kategorie `Hardware/` steht vollstaendig in der Liste (VCN, NVENC, QSV, MF). HandBrake trennt zwei Fragen: --preset-list nennt alle Presets, --help nur die nutzbaren Encoder. Zwei Fragen, zwei Quellen. 2. mounts.pfad_map_vorschlag/pfad_map_zeile - der fehlende Anschluss fuer RIPPY_PATH_MAP. Geraten werden muss dafuer nichts: Rippy hat die Freigabe selbst eingehaengt und kennt ihre Quelle (//host/share). Mountpunkt plus Quelle IST das Mapping. NFS gibt bewusst "" - Windows-Schreibweise ist nicht ableitbar (AGENTS Regel D). Der Test fand dabei sofort die dokumentierte Windows-Falle: os.path.join baute `/app/media\rippy` in einen Container-Pfad, das Mapping waere still wirkungslos geblieben. _mountpoint nutzt jetzt posixpath. 3. presets.empfehlung - "immer das Beste" (Commander-Anforderung) ohne Punktesystem: fuer jede Lage eine feste Reihenfolge echter Namen, genommen wird der erste, den der Worker kennt. Hardware nur, wenn die Familie wirklich gemeldet ist (vce -> Preset heisst VCN, sonst liefe eine AMD-Karte unter dem Intel-Namen). vaapi und MF werden nie empfohlen: fuer vaapi gibt es kein Preset, bei MF ist die Nutzbarkeit nicht ablesbar. 4. eta - Restzeit aus dem gemessenen Fortschritt. Messreihe je Phase (Rip und Kompression haben nichts miteinander zu tun), Stillstand verlaengert die Schaetzung, und unter zwei Messwerten oder 60 Sekunden Spanne gibt es ehrlich keine Aussage. Test mit den echten 25.07.-Werten: 1,44 % in 29 min landet bei "noch ca. 1 Tag 23 h" - genau die Angabe, deren Fehlen den 50-Stunden-Lauf unsichtbar machte. Dazu: HandBrakes "Invalid preset <Name>" wird uebersetzt. Vorher stand im UI nur "HandBrake endete mit Code 3" - dass der Preset-NAME das Problem ist, war daraus nicht zu erraten. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
35cfcbcb07 |
style: echte Umlaute im ganzen Projekt + Installer im Rippy-Look
Ampel / ampel (push) Successful in 27s
Commander-Rueckmeldung: Umlaute fehlen. Ausloeser war sichtbar der Installer -
"Diese Maschine uebernimmt die Video-Kompression fuer Rippy" stand woertlich im
Screenshot.
## Die .ps1-Falle war loesbar, nicht unumgehbar
Bisher galt: ausgelieferte .ps1 MUESSEN ASCII sein, weil PowerShell 5.1 sie
ohne BOM als ANSI liest. Das ist nur die halbe Wahrheit - gemessen mit echtem
powershell.exe 5.1:
ohne BOM: $s = "Größe: äöü" + Unerwartetes Token -> Skript kaputt
mit BOM: Groesse: aeoeue + laeuft, Length 16 korrekt
Alle drei Skripte sind jetzt UTF-8 MIT BOM und tragen echte Umlaute; unter 5.1
gegengeprueft (BOM vorhanden, Parser fehlerfrei, Text korrekt gelesen). Der
Kopfkommentar sagt das jetzt richtig statt "ASCII-only".
## Umstellung: Text ja, Bezeichner nein
Umlaute gehoeren in Kommentare und Anzeigetexte, nicht in Funktionsnamen oder
Datenschluessel. Deshalb je Sprache das passende Werkzeug:
- Python: ueber den TOKENIZER - angefasst wurden ausschliesslich COMMENT- und
STRING-Tokens. 156 Stellen. Code ist damit garantiert unberuehrt.
- TypeScript: nur // und /* */ Kommentare sowie JSX-Text (kann per Definition
kein Bezeichner sein). 24 Stellen. `const waehlen`, `let laeuft`, `plaetze`,
`GeraetInfo` sind nachweislich unversehrt.
- install.sh: Anzeigetext, aber die Shell-Funktionen (gruen/rot/gelb/titel) und
der Schalter --nur-pruefen bleiben ASCII - das sind Schnittstellen.
- Markdown: 0 Aenderungen, die Doku hatte schon Umlaute.
ZWEI FEHLER MEINES KONVERTERS, beide von Werkzeugen gefangen:
1. In f-Strings steht in {...} CODE, kein Text. Aus f"{groesse}" wurde
f"{größe}", waehrend die Variable groesse hiess - Ruff meldete F821
"Undefined name". Der Konverter lagert Einsetzungen jetzt aus.
2. Ein Dict-Schluessel wurde umbenannt: die Wortliste enthaelt das PRAEFIX
"uebersprung", der Tabu-Schutz prueft aber ganze Woerter. bericht[...] ist
wieder ASCII - Umlaute in Datenschluesseln brechen JSON-Runden und DB-Felder.
## Installer im Rippy-Look
Statt hellgrau jetzt dieselben Toene wie das Web-UI (aus lib/design.ts
uebernommen): slate-900 Flaeche, dunkle Eingabefelder, Amber-Hauptknopf wie
"Los geht's" im Wizard. Oben ein Kopfbereich mit dem Farbverlauf
amber -> indigo -> purple und dem Disc-Symbol - in WinForms per Paint-Ereignis
gezeichnet, weil es dort keine Verlaeufe von der Stange gibt.
Geprueft, nicht gehofft: Das Fenster wurde headless in ein PNG gerendert
(DrawToBitmap) und angesehen - Verlauf, Symbol, Umlaute und Farben sitzen.
RippyWorkerSetup.exe neu gebaut (57344 -> 60416 Bytes); Umlaute und das
requireAdministrator-Manifest sind in der .exe verifiziert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
6a17af2118 |
feat(transcode,ui): Kompression je Disc-Typ abwaehlbar + Wizard rechnet mit der CPU
Ampel / ampel (push) Successful in 28s
Loest die offene Frage aus dem Savepoint ("UHD gar nicht komprimieren?") und
nimmt dem Wizard die Falle, in die er bisher fuehrte.
## Kompression je Disc-Typ abwaehlbar
Bisher gab es nur den globalen Schalter transcodeEnabled: alles komprimieren
oder nichts. Wer 4K verlustfrei behalten und DVDs trotzdem schrumpfen wollte,
hatte keine Moeglichkeit - obwohl genau das die vernuenftige Einstellung fuer
diese Maschine ist (4K-HEVC = gemessene 28-55 h je Film ohne AVX2).
Jetzt kann das Preset eines Disc-Typs auf den Reservewert "keine" stehen, dann
bleibt die verlustfreie Datei aus dem Rip stehen. Neue reine Funktion
komprimieren_fuer(disc_type, einstellungen); der globale Schalter schlaegt
weiter alles. preset_fuer() ueberspringt den Reservewert bewusst und gibt ihn
NIE als Preset-Namen zurueck - sonst bekaeme HandBrake `--preset keine` und
wuerde scheitern. Wer ueber "Neu komprimieren" ausdruecklich doch komprimieren
will, bekommt so ein brauchbares Preset statt eines Fehlers.
Der Reservewert kollidiert mit keinem echten Namen: gegengeprueft gegen alle
90 Presets aus `HandBrakeCLI --preset-list` im Worker-Image. Bei der
Gelegenheit auch die fuenf im UI angebotenen Namen geprueft - alle echt.
## Der Wizard empfiehlt nach GEMESSENER Rechenleistung
Vorher stand H.265 als Standard drin. Auf einer CPU ohne AVX2 sind das ein bis
zwei Tage pro 4K-Film - genau der Lauf, der am 25.07.2026 abgebrochen werden
musste. Der Wizard hatte die Zahlen sogar schon vorliegen (/capabilities
meldet cpu_simd und cpu_kerne), nur benutzt hat er sie nicht.
Jetzt: schwache CPU -> 4K wird nicht komprimiert, Blu-ray/DVD gehen auf H.264
(schneller als H.265). Starke CPU oder Hardware-Encoder -> H.265 durchgehend.
Der Wizard schreibt dabei ALLE vier Preset-Felder, nicht nur das allgemeine -
vorher fiel 4K auf ein 1080p-Preset zurueck und die Aufloesung war weg.
Gewarnt wird nur, wenn es belegt ist: schwacheEncoderCpu() verlangt mindestens
einen Worker mit BEKANNTER SIMD-Stufe und keinen mit Hardware-Encoder. Ein
Windows-Worker meldet "unbekannt" (dort gibt es kein /proc/cpuinfo) - dann wird
geschwiegen statt falsch gewarnt. Auf Windows gegengeprueft: 16 Kerne und
CPU-Modell kommen korrekt durch, encoders ist ohne HandBrake leer.
## Weitere Wizard-Haerten
- Kasten "Was Rippy gerade sieht": Laufwerk, Worker (mit Kernen/SIMD), freier
Platz. Jede Zeile hat bei Problemen eine HANDLUNGSANWEISUNG statt nur eines
Kreuzes - kein Laufwerk, kein Worker und wenig Platz sind die drei Faelle, in
denen man vorher ratlos dastand.
- Laedt alle drei Quellen parallel (Promise.allSettled) und wiederholt im
5-s-Takt: beim ersten Start laeuft der Worker noch hoch, vorher stand dort
dauerhaft "Noch kein Worker gemeldet" ohne Aussicht.
- API-Keys sind SICHTBAR statt als Punkte: das sind kopierte Keys, keine
Passwoerter, und einen Tippfehler sieht man in Punkten nicht.
- Keys werden direkt nach dem Speichern geprueft (/metadata/status). Ein
falsch kopierter Key faellt sofort auf, statt erst beim ersten Rip als
"Unknown Disc" - mit der Wahl "Key korrigieren" oder "Trotzdem fertigstellen".
## Einstellungen -> Verarbeitung
Alle drei Preset-Auswahlen bekommen "Nicht komprimieren", und beim 4K-Feld
erscheint die AVX2-Warnung mit der gemessenen Zahl - aber nur, wenn die
Maschine sie wirklich braucht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
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>
|
||
|
|
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
|
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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. |
||
|
|
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) |
||
|
|
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 |
||
|
|
42f19a0806 | ripping.py: HandBrakeCLI-Check + Typ-Erkennung | ||
|
|
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 |