isGermanStream wertete die Titel-Regex /\b(german|deutsch)\b/ fuer JEDEN nicht
deutsch-getaggten Audiostream aus — also auch fuer eine bereits anderssprachig
getaggte Spur (z.B. {language:"eng", title:"German Commentary"}). Der Kommentar
ueber dem Titel-Fallback sagt ausdruecklich, er sei "used when the language tag
is missing", aber genau diese Gating-Bedingung fehlte.
Folge: pickAudioTrack (der EINZIGE Caller) nimmt den ersten isGermanStream-
Treffer. Lag eine eng-Spur mit "German"/"Deutsch" im Titel VOR der korrekt mit
"ger" getaggten Spur, gewann die englische Spur. Der Remux behielt dann Englisch,
verwarf die echte deutsche Spur, ersetzte das Original atomar in-place und
strippte den .DL.-Marker — irreversibler Datenverlust mit falscher Sprache, vom
System als Erfolg ("german-tag"/"remuxed") gemeldet. Single-Trigger, kein
compound-Vorbedingung. Betrifft genau die vom Nutzer bestaetigte Tonspur-Funktion.
Fix: Titel-Fallback nur noch ausfuehren, wenn KEIN Sprach-Tag vorhanden ist
(`if (lang) return false;` vor der Titel-Pruefung) — deckt sich exakt mit der
dokumentierten Absicht des bestehenden Kommentars. Korrekt getaggte deutsche
Spuren gewinnen jetzt immer; eine anderssprachige Spur mit "German" im Titel wird
nicht mehr faelschlich gewaehlt. Untagged-Spuren nutzen weiter den Titel-Fallback
(unveraendert), und der German-Release-Mislabel-Pfad (German-first-Konvention)
greift weiterhin.
Runde-7-Audit (adversarisch verifiziert) hat ausserdem den deferred-Extraction-
Cluster abgeschlossen: #10 CRC-Kleindatei-Delete und #12 7z-Exit-1-als-Erfolg sind
BENIGN, #11 resume-empty-output not-confirmed (compound), #13 = das dokumentierte
LOW Companion-Overwrite (PP-1, compound, nur Sekundaerdateien).
Rot-bewiesen: zwei reine pickAudioTrack-Tests (eng-Titel-"German" vor echter ger →
audioRelIndex 1; eng-Titel-"Deutsch entfernt" ohne echte dt. Spur → skip) failen
ohne den Gate. Volle Suite 884 gruen, tsc unveraendert.
6.3 KiB
Offene Entscheidungen für dich (Audit-Loop 2026-06-17)
Diese zwei Punkte habe ich BEWUSST nicht autonom „gefixt", weil jede Lösung einen Produkt-/Geschmacks-Kompromiss enthält, den du entscheiden solltest, nicht ich. Beide sind verifiziert (Code-Zitat + Szenario), nur die Richtung ist deine Wahl.
1. Failover-Kappung durch globalen 60-Sekunden-Timeout (HIGH)
Was passiert (belegt):
download-manager.ts baut EINEN Timeout fürs gesamte Unrestrict:
const unrestrictTimeoutSignal = AbortSignal.timeout(getUnrestrictTimeoutMs()); // 60s
const unrestrictedSignal = AbortSignal.any([active.abortController.signal, unrestrictTimeoutSignal]);
Dieses EINE Signal geht an die komplette Provider-Kette in debrid.ts. Die 60s sind
also ein Budget für ALLE Provider zusammen, nicht pro Provider. Wenn Provider 1
(z.B. Mega-Web mit Account-Queue) das Budget verbraucht, dann sieht Provider 2 ein
bereits abgelaufenes Signal → debrid.ts wertet den Abbruch als „kein Failover" und
wirft, ohne Provider 2 echt zu versuchen.
Aktuell weitgehend latent: Seit v1.7.214 wird die API zuerst probiert (schneller Pfad), Mega-Web ist nur noch Fallback. Das Szenario „langsamer Provider 1 hungert Provider 2 aus" trifft in der Produktion derzeit selten. Deshalb dokumentiert statt dringend gefixt.
Deine Entscheidung — zwei Richtungen (gleiche Spannung, andere Seite):
-
A) Pro-Provider-Timeout: Jeder Provider bekommt sein eigenes frisches Budget. Failover bekommt IMMER einen echten Versuch. Kosten: Worst-Case-Wartezeit pro Item steigt. Das Budget ist dabei ein DREHregler, kein fixer Wert: 60s/Provider = bis 180s Worst-Case (3 Provider), 30s/Provider = bis 90s usw. Du akzeptierst langsameres Worst-Case-pro-Item für vollständigeres Failover — und stellst über den Pro-Provider-Wert ein, wie viel langsamer.
-
B) Globales Budget behalten, aber Slice für Failover reservieren: Provider 1 wird auf z.B. 35s gedeckelt, damit garantiert Zeit für Provider 2 bleibt. Kosten: Ein legitim langsamer Provider 1 (Mega-Web-Account-Queue bis ~90s) wird früher abgeschnitten → mehr Failover, auch wenn Provider 1 noch erfolgreich gewesen wäre.
Kernfrage, die nur du beantworten kannst: Wie lange darf ein Item bei einem langsamen aber funktionierenden Provider hängen, bevor wir ihn zugunsten des nächsten aufgeben?
2. Gespiegelter Mega API/Web-Schalter (HIGH, in Runde 3 als 2/3 bestätigt)
Was passiert (belegt): Die Mega-Debrid API- und Web-Account-Zeilen teilen sich EINE
login-only Enable-Flag (hasMegaDebridCredentials gilt für beide; die Pro-Modus-Auswahl
läuft über isMegaDebridModeEnabled(settings, "api"|"web")). Dein Report: „API ausschalten
schaltet Web an" — weil der Schalter sich spiegelt.
Warum ich es NICHT autonom geändert habe:
- Daten-Modell-Fix (echte unabhängige Flags) braucht eine Settings-Migration, die deaktivierte Accounts versehentlich re-aktivieren könnte.
- Die saubere UI-Variante (zwei echte unabhängige Schalter) ist ein Layout-Redesign — und du bist UI-Geschmack-sensibel; das will ich nicht ungefragt umbauen.
Deine Entscheidung: Ein gemeinsamer Schalter (API+Web zusammen an/aus, klar beschriftet) ODER zwei unabhängige Pro-Modus-Schalter (mehr Kontrolle, aber UI + Migration nötig)?
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 Eintrag in einer Endlosschleife hängen: eine interne „Viele-Fehler"-Pause halbierte die Zähler, sodass das eingestellte Limit nie erreicht wurde — der Eintrag scheiterte nie, blockierte dauerhaft einen Download-Slot und hämmerte den Anbieter (weil dabei auch die Anbieter-Sperre zurückgesetzt wurde). Jetzt wird das von dir eingestellte Limit hart eingehalten: nach N Versuchen scheitert der Eintrag sauber. Standard-Einstellung („unendlich", der Auslieferungs-Default) war nie betroffen. Rot-bewiesener Test.
-
Mega „bis Tagesreset gesperrt" parkt jetzt wirklich (statt alle 2 min neu zu versuchen): Wenn ALLE Mega-Accounts wegen wiederholt leerer Antworten bis zum Tagesreset geparkt waren, hat das Tool den Fehler bisher als normalen Umwandlungsfehler behandelt und den ganzen Tag alle ~2 Minuten neu probiert (und dabei den Provider-Circuit-Breaker mit Fehlern vollgemüllt). Jetzt erkennt es den Park und legt das Paket EINMAL bis zum Tagesreset schlafen — genau das, was der „bis Tagesreset"-Park eigentlich erreichen sollte. Bei Standard-Einstellungen heilte sich das vorher schon um Mitternacht selbst (kein Datenverlust), war aber unnötige Log-Flut und Churn. Rot-bewiesener Test.
-
MED Failover-Routing: Wenn ein Provider in den Manager-Cooldown läuft (≥20 Fehler in Folge) und auto-Fallback an ist, hat der Manager bisher zwar einen Ersatz-Provider berechnet, ihn aber WEGGEWORFEN — die Kette führte trotzdem wieder mit dem ausgebremsten Provider an. Jetzt wird der Ersatz-Provider als „Lead" durchgereicht und die Kette führt mit ihm an, OHNE einen Provider zu verlieren (der ausgebremste bleibt als letzter Notnagel in der Kette). Greift nur, wenn der Provider bereits nachweislich degradiert ist → strikt-besser-wenn-aktiv, kein Timeout/Cancel-Vertrag berührt. Rot-bewiesener Test. (Hält für Roll-up-Release bereit.)