Commit Graph
11 Commits
Author SHA1 Message Date
ScarriffleandClaude Opus 5 946de29893 Nachsehen, was in den Tonspuren wirklich steht
Die Sprachwahl vergleicht Kürzel, und Kürzel lügen — beim ZDF-Fall ist
die als deutsch ausgezeichnete Spur die mit Audiodeskription. Ob der
**Name** der Spur das rettet, sieht man nur, wenn man beides nebeneinander
legt. Alles andere wäre geraten, und davon hatten wir heute genug.

`--spuren <host> <suchbegriff>` sucht einen Titel und druckt zu jeder
Tonspur: Kürzel, Name aus der Datei, wie Jellyfin es zusammensetzt,
Codec, Kanäle und die Kennzeichen.

Dafür holt der Decoder jetzt auch `Title`, `IsHearingImpaired` und
`IsOriginal`. `Title` ist das zweite Signal neben dem Kürzel und
manchmal das einzige richtige: wo „eng" steht, kann im Namen „Deutsch"
stehen. Wir haben es bisher weggeworfen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 19:11:27 +02:00
ScarriffleandClaude Opus 5 efed8717a3 „Auto" gibt nicht mehr auf, es versucht es kleiner
Der Fehlstart im Zug hat den eigentlichen Mangel gezeigt: die ganze neue
Regelung misst **ab dem ersten Bild**. Kommt nie eines, misst sie nichts,
greift nichts — und „Auto" hat sich als das erwiesen, was es wörtlich
heisst: „nimm, was in den Einstellungen steht". Steht dort „Original",
bittet die App über eine Zugverbindung um eine 4K-Datei und wartet
vierzig Sekunden auf etwas, das nie kommen kann.

Statt aufzugeben geht der Watchdog jetzt eine Sprosse tiefer und baut
neu auf — bei Filmen über `restart()`, bei Sendern über den Tuner-Abbau.
Gezählt gegen dasselbe Budget wie die Sicherheitsleine, sonst schickt
eine tote Leitung die App endlos im Kreis.

Scheitert auch das, nennt die Meldung jetzt den Grund und den Weg statt
nur „keine Daten mehr": wer ohne Grenze angefragt hat, soll erfahren,
dass es daran liegt und wo es sich ändern lässt.

Und „Strom" heisst Stream. Zweiunddreissig Stellen, dazu das
Gedächtnis ergänzt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 18:30:10 +02:00
ScarriffleandClaude Opus 5 314c1a3bfc Die Schnipsel wiegen, nicht die Playlist zählen
Berechtigter Einwand: eine Playlist zu bekommen beweist gar nichts. Sie
ist Text und kostet ein Kilobyte; die Datenrate steckt in den
Schnipseln. Die vorige Fassung zählte `#EXTINF`-Zeilen und hätte
„funktioniert" gemeldet, auch wenn der Server bei jeder Stufe denselben
Strom ausliefert.

Jetzt lädt die Probe je Stufe den **ersten Schnipsel** und rechnet aus,
was er an Datenrate bedeutet — inklusive der unveränderten Stufe als
Vergleichsmass. Werden sie kleiner, trägt die Idee. Bleiben sie gleich
gross, rechnet der Server trotz anderer Zahl dasselbe, und ein
selbstgebautes Menü brächte nichts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 17:37:14 +02:00
ScarriffleandClaude Opus 5 f48eb55f35 Prüfen, ob wir uns die Leiter selbst bauen können
Der Wortlaut der Master-Playlist zeigt, woraus Jellyfins eigene Leiter
bestünde: dieselbe `main.m3u8`-Adresse, mehrfach, mit anderem
`VideoBitrate`. Eine Master-Playlist ist nur ein Menü.

Liefert der Server diese Unter-Playlists auch dann, wenn **wir** die
Zahl ändern, brauchen wir seine Zustimmung gar nicht — dann schreiben
wir das Menü selbst, und die Frage, warum er es verweigert, ist
gegenstandslos.

Die Probe versucht deshalb drei Stufen von Hand: halbe Bitrate, ein
Viertel, und ein Viertel zusammen mit `maxHeight=480`. Das letzte ist
der interessante Fall — Jellyfins eigene Leiter lässt die Auflösung
stehen und dreht nur an der Bitrate. Eine Stufe, die auch kleiner
rechnet, sieht bei wenig Bandbreite deutlich besser aus als dieselbe
Auflösung mit zu wenig Daten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 17:34:00 +02:00
ScarriffleandClaude Opus 5 6e18fda4aa Die Probe zeigt Fassung und Wortlaut
Der Proxy ist gelöst — Jellyfin hält die Verbindung jetzt für
ausserhalb —, und es kommt trotzdem nur eine Stufe. Damit sind alle
Hürden widerlegt, die im Quelltext von `master` stehen. Also stimmt
etwas an der Annahme nicht, und am wahrscheinlichsten ist es die
Fassung: ich lese womöglich den Quelltext einer anderen Version als der,
die dort läuft.

Deshalb meldet die Probe jetzt `Jellyfin <Version>` — und druckt bei nur
einer Stufe die Master-Playlist **im Wortlaut**. Ab da hilft keine
Zusammenfassung mehr: was fehlt, sieht man nur im Original.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 17:30:25 +02:00
ScarriffleandClaude Opus 5 e4e6cc6cbd Die Probe liest zurück, was der Server wirklich eingetragen hat
Ein Eintrag unter „Bekannte Proxys", der gespeichert, aber nicht
übernommen wurde, sieht von außen genauso aus wie gar keiner — und bei
der Fehlersuche unterscheidet das alles.

`GET /System/Configuration/network` führt `KnownProxies`. Zusammen mit
`IsLocal` und `IsInNetwork` steht damit in drei Zeilen, woran es liegt:
kein Eintrag, der falsche Eintrag, oder fehlender Neustart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 17:28:10 +02:00
ScarriffleandClaude Opus 5 539ea0aacb Die Probe zeigt beide Werte, nicht nur das Urteil
`IsLocal` und `IsInNetwork` beantworten verschiedene Fragen, und der
Unterschied benennt die Ursache: `IsLocal` heißt, die Anfrage kommt über
127.0.0.1 — dann steht der Proxy auf demselben Host, und ein Eintrag
unter „Bekannte Proxys" mit der LAN-Adresse geht ins Leere, weil Jellyfin
diese Adresse nie zu sehen bekommt.

Vorher stand nur „LOKAL" da, und damit blieb offen, ob der Eintrag fehlt
oder der falsche ist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 16:25:29 +02:00
ScarriffleandClaude Opus 5 d878289929 Der Server sagt jetzt selbst, ob er uns für lokal hält
Die Probe endete bisher mit einem Konjunktiv: „Kam dieser Aufruf von
zuhause, ist Punkt 1 die Erklärung." Das ist eine Vermutung an genau der
Stelle, an der die ganze Messung hängt.

`GET /System/Endpoint` beantwortet `IsInNetwork` mit **demselben**
Aufruf, mit dem auch die ABR-Sperre entscheidet:
`_networkManager.IsInLocalNetwork(HttpContext.GetNormalizedRemoteIP())`.
Damit steht als Erstes im Bericht, ob eine Leiter überhaupt möglich
wäre — und ob das Folgende eine Aussage über unterwegs enthält oder
keine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 15:43:55 +02:00
ScarriffleandClaude Opus 5 cdff53fa0d Eine Leiter bestellen statt einer einzelnen Stufe
Der Kern des Ruckelproblems: die App bestellte bei beiden Servern eine
HLS-Liste mit genau einer Variante. AVPlayer kann nur zwischen Stufen
wechseln, die in der Liste stehen — bei einer gibt es nichts zu wechseln,
und wenn die Leitung einbricht, kann nichts nachgeben.

**Jellyfin.** `enableAdaptiveBitrateStreaming` wird gesetzt, und zwar
ersetzend: die Voreinstellung im Server ist `false`, und bei zwei
gleichnamigen Werten gilt beim Server der erste — dieselbe Falle wie bei
`maxHeight` eine Funktion weiter oben. Dazu wird `main.m3u8` zu
`master.m3u8`, falls der Server die Schnipselliste nennt; nur auf der
Stufenliste kann der Parameter wirken.

Am Geräteprofil ändert sich **nichts**. Mehrere `TranscodingProfiles`
wären der naheliegende Fehlgriff — die beschreiben Formate, nicht
Bitraten. `MaxStreamingBitrate` bleibt die oberste Sprosse; was darunter
liegt, erfindet der Server.

**Plex.** `autoAdjustQuality=1`, als Eigenschaft der Anfrage statt als
feste Zeile: `queryItems` speist auch die Adresse zum Herunterladen, und
dort ergäbe eine Leiter keinen Sinn. Bewusst **nicht** am Entscheider —
der antwortet auf Unbekanntes mit nackten 400ern, wofür es hier eigens
`transcoderBisect` gibt. Er beantwortet ohnehin nur „darf das gespielt
werden". Stünde der Wert dort und nähme der Server ihn übel, wäre nicht
die Leiter kaputt, sondern die Wiedergabe.

Beides nur bei „automatisch". Wer im Blatt ausdrücklich „720p · 3 Mbps"
antippt, bekommt das und nicht „höchstens 3, meistens weniger" unter
unverändertem Etikett.

**Was das nicht kann, und das gehört dazugesagt:** Jellyfin verweigert
die Leiter im lokalen Netz grundsätzlich — „Within the local network this
will likely do more harm than good." Ein schwaches WLAN zählt dort mit,
und vom Client aus ist das nicht zu überstimmen. Ebenso fällt sie weg,
wenn Bild oder Ton nur kopiert statt gerechnet werden. Ob am Ende
wirklich mehrere Stufen ankommen, steht deshalb nicht im Code, sondern in
`PlaybackStatistics.variantCount`.

Elf neue Tests, darunter der doppelte Parameter, die andere
Schreibweise, und dass die Sitzungskennung beim Umbau dieselbe bleibt —
sonst bliebe beim Aufräumen ein Transcoder stehen.

Die Probe zeigt jetzt außerdem, ob kopiert statt gerechnet wird. Das ist
die zweite Hürde, und sie ist von zuhause aus nicht sichtbar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 15:26:57 +02:00
ScarriffleandClaude Opus 5 2d3c4adbba Die Probe räumt auf und sagt, woran es liegt
Sie hat am Server eine Transcode-Sitzung angelegt und nicht wieder
beendet — ein Messwerkzeug, das Arbeit hinterlässt, ist ein schlechtes.
Jetzt läuft `endPlayback` am Ende.

Und sie erklärt das Ergebnis, statt es nur hinzustellen. Kommt nur eine
Stufe zurück, nennt sie die Hürden aus Jellyfins eigenem Quelltext
(`DynamicHlsHelper.EnableAdaptiveBitrateStreaming`) — allen voran die
erste und überraschendste: im lokalen Netz liefert Jellyfin
**grundsätzlich** keine Leiter. Wörtlich dort: „Within the local network
this will likely do more harm than good." Ein schwaches WLAN ist für
Jellyfin auch nur lokales Netz.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 15:21:36 +02:00
ScarriffleandClaude Opus 5 afab93f53a FlixyProbe kann die Leiter zählen
Die Frage, von der alles Weitere abhängt, ist eine Tatsachenfrage:
Liefert der Server eine HLS-Liste mit mehreren Stufen oder mit einer?
Sie über einen Build aufs Gerät zu beantworten kostet einen halben Tag;
über HTTP kostet sie Sekunden. Genau dafür gibt es dieses Werkzeug.

`--playlist <adresse>` holt eine Playlist und zählt die
`EXT-X-STREAM-INF`-Zeilen mitsamt Bandbreite und Auflösung. Es
unterscheidet dabei die drei Fälle, die man auseinanderhalten muss: eine
Master-Playlist mit mehreren Stufen, eine mit genau einer — und eine
Varianten-Playlist, die gar keine Stufen führt, sondern Schnipsel. Die
letzte Verwechslung ist die naheliegende: `main.m3u8` sieht aus wie eine
Playlist und ist die falsche.

`--jellyfin <host>` meldet sich an, holt einen Film, lässt den Server
eine Transcode-Adresse aushandeln und prüft sie dreimal: unverändert,
als `master.m3u8`, und als `master.m3u8` mit
`enableAdaptiveBitrateStreaming=true`. Damit steht danach fest, ob der
Umbau in JellyfinBackend überhaupt etwas bringen kann.

Das Passwort wird eingetippt statt übergeben, ohne Echo und ohne Ablage.
Gedruckt werden Pfad und die **Namen** der Abfragewerte, nie die
vollständige Adresse mit Schlüssel — dieselbe Regel, nach der das
Werkzeug schon vorher gebaut war.

Beide Modi laufen vor der Plex-Anmeldung: die eine Frage hat mit Plex
nichts zu tun, die andere bringt ihre eigene Anmeldung mit.

Der Leser selbst ist gegen drei erfundene Playlists geprüft — mehrstufig,
einstufig, und eine Schnipselliste.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-27 15:02:43 +02:00