diff --git a/src/main/video-processor.ts b/src/main/video-processor.ts index bb1b9f8..bbc63b1 100644 --- a/src/main/video-processor.ts +++ b/src/main/video-processor.ts @@ -104,6 +104,9 @@ function isGermanStream(stream: ProbedAudioStream): boolean { // Free-text title fallback (used when the language tag is missing). Full words // only — the 2-3 letter codes ger/deu are too ambiguous in a title and would // pick the wrong track to keep (which then deletes the real German one). + if (lang) { + return false; + } const title = (stream.title || "").toLowerCase(); return /\b(german|deutsch)\b/.test(title); } diff --git a/tasks/audit-loop.md b/tasks/audit-loop.md index 35570e4..f6b38a7 100644 --- a/tasks/audit-loop.md +++ b/tasks/audit-loop.md @@ -165,6 +165,27 @@ Multi-Agent-adversarisch, Routing-Fix frueher advisor-gesegnet, Praezedenz 215/2 Runde-5/6-Charakterisierungen (PP-SEM-1 benign, DISK-1 deferred, deferred-LOW-Cluster #10/#11/#13 benign) NICHT released — dokumentiert. +## Runde 7 (Post-Download: Extraction + Video-Processor + Companion/Orchestrierung) — Workflow wcxk08n5i +3 Finder + adversarisch verifizieren. 2 confirmed, 0 refuted. Schliesst den deferred-Extraction-Cluster ab. +- **CONFIRMED MED (GEFIXT) VP-1 Falsche Tonspur:** isGermanStream (video-processor.ts:99-108) wertet die + Titel-Regex /\b(german|deutsch)\b/ fuer JEDEN nicht-deutsch-getaggten Stream — NICHT auf "Sprach-Tag fehlt" + gegated, obwohl der Kommentar (104-106) genau das als Absicht nennt. pickAudioTrack (124, EINZIGER Caller) + nimmt den ERSTEN Treffer → eine eng-Spur mit Titel "...German..." vor der echten ger-Spur GEWINNT → Remux + behaelt Englisch, verwirft die korrekte dt. Spur, ersetzt das Original atomar in-place (500) und strippt + .DL. → irreversibler Datenverlust + falsche Sprache, als Erfolg gemeldet. Single-Trigger (nicht compound). + Betrifft genau die vom Nutzer bestaetigte dt.-Tonspur-Funktion [[project_german_audio_feature]]. Fix: + `if (lang) return false;` VOR dem Titel-Fallback (deckt sich mit der Kommentar-Absicht). Rot-bewiesen + (2 Tests: eng-Titel-"German" vs echte ger → audioRelIndex 1; eng-Titel-"Deutsch entfernt" → skip). tsc=6. +- **DOKUMENTIERT, nicht gefixt (LOW compound) PP-1/#13 Companion-Overwrite:** renameCompanionFiles/ + moveCompanionFiles (dl-mgr 3735/3791) ohne Uniqueness-Guard (anders als MKV via buildUniqueFlattenTargetPath); + cross-volume copyFile ohne COPYFILE_EXCL (3696) → ueberschreibt einen vorhandenen Orphan-Companion still + (nur .srt/.idx/.nfo, nie Archiv/Video). Compound (Orphan + Namenskollision), Sekundaerdateien, Integrations- + TDD noetig → dokumentiert. Fix bekannt (Uniqueness-Guard spiegeln). +- **Deferred-Extraction-Cluster re-klassifiziert (aus Runde 2):** #10 CRC-Kleindatei-Delete BENIGN (failed + Archive aus cleanupSources ausgeschlossen, nicht geloescht); #12 7z-Exit-1-als-Erfolg BENIGN (nur Erfolg + wenn KEINE Error-Marker — echte CRC/Korruption korrekt als Fehler); #11 resume-empty-output NOT-CONFIRMED + (compound, unbewiesene Hybrid-Collect-Ordering-Annahme); #13 = PP-1. + ## Runde 6 (Retry/Backoff/Error-Klassifikations-State-Machine + Disk/IO) — Workflow wqurq83ma 3 Finder + adversarisch verifizieren. 1 confirmed (2/3), 3 refuted. Schliesst den deferred-LOW-Cluster ab. - **CONFIRMED HIGH (GEFIXT) SHELVE-LOOP-RETRYLIMIT:** Bei FINITEM retryLimit>=5 sind alle drei Per-Klasse- diff --git a/tasks/entscheidungen-offen.md b/tasks/entscheidungen-offen.md index 3cc53b2..3d468e3 100644 --- a/tasks/entscheidungen-offen.md +++ b/tasks/entscheidungen-offen.md @@ -63,6 +63,16 @@ ODER zwei unabhängige Pro-Modus-Schalter (mehr Kontrolle, aber UI + Migration n ## Erledigt in dieser Runde (zur Info, kein Handlungsbedarf) +- **Deutsche Tonspur: falsche Spur-Auswahl behoben (Datenverlust-Schutz):** Die Erkennung der + deutschen Tonspur hat den Titel-Text einer Spur („...German...") auch dann ausgewertet, wenn die + Spur bereits ein anderssprachiges Tag hatte (z.B. eine englische Spur mit „German" im Titel, wie + „German Commentary"). Lag so eine Spur VOR der korrekt mit „ger" getaggten Spur, wurde die falsche + (englische) behalten und die echte deutsche Spur beim Remux unwiderruflich verworfen — das Ergebnis + wurde als Erfolg gemeldet. Jetzt wird der Titel nur noch dann herangezogen, wenn gar kein Sprach-Tag + vorhanden ist (so war es ohnehin gemeint). Korrekt getaggte deutsche Spuren gewinnen jetzt immer. + Rot-bewiesener Test. (Noch nicht released — wird mit der nächsten Runde gebündelt.) + + - **Endlos-Wiederholung bei festem Wiederholungslimit behoben:** Wenn du ein FESTES Retry-Limit (z.B. 5) eingestellt hattest UND ein Link sprunghaft verschiedene Fehlerarten produzierte (mal Umwandlungs-Timeout, mal Abbruch mitten im Download, mal allgemeiner Fehler), konnte ein diff --git a/tests/video-processor.test.ts b/tests/video-processor.test.ts index ccdbcb9..90a31f6 100644 --- a/tests/video-processor.test.ts +++ b/tests/video-processor.test.ts @@ -92,6 +92,17 @@ describe("pickAudioTrack", () => { expect(d).toMatchObject({ action: "remux", audioRelIndex: 0, reason: "fallback-first-untagged" }); }); + it("tag mode does NOT let an eng track titled 'German' beat a correctly-tagged German track", () => { + const engTitledGerman = { language: "eng", title: "German Commentary" }; + const d = pickAudioTrack([engTitledGerman, ger], "tag"); + expect(d).toMatchObject({ action: "remux", audioRelIndex: 1, reason: "german-tag" }); + }); + + it("tag mode does NOT pick a non-German-tagged track just because its title contains 'Deutsch'", () => { + const d = pickAudioTrack([{ language: "eng", title: "Deutsch entfernt" }, { language: "fre", title: "" }], "tag"); + expect(d).toMatchObject({ action: "skip", reason: "no-german-track" }); + }); + it("tag mode with single German -> single (no remux)", () => { expect(pickAudioTrack([ger], "tag")).toMatchObject({ action: "single" }); });