Commit Graph
445 Commits
Author SHA1 Message Date
ScarriffleandClaude Opus 5 70ab4cc421 Mein Prüfbild war dunkler als jeder echte Abspann
Die Abspannsuche lief gegen eine feste Schwelle von 35. Die stammte aus
einem erzeugten Prüfbild mit 0,8 Prozent weisser Fläche — Helligkeit 18,
weit unter 35, alles schien zu stimmen. Ein echter Abspann hat mehr
Schrift.

Nachgemessen an 1080p mit zwei Spalten Namen, durch dieselbe ffmpeg-Kette
wie im Betrieb:

    Handlung                              126
    Abspann, realistische Schriftdichte     32
    Abspann, dicht gesetzt                  47

Die Fünfunddreissig lag mitten zwischen den beiden Abspannfällen und
schnitt sie auseinander. Dasselbe noch einmal an der erzeugten Prüfdatei,
nachdem ihr Abspann realistische Dichte bekam: 40,2 — und die Prüfung,
die vorher grün war, wurde rot. Das ist der Fehler, lokal reproduziert.

**Dunkel ist keine absolute Grösse.** Entscheidend ist nicht, wie dunkel
der Abspann ist, sondern dass er viel dunkler ist als das, was davor
lief. Gemessen wird jetzt gegen den Grundton des Films — das obere
Viertel der Proben, mal 0,55. Die alte Schwelle bleibt als Boden, damit
ein durchweg dämmriger Film nicht in Fehlalarme rutscht.

**Und die Logotafel.** Die Suche verlangte, dass die allerletzte Probe
dunkel ist. Hinter dem Abspann steht bei vielen Produktionen noch eine
Tafel — Sender, Studio, Förderer —, oft hell. Ein einziges weisses
Schlussbild machte damit den ganzen Abspann unsichtbar. Zwanzig Sekunden
sind jetzt erlaubt, in Sekunden gezählt und nicht in Proben: wie viele
Messpunkte auf eine Tafel fallen, hängt allein an der Schlüsselbilddichte
der Datei.

**Ein Lauf ohne Fund sagt jetzt, warum.** Anzahl Proben, Schwelle,
letzte Probe — ohne diese drei Zahlen ist „kein Abspann erkannt" keine
Auskunft, und man rät wieder.

Sieben neue Prüfungen mit den gemessenen Werten. Die beiden
entscheidenden sind mit der alten Schwelle rot; gegengeprüft, nicht
behauptet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-14 21:57:39 +02:00
ScarriffleandClaude Opus 5 7e5b3fb0ee Eine Staffel mit einer Folge fiel ganz durch
Nein, die Erkennung sieht sich nicht die ganze Serie an — sie gruppiert
nach Staffel, vermerkt je Staffel, und der eindeutige Schlüssel führt die
Staffel mit. Andere Besetzung, anderer Abspann, andere Musik in Staffel 2
stören den Abgleich also nicht. Der Verdacht war berechtigt, die Stelle
eine andere.

Gefunden hat ihn die Frage trotzdem. Ganz oben in der Staffelschleife
stand `if (geordnet.Count < 2) continue;` — richtig für den Tonabgleich,
der zwei Folgen zum Vergleichen braucht. Seit es den Bildweg gibt, ist es
zu früh: der braucht keine zweite Folge, nur eine Datei. Eine laufende
Serie, von der erst die Premiere der neuen Staffel da ist, bekam deshalb
gar nichts — weder über den Ton, was stimmt, noch über das Bild, was
hätte gehen müssen.

Jetzt läuft der Tonabgleich nur, wenn es etwas zu vergleichen gibt, und
der Bildweg in jedem Fall. Mit Vermerk, sonst liefe er bei jedem Scan
von Neuem.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-14 21:27:41 +02:00
ScarriffleandClaude Opus 5 ef667a9f39 Erst für sich, dann mit der Bedienung
Die Acht-Sekunden-Frist war geraten, und sie war die falsche Antwort auf
eine richtige Beobachtung. Ein Zeitgeber entscheidet für den Zuschauer,
wann er genug gesehen hat; das kann er selbst besser.

Jetzt gilt für Vorspann und Abspann, Web wie App, dieselbe Regel: eine
neue Marke zeigt ihre Knöpfe von selbst, ohne dass man das Bild
anfassen müsste. Sobald die Bedienung einmal eingeblendet war, gehören
sie zu ihr und gehen mit ihr — ein- wie ausblenden. Eine neue Marke
fängt wieder von vorn an; sie ist ein neues Angebot.

**Der Übergang zählt, nicht der Zustand.** Beim Start liegt die
Bedienung ohnehin da, und `zeigen()` läuft im Web bei jeder
Mausbewegung. Beides als „einmal gezeigt" zu werten hiesse, dem Intro
seinen Knopf zu nehmen, bevor es ihn je hatte. Gewertet wird deshalb nur
der Sprung von verborgen nach sichtbar.

Am Ende des Films bleiben die Knöpfe stehen: dort ist „Nächste Folge"
die einzige noch offene Frage, und es gibt kein Bild mehr, das sie
verdecken könnten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-14 16:57:31 +02:00
ScarriffleandClaude Opus 5 820789b7f6 Die Ausnahme löste nichts und stand dafür im Bild
„Beim Abspann kommt kein Knopf" hatte ich als zu kurze Frist gedeutet und
die Abspann-Knöpfe dauerhaft gemacht. Die Frage war falsch gestellt: es
kam keiner, weil dem Staffelfinale die Marke fehlte — der Tonabgleich
findet sie dort nicht, weil das Finale anders ausklingt. Das ist
inzwischen behoben, über das Bild.

Geblieben war die Ausnahme, und sie liess einen Knopf sechs Minuten lang
über dem Bild stehen, auch nachdem die übrige Bedienung längst weg war.
Jetzt gilt für Vorspann und Abspann dieselbe Frist: acht Sekunden von
selbst, danach zusammen mit der Bedienung. Am Ende des Films bleiben sie
— dort ist es die einzige offene Frage, und es gibt kein Bild mehr, das
sie verdecken könnten.

Im Web steht die Ausnahme noch; dort fällt sie nicht auf, weil die
Bedienung bei jeder Mausbewegung ohnehin zurückkommt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-14 16:52:34 +02:00
ScarriffleandClaude Opus 5 93f4dfd8e9 Ein frischer JSONDecoder, drei Zeilen neben der Warnung davor
Im Web stand am Abspann „Nächste Folge", in der App nur „Abspann
überspringen". Der Server war es nicht: beide fragen denselben Endpunkt,
und der ordnet nach Staffel und dann nach Nummer — er findet also auch
die erste Folge der nächsten Staffel.

Es war `nachbar`. Die Stelle baute sich einen frischen `JSONDecoder()`,
und der kennt das Datumsformat des Servers nicht. Solange die
Nachbarfolge weder `publishAt` noch `lastPlayedAt` mitbrachte, ging es
gut — mit eingeschalteter Prüfung bringt sie ein `publishAt`. Das `try?`
schluckte den Fehler, und von aussen sah es aus, als gäbe es keine
nächste Folge: kein Knopf, kein Hinweis, nichts.

In `FlaroClient` steht seit je ein eingerichteter Dekoder, ausdrücklich
nicht privat, „damit die Prüfungen denselben Dekoder benutzen" — und
direkt darunter die Warnung, dass ein frischer an genau diesem Format
scheitert. Diese eine Stelle las sie nicht.

Vier Prüfungen dazu, darunter die mit Datumsangaben: mit dem alten
Dekoder ist sie rot, mit dem neuen grün. Gegengeprüft, nicht behauptet.

Die übrigen frischen Dekoder im Quelltext lesen nur, was dieselbe App
vorher selbst geschrieben hat — Zwischenspeicher, Abzüge, Offline-
Angaben. Die laufen rund und bleiben.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-14 08:39:31 +02:00
ScarriffleandClaude Opus 5 ce4da992ea Einen Knopf je Serie ist bei fünfundneunzig kein Angebot
Es gab ihn: auf der Serienseite, das Uhrsymbol. Nur gilt er für genau
eine Serie — und nach jeder Änderung an der Erkennung will man ohnehin
alles noch einmal. Der Weg dorthin fehlte da, wo man ihn sucht: bei der
Mediathek, neben „Scannen" und „Metadaten auffrischen".

Der Lauf selbst war schon da. `NachScanAsync` macht genau das, Serien
über den Tonabgleich und Filme über das Bild — er hing bloss am Scan und
liess sich nicht von Hand anstossen. Jetzt nimmt er ein „erneut" entgegen
und ist über einen Endpunkt erreichbar. Die Antwort kommt sofort: über
einen grossen Bestand dauert das Stunden, und eine Anfrage so lange offen
zu halten hiesse, sie in ein Zeitlimit laufen zu lassen. Wie weit es ist,
steht im Protokoll von heute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 21:01:11 +02:00
ScarriffleandClaude Opus 5 1340176bf0 Beim Staffelfinale klingt der Abspann anders
Und genau daran fiel er durch. Der Tonabgleich lebt davon, dass der
Abspann in jeder Folge derselbe ist; beim Finale ist er es oft nicht —
anderer Schluss, andere Musik, kein Treffer. In jeder Staffel fehlte
deshalb genau eine Marke, immer die letzte, und wer dort weitersah, sah
keinen Knopf. Das war der ganze Fehler. Der Spieler war nie schuld, und
meine Schranken-Vermutung von eben war falsch.

Was der Ton nicht findet, sucht jetzt das Bild — derselbe Weg wie bei
einem Film: dunkel werden und bis zum Ende durchhalten. Das Verfahren
lag fertig in `FilmAsync` und war nur dort eingebaut; es steht jetzt für
sich und wird von beiden benutzt. Nur für die Lücken: bei einer Staffel
ohne fehlende Marke läuft der Abtaster gar nicht.

**Drei Punkte heissen „mehr davon", nicht „tu etwas".** Bei einer Folge
taten sie etwas — wegräumen aus „Fortsetzen", ohne Rückfrage. Jeder, der
sie sah, hat ein Menü erwartet, draufgetippt, und dann baute die Seite
sich neu auf und die Punkte waren weg. Jetzt ein Kreuz, und eine Zeile,
die sagt, was geschehen ist.

Und die Markenanzeige nennt die Zeiten, nicht nur die Namen: dass eine
Marke da ist, sagt noch nicht, dass sie an der richtigen Stelle steht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 20:49:50 +02:00
ScarriffleandClaude Opus 5 74643b8242 Gefunden und gleich wieder weggeworfen
**Stream, nicht Strom.** Mein Fehler, und die Regel kenne ich: Fachbegriffe
bleiben englisch. Betroffen war eine Meldung im Spieler und vier Zeilen im
Tagesprotokoll.

**Der Abspann fiel durch die eigene Schranke.** `Hoechstlaenge` von fünf
Minuten galt für Vorspann und Abspann gleichermassen. Fünf Minuten sind
für einen Abspann aber keine Obergrenze, sondern die Regel — eine deutsche
Serienproduktion listet Sprecher, Synchronregie und Studio hinterher, und
sechs Minuten kommen vor. Der Tonabgleich fand das Stück, und die Zeile
darunter warf es weg. Von aussen sah das aus wie „nichts gefunden".
Der Abspann darf jetzt so lang sein wie sein Suchfenster; weiter reicht
eine Marke ohnehin nie.

**Vermutung, nicht Messung** — das Stück steht auf einem Server, an den ich
nicht komme. Deshalb dasselbe Commit:

**Man kann jetzt nachsehen.** Neben jeder Folge steht für Verwalter, was
die Erkennung gefunden hat: „Vorspann + Abspann", „Vorspann" oder „keine
Marken". Ob eine Marke fehlt oder bloss nicht angezeigt wird, war von
aussen nicht zu unterscheiden — und beides hat eine andere Ursache. Die
Angabe kostet nichts: sie steht längst in der Antwort des Servers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 20:33:52 +02:00
ScarriffleandClaude Opus 5 a360bed02b Vier Stellen, an denen eine Angabe unterwegs verlorenging
**Der Aufmacher wusste nur die Serie.** `Heroeintrag.titel` ist bei einer
angefangenen Folge der Name der Serie — richtig, denn der Aufmacher zeigt
die Serie. Wer von dort startete, las über dem Spieler „Biohackers" und
nicht, welche Folge läuft. Staffel, Nummer und Folgentitel reisen jetzt
mit. Dasselbe im Aufmacher selbst: „Staffel 1 · Folge 2" statt „S1 · F2".

**Der Abspann ist kein Angebot, sondern eine Frage.** Die Acht-Sekunden-
Frist von gestern war für das Intro gedacht und traf den Abspann mit:
„Nächste Folge" verschwand genau dort, wo man hinsieht. Ein Intro-Knopf
geht, wenn man ihn nicht nimmt; der Abspann-Knopf bleibt, bis die Folge
zu Ende ist. Web und App.

**„deu" stand da, weil es in der Datei steht.** Der Server reichte einen
vorhandenen Spurnamen unbesehen durch — und viele Dateien tragen als
Titel schlicht das Sprachkürzel. Wiederholt er bloss die Sprache, gilt er
nicht, und die Tabelle darunter macht „Deutsch" daraus.

**Und zweimal „Deutsch" ist keine Wahl.** Zwei deutsche Untertitelspuren
sind der Normalfall — Vollfassung und Nur-Fremdsprachiges. Gleichnamige
bekommen jetzt ihren Codec dazu, und wenn der auch gleich ist, die
Nummer. Das kann keine Spur für sich beantworten: ob ein Name eindeutig
ist, hängt an den anderen. Deshalb steht es in `Benennung` und hat fünf
Prüfungen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 17:34:11 +02:00
ScarriffleandClaude Opus 5 d152ac3795 Der Regler gehörte der Uhr, nicht dem Finger
`zeitAuffrischen` schrieb `zeitleiste.value` bei jedem `timeupdate` neu —
viermal je Sekunde, auch mitten im Ziehen. Das hatte zwei Gesichter, und
nur das harmlosere war zu sehen: der Knopf sprang unter dem Finger an die
laufende Stelle zurück, und nach dem Loslassen noch einmal, weil ein
Sprung einen Augenblick braucht und der Spieler in dem weiter die alte
Stelle meldet.

Das andere ist schlimmer. Gemessen an einer Nachbildung mit 20-ms-Takt:
gezogen auf 113, und `onchange` las 7 — der Takt hatte `value` überschrieben,
bevor der Browser den Zug festschreiben konnte. Es sprang also nicht nur
zurück, es sprang an die falsche Stelle. Genau deshalb half Festhalten: es
schiebt den letzten `input` näher an den `change`.

Jetzt gehört der Regler dem Zeiger, solange einer darauf liegt, und danach
dem Sprungziel, bis der Spieler dort angekommen ist. Mit Notbremse nach
dreissig Sekunden, damit eine Leiste nie stehen bleibt, wenn ein neu
gebauter Strom woanders herauskommt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 16:39:28 +02:00
ScarriffleandClaude Opus 5 0186087051 Ein Angebot, das keiner annimmt, nimmt man zurück
„Intro überspringen" soll erscheinen, ohne dass man den Bildschirm
antippen muss — das war der Wunsch, und er war richtig. Nur blieb der
Knopf dann liegen, solange die Marke dauert: bei einem Abspann sechs
Minuten lang ein Knopf über dem Bild, auch nachdem die übrige Bedienung
längst weggeblendet war.

Jetzt hat er eine eigene Frist. Acht Sekunden von selbst, lang genug zum
Bemerken und Treffen; danach gehört er zur Bedienung wie alles andere
und kommt mit einem Antippen zurück. Am Ende des Films bleibt er stehen
— dort ist er die einzige Frage, die noch offen ist.

Im Web dasselbe, plus die Stelle, an der es im Stehen auseinanderfiel:
`markenstand` rechnet nur, während das Bild läuft. Wer pausiert im Intro
die Maus bewegte, bekam die Bedienung zurück und den Knopf nicht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 16:16:15 +02:00
ScarriffleandClaude Opus 5 fbd865e93b Heruntergeladen heisst nicht: ohne Angaben
Bei einer lokalen Datei kehrte der Spieler zurück, sobald sie lief — und
liess `item` leer. Daran hing mehr als der Titel: keine Marken, also kein
„Intro überspringen"; keine Nachbarfolgen, also keine Knöpfe zum Blättern.
Nur bei Heruntergeladenem, und darum sah es so lange nach einem Fehler in
der Erkennung aus. Jetzt werden die Angaben nachgeholt, während das Bild
schon läuft.

Dazu, was derselbe Weg betrifft: der Spieler sagt „Staffel 1 · Folge 6"
statt „S1 E6" — der Folgenname wird an einer Stelle gebaut, nicht an
dreien. Im Abspann einer Serie stehen zwei Knöpfe statt einem, weil der
Abspann zwei Fragen stellt.

Und die Abdrücke, mit denen der Tonabgleich geprüft wird, sind jetzt
echte: zwei Aufnahmen desselben dreissigsekündigen Stücks, verschiedene
Bitraten, durch fpcalc gedreht. Vorher war jede Prüfung mit erfundenen
Zahlen bestanden — und genau deshalb war nie belegt, dass der Abgleich an
echten Daten etwas findet. Er findet: 17,8–51,0 s und 72,7–105,9 s, bei
20–50 und 75–105.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 16:03:57 +02:00
ScarriffleandClaude Opus 5 afa78f9ee0 Ein Knopf, von dem niemand weiss, dass es ihn gibt, ist keiner
„Intro überspringen" lag im Web in der Bedienleiste und verschwand mit
ihr. Am Fernseher sieht man die Leiste gar nicht — der Knopf war also
da und trotzdem unsichtbar. Jetzt liegt er als eigene Schicht über dem
Bild und bleibt stehen, solange die Marke läuft.

**Im Abspann ist „überspringen" ohnehin die falsche Frage.** Was man
dort will, ist die nächste Folge; ans Ende dieser zu springen bringt
niemanden weiter. Gibt es eine, heisst der Knopf jetzt so — im Web wie
in der App, und in der App nicht mehr erst, wenn alles durchgelaufen
ist. Bei einem Film gibt es nichts danach: dort heisst „Abspann
überspringen" jetzt wirklich Schluss, statt auf ein stehendes Bild zu
spulen und den Spieler offen zu lassen.

Dazu der Titel über dem Spieler. Dort stand bei einer Folge „S1 E6" und
bei einer aus der Detailseite gestarteten sogar nur „Wiedergabe". Auf
einer Kachel ist die Kurzform richtig, dort zählt jeder Buchstabe; über
dem Spieler steht eine Zeile in einer leeren Fläche. Jetzt steht da
„Küstenwache · Staffel 1 · Folge 6 · Der Nebel kommt". In der App hiess
es „Episode" statt „Folge" — das eine Wort, das sonst nirgends steht.

Und drei Prüfungen für die Marken auf dem Weg in die App: aus einer
Serverantwort mit Vorspann und Abspann werden zwei Marken an der
richtigen Stelle. Die Übersetzung war nicht der Grund, warum der Knopf
dort fehlte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 15:35:59 +02:00
ScarriffleandClaude Opus 5 7673c73757 Vier Sekunden, die ffprobe zu früh aufhörte zu lesen
Die Untertitel kamen vier Sekunden zu spät. Nicht an ihnen lag es: der
Server meldete dem Spieler einen Anfang, der vor dem lag, an dem der
Strom wirklich begann, und genau diese Differenz landet eins zu eins im
Versatz.

Die Schlüsselbildsuche las mit `-read_intervals` bis eine halbe Sekunde
hinter den Wunsch. ffprobe bricht am Ende eines Fensters auf Paketebene
ab — das letzte Schlüsselbild darin kam regelmässig gar nicht mehr
heraus, und die Suche gab das davor zurück. Bei Bildgruppen von vier
Sekunden sind das vier Sekunden.

Nachgemessen gegen die Stelle, an der ffmpeg tatsächlich anfängt, an
einer Datei mit Schlüsselbildern alle vier Sekunden:

    Wunsch   Suche (0,5 s)   ffmpeg    Abweichung
      52,0            48      52,0         −4,0
      73,3            68      72,0         −4,0
     100,2            96     100,0         −4,0

Mit zehn Sekunden Nachlauf lag dieselbe Messung bei allen sieben Werten
auf 0,000. Was über den Wunsch hinausgelesen wird, verwirft die
Filterung ohnehin.

Die Prüfung vergleicht nicht gegen eine erwartete Zahl, sondern gegen
ffmpeg selbst — mit dem alten Wert fällt sie um.

Dazu der Filmteil der Abspannerkennung: `Abspannkante` als reine
Rechnung mit elf Prüfungen, `Bildabtaster` über ffmpeg, Marken auch an
Filmen, Knöpfe zum Suchen und Verwerfen auf der Filmseite. An einer
erzeugten Datei trifft die Kante auf vier Sekunden genau.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 06:42:16 +02:00
ScarriffleandClaude Opus 5 8112c15d4d Jeder Scan hätte jede Tonspur noch einmal gelesen
Gemerkt wurde nur, was gefunden wurde. Eine Staffel ohne Abspann — es
gibt genug davon — sah damit bei jedem Scan aus wie eine, in der noch
niemand nachgesehen hat, und wurde wieder abgetastet: jede Tonspur jeder
Folge noch einmal von der Platte, für immer, ohne Ertrag. Bei
sechstausend Folgen ist das kein Schönheitsfehler.

Jetzt steht auch „gesucht und nichts gefunden" in der Datenbank, je
Staffel und Art. Ausgelöst wird ein zweiter Lauf von der Folgenzahl:
kommt eine Folge dazu, gibt es etwas Neues zu vergleichen, sonst nicht.
Ein Zeitstempel allein täte das nicht — eine Staffel, die sich nie
ändert, hat nie einen Grund für einen zweiten Lauf.

Dazu der Knopf, der ausdrücklich doch noch einmal rechnet: die Uhr auf
der Serienseite sucht ab jetzt immer neu. Von selbst läuft die Suche
nach jedem Scan und überspringt dort das Abgesuchte; wer hier drückt,
will genau das Gegenteil.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-13 05:51:23 +02:00
ScarriffleandClaude Opus 5 9bcdd239d7 Entwurf: den Abspann eines Films im Bild finden
Der Tonabgleich kann bei Filmen grundsätzlich nichts finden — er erkennt
einen Abspann daran, dass er sich über die Folgen einer Staffel
wiederholt, und ein Film hat nichts, womit er sich vergleichen liesse.

Der Entwurf steht auf zwei Messungen statt auf Vermutungen: an einem
erzeugten Film liegt die mittlere Helligkeit in der Handlung bei 125 und
im Abspann bei 18, mit einer scharfen Kante genau am Übergang. Und das
Dekodieren der letzten Minuten kostet 2,89 Sekunden, wenn man jedes
zweite Bild nimmt, aber 0,24, wenn man sich auf Schlüsselbilder
beschränkt.

Dazu steht drin, wo das Verfahren danebenliegt: ein Abspann über
laufendem Bild hat keine dunkle Strecke und bekommt deshalb keinen Knopf.
Das ist die richtige Antwort — ein geratener Knopf schnitte Handlung weg.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 22:12:15 +02:00
ScarriffleandClaude Opus 5 fd79fb4022 „No such file or directory" über Dateien, die da waren
Im Protokoll stand für jede einzelne Folge, fpcalc könne die Datei nicht
öffnen — während der Spieler dieselbe Datei im selben Augenblick
umpackte. Null Marken, und der Grund stand nicht da.

`-ts` ist bei fpcalc kein Zeitstempel, sondern ein Schalter: „gib
Zeitstempel aus". Die Sekundenzahl dahinter las fpcalc als zweiten
Dateinamen, fand ihn nicht und brach ab, bevor es die echte Datei
überhaupt ansah.

Nachgemessen am Binärprogramm aus dem Abbild: einen Startpunkt gibt es
bei fpcalc gar nicht. `-length` begrenzt nur die Dauer vom Anfang an —
für den Abspann braucht es aber das Ende. Also einmal die ganze Spur je
Folge, und Vorspann wie Abspann sind danach zwei Ausschnitte aus
demselben Abdruck.

Das ist nicht nur richtig, sondern billiger: eine Folge von 45 Minuten
kostet 1,6 Sekunden und ergibt 21 786 Werte — gegenüber zwei
Ausschnitten, die zusammen mehr gekostet hätten und nie funktionierten.
Die Rate von 0,1239 Sekunden je Wert steht jetzt als Prüfung daneben.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 22:09:56 +02:00
ScarriffleandClaude Opus 5 2c535e6f47 Drei Wege, die über ein Neuladen führten
**In „Fortsetzen" startet ein Tipp.** Dort steht ein Titel, *weil* man ihn
angefangen hat, und die Stelle steht daneben — der Umweg über die
Detailseite stellte eine Frage, die schon beantwortet war. Überall sonst
bleibt es beim Weg auf die Seite: wer nachsehen will, wie viele Staffeln
eine Serie hat, soll nicht den Film bekommen.

**Ein Haken nimmt die Kachel mit.** In „Fortsetzen" und „Als Nächstes"
steht, was offen ist. Eine abgehakte Folge ist nicht mehr offen — sie mit
einem Haken stehen zu lassen sah aus, als hätte das Abhaken nicht
gewirkt. Dasselbe für „Aus Fortsetzen entfernen": in der Reihe selbst
heisst entfernen genau das.

**Und ein getauschtes Bild erreicht den Aufmacher.** Wer auf der
Startseite ein Plakat wechselt, sieht denselben Titel gleich darüber in
voller Breite — dort stand bis zum nächsten Neuladen das alte. Die
Kachel frischt sich selbst auf; der Aufmacher steht ganz woanders und
erfuhr nichts davon. Jetzt meldet der Bilderdialog es der ganzen Seite,
und wer es angeht, hört zu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 21:54:50 +02:00
ScarriffleandClaude Opus 5 adca700c4a Marken suchen, ohne dass jemand danach fragt
Eine neue Folge bekommt keine Vorspann-Marke, wenn niemand den Knopf
drückt — und niemand drückt ihn, weil man nicht weiss, dass es etwas zu
drücken gibt. Der Scan ist der Augenblick, in dem neue Folgen entstehen;
jetzt hängt sich der Lauf dort hinten an.

Eine Serie nach der anderen, nicht alle zugleich: jede liest von jeder
ihrer Folgen ein Stück Ton, und zwanzig gleichzeitig wären zwanzig
Leseköpfe auf derselben Platte. Gerechnet wird nur, wo noch nichts
steht — beim ersten Mal über einen grossen Bestand dauert das
entsprechend, danach findet der Lauf nichts mehr zu tun.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 21:52:24 +02:00
ScarriffleandClaude Opus 5 1d70be0f99 Fünf Aufmacher je Titel, und der Abspann zählt als Schluss
**Der Aufmacher darf wechseln.** Bisher hing hinter jedem Titel genau ein
Hintergrundbild, und das Karussell war nach einer Woche ein Standbild.
Jetzt lassen sich bis zu fünf Aufnahmen aussuchen — im Bilderdialog unter
einem vierten Reiter, gespeist aus denselben Hintergründen.

Welches gerade gilt, entscheidet der Server aus Uhrzeit und Kennung: alle
fünf Stunden ein anderes, überall dasselbe — im Web, in der App, nach
einem Neustart. Ein Zufall je Abruf hiesse, dass das Bild beim Blättern
springt; eine gespeicherte Wahl hiesse einen Schreibvorgang je Titel und
Fenster. Die Kennung geht mit in die Rechnung, damit nicht alle Titel im
selben Augenblick umschalten.

Plakat und Hintergrund bleiben unberührt. Sie stehen hinter Kacheln und
Kopfzeilen, und dort soll nichts wechseln.

**Und der Abspann zählt als Schluss.** Eine Serie hängt sechs Minuten
Abspann an eine Folge von fünfundvierzig; neunzig Prozent liegen dann
mittendrin, und die Folge gilt erst als gesehen, wenn man ihn sich ganz
ansieht. Die Schwelle herunterzudrehen hiesse, jeden anderen Titel zu
früh abzuhaken. Der erkannte Abspann ist die genauere Antwort auf
dieselbe Frage — er zieht die Schwelle nach vorn, nie nach hinten.

Dazu der Verlauf über dem Aufmacher: er war immer noch zu dunkel. Jetzt
trägt der Schattenwurf der Schrift, was vorher eine Decke über dem
ganzen Bild tat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 21:44:43 +02:00
ScarriffleandClaude Opus 5 8cf2118723 Vorspann und Abspann — erkannt, abgelegt, überspringbar
Beides mit derselben Rechnung, nur in einem anderen Fenster: vorn die
ersten fünfzehn Minuten, hinten die letzten zehn. Was `Tonabgleich`
findet, hängt allein daran, welchen Ausschnitt man ihm gibt — eine
zweite Erkennung für den Abspann wäre dieselbe Suche ein zweites Mal.

Je Staffel verglichen, nicht je Serie: Serien wechseln ihren Vorspann
zwischen Staffeln, und über alle hinweg fände man nichts oder das
Falsche. Gefundenes über fünf Minuten wird verworfen — zwei Folgen, die
dieselbe Datei tragen, teilen vierzig, und darüber stünde sonst ein
Überspringen-Knopf.

Der Lauf geht auf Zuruf, nicht bei jedem Scan: er liest von jeder Folge
ein Stück Ton und dauert Minuten. Der Knopf dafür steht auf der
Serienseite, bei den Verwalterknöpfen.

Die Marken gehen im Folgenvertrag mit — als „intro" und „credits", die
Wörter, die die Apps von Jellyfin her ohnehin kennen. In der App zeichnet
sie der vorhandene Überspringen-Knopf, der bisher nie etwas zu tun
hatte; im Web ist er neu, rechtsbündig über der Zeitleiste.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 21:28:36 +02:00
ScarriffleandClaude Opus 5 acba683c94 Eine Folge weiter, eine zurück — ohne den Spieler zu verlassen
Wer eine Serie schaut, will blättern können. Bisher gab es genau einen
Knopf dafür, und der erschien erst am Ende: „Nächste Folge", wenn der
Abspann durchgelaufen war. Zurück ging gar nicht — nur über die
Serienseite, und die beendet die Wiedergabe.

Jetzt stehen beide Knöpfe in der Bedienleiste, in der App wie im Web,
links und rechts vom Abspielknopf. Nur bei Serien: bei einem Film
antwortet der Server mit 404, bei der letzten Folge mit 204, und beides
heisst hier „kein Knopf". Sie erscheinen also von selbst nur dort, wo
sie etwas tun.

Der Server kannte nur den Weg vorwärts. Jetzt gibt es `/previous`
daneben, und beide Richtungen kommen aus derselben Rechnung — als zwei
Endpunkte abgeschrieben liefen sie auseinander, sobald einer etwas
dazubekommt. Jellyfin hat kein Gegenstück zu „NextUp"; dort entsteht
die vorige Folge aus der Folgenliste der Serie.

Beim Wechsel gilt weiter, was für die Serie an Sprache eingestellt ist.
Ohne das spränge die nächste Folge auf die erste Tonspur der Datei
zurück — bei deutschen Veröffentlichungen also auf Deutsch, mitten in
einer Serie, die man im Original schaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 21:11:09 +02:00
ScarriffleandClaude Opus 5 bcbe5557d7 Der Kern des Vorspann-Abgleichs — ohne Anschluss, aber geprüft
Ein Vorspann ist das, was in jeder Folge einer Staffel gleich klingt.
Sonst ist an einer Folge nichts, woran er sich erkennen liesse: er sieht
aus wie Handlung und klingt wie Handlung, er wiederholt sich nur.

`Tonabgleich` sucht das längste Stück, das zwei Abdruckreihen teilen —
reine Rechnung, ohne Datei und ohne ffmpeg, deshalb mit sieben Prüfungen
belegt. Darunter die wichtigere Richtung: zwei Folgen ohne Gemeinsamkeit
ergeben nichts. Ein nicht gefundener Vorspann kostet einen Knopf, ein
erfundener schneidet dem Zuschauer eine halbe Minute Handlung weg.

Die Abdrücke holt `fpcalc` aus Chromaprint, nicht selbstgeschriebene
Signalverarbeitung. Dasselbe tut Jellyfins Intro Skipper, aus demselben
Grund. Das Programk liegt ab jetzt im Abbild; fehlt es, gibt es eben
keine Marken — sie sind eine Zugabe, kein Teil der Wiedergabe.

Noch ruft das niemand auf. Tabelle, Lauf und Knöpfe kommen als Nächstes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 20:56:37 +02:00
ScarriffleandClaude Opus 5 bfe263d495 Vierundzwanzig Bilder, und der Weg dorthin fehlte sowieso
Zwei Dinge, die zusammengehören.

**Den Bilderdialog gab es nur an der Kachel.** Wer auf der Seite eines
Films stand und sah, dass das Plakat falsch ist, stand genau dort, wo er
nichts dagegen tun konnte — der Weg führte zurück in die Liste und über
das Dreipunktmenü. Jetzt steht „Bearbeiten" in der Knopfreihe der
Detailseite, bei Filmen wie bei Serien, und nur im Kopf: dieselbe Reihe
steht auch über jeder Fassung und jeder Folge.

**Und es waren vierundzwanzig, weil dort vierundzwanzig stand.** Bei
„365 Tage" hat TMDB neunundsechzig Plakate. Dazu ein zweiter, leiserer
Filter: gefragt wurden nur drei Sprachen. Fürs automatische Holen ist
das richtig — dort wird eines genommen, und es soll passen. Wer von Hand
wählt, will sehen, was es gibt; sortiert wird ohnehin nach Sprache, also
steht das Passende weiterhin oben.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 20:49:37 +02:00
ScarriffleandClaude Opus 5 78e347c58d Zwei Zeilen Untertitel, die zweite halb unter dem Bildrand
Gemessen am Bildschirmfoto: zwischen den Zeilen lagen 71 Pixel bei 18
Pixel Texthöhe — fast das Vierfache dessen, was `line-height: 1.25`
ergibt. Und die zweite Zeile war mitten im Buchstaben abgeschnitten.

Beides derselbe Grund. Der bisherige Weg ging über die Norm:
`lineAlign = "end"` macht `line: 90` zur **Unter**kante, und dann steht
auch ein zweizeiliger Untertitel vollständig über dem Rand. Chrome und
Firefox halten sich daran — nachgestellt und abgelichtet. WebKit nicht:
dort ist es die Oberkante, der Kasten wächst nach unten aus dem Bild,
und `line-height` aus `::cue` bleibt ebenfalls wirkungslos.

Jetzt wird dort gar nichts mehr an den Einblendungen verstellt.
Stattdessen rückt der Kasten ab, in den der Browser sie setzt — ein
Element, das WebKit selbst erfunden hat und das es dort also gibt. Eine
Verschiebung des ganzen Kastens kann nichts abschneiden, egal wie viele
Zeilen eine Einblendung hat.

Wer den Kasten nicht kennt — Firefox —, bekommt weiter den Weg über die
Norm. Erkannt wird das daran, ob die Regel im Stilblatt stehen bleibt,
nicht an der Browserkennung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 20:42:16 +02:00
ScarriffleandClaude Opus 5 5a0f2bf07f Eine Prüfung dafür, dass eine Datei auch ein Bild sein darf
Der Lader gab bei jeder `file:`-Adresse `nil` zurück, und nichts hätte
das gemeldet. Drei Zeilen Prüfung: ein PNG auf der Platte kommt an, eine
fehlende Datei nicht, und Text ist kein Bild.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 20:28:14 +02:00
ScarriffleandClaude Opus 5 79d7d04583 Ein Download sah aus wie eine Videodatei, nicht wie ein Film
Vier Dinge, die beim Ausprobieren auffielen.

**Die Plakate blieben grau.** Sie lagen auf der Platte, der Lader wollte
sie aber nicht: er verlangte von jeder Antwort eine HTTPURLResponse, und
eine Datei antwortet nicht so. Jede lokale Adresse kam als `nil` zurück.

**Eine Serie hatte ohnehin nie ein Plakat.** Heruntergeladen wird nie die
Serie, nur ihre Folgen — und deren Bild ist das Szenenbild, quer. Jetzt
kommt das Serienplakat unter dem Serienschlüssel mit und geht mit der
letzten Folge wieder.

**Zwanzig Folgen waren zwanzig Kacheln.** Jetzt steht die Serie einmal
da, darunter wie viele Folgen bereitliegen; welche genau, zeigt ihre
Seite — auch ohne Server, dann aus dem, was auf dem Gerät liegt.

**Das Bild wurde schwarz, sobald jemand auf „Bildfüllend" wechselte.**
Daran war ein eigener ViewModifier schuld, der zwischen
`ignoresSafeArea()` und gar nichts umschaltete. Genau das ist in SwiftUI
ein Zweig: der Baum darunter wurde neu gebaut, die Bildebene mit ihm.
`edges: []` ignoriert nichts und bleibt doch derselbe Modifikator.

Dazu „Als Nächstes": die Reihe begann am Anfang der Serie statt dort, wo
der Benutzer steht. Wer bei Folge 2 war und Folge 1 nie abgehakt hatte,
bekam Folge 1 vorgeschlagen — und das Abhaken half nicht, weil die
Kachel sich nur selbst einen Haken malte, statt zu verschwinden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 20:20:27 +02:00
ScarriffleandClaude Opus 5 8f0568cb6c Ohne Server stand man vor der Tür, mit dem Film in der Tasche
Fiel der Server aus, endete der Start bei einem Fehlerbildschirm mit
zwei Knöpfen: „Erneut versuchen" und „Abmelden". Beide nützen im
Flugzeug nichts — und dahinter lagen die Dateien, die man genau für
diesen Fall heruntergeladen hatte.

Jetzt geht die App trotzdem auf: Token und Konto liegen auf dem Gerät,
die Mediathekenliste auch, und die Startseite kommt neuerdings aus
demselben Speicher. Oben die Downloads, darunter der Stand vom letzten
Mal, ausgegraut, mit einem Satz, der sagt warum. Die Detailseite nimmt
den Titel vom Gerät, wenn der Server schweigt, und der Abspielknopf
bleibt an, weil die Datei ja da ist.

Und was man offline geschaut hat, zählt: Fortschritt, den der Server
nicht annimmt, wird zurückgelegt und nachgereicht, sobald er wieder
antwortet. Dafür sagt `reportProgress` jetzt, ob die Meldung ankam.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 19:41:22 +02:00
ScarriffleandClaude Opus 5 77593105de Heruntergeladenes lag auf dem Gerät und war nirgends zu sehen
Downloads gab es nur im Downloads-Bereich. Wer wissen wollte, was im
Flugzeug läuft, musste zwei Listen vergleichen: die Mediathek und die
Downloads.

Jetzt sind sie eine Reihe auf der Startseite, tragen in jeder Kachel
eine Marke, und in der Mediathek gibt es „Nur Heruntergeladene" — der
Filter fragt den Server gar nicht erst, weil der nicht weiss, was auf
diesem Gerät liegt.

Dabei kam heraus, dass Downloads nie ein Bild mitbrachten: der
Dateiname dafür stand im Modell, gesetzt hat ihn niemand. Neue holen es
mit, alten wird es beim nächsten Start nachgereicht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 19:28:45 +02:00
ScarriffleandClaude Opus 5 fb8ad1c831 Der Stand lag daneben und wurde trotzdem weggeworfen
Der Fortschrittsbalken ist an **einer** Stelle gebaut und wird in jeder
Kachel verwendet — Web wie App. Fehlte er, dann nicht an der Kachel,
sondern weil der Server `State: null` schickte. Drei Listen taten das,
obwohl die Stände in derselben Abfrage danebenlagen:

  /home/suggestions  — „Weil du Ähnliches gesehen hast"
  /home/seasonal     — die saisonale Reihe
  /movies/{id}/similar — „Ähnliche Titel"

Ausgerechnet die erste entsteht aus dem Sehverhalten: ein halb gesehener
Film sah dort aus wie ein unangetasteter, während dieselbe Kachel in der
Mediathek einen Balken trug. `ZuständeZu` gab es längst, es war nur
privat.

**Und „Als Nächstes" lässt sich jetzt räumen.** Das vorhandene Weglegen
reichte nicht dorthin: die Reihe liest `Watched` und `InProgress`, nie
`Dismissed` — und bei einer nie gestarteten Folge ist `InProgress` ohnehin
`false`. Weggelegt wird deshalb die **Serie**, nicht die Folge: beim
nächsten Laden rückte sonst die übernächste nach, und man legte
zwanzigmal weg. Den Zustand dafür gibt es schon, er wurde nur nie
gelesen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 19:13:09 +02:00
ScarriffleandClaude Opus 5 fa8d1a97e2 Vom Aufmacher war vor allem Grau zu sehen
Zwei Beschwerden, zwei Ursachen.

**„Niedrig" war nicht niedrig.** Mit 62 vh war es mittel mit anderem
Namen; die Spanne reichte nur nach oben, weil die fünfte Stufe damals
oben gebraucht wurde. Darunter steht jetzt „Flach" mit 46 vh — für den,
der den Aufmacher als Kopfzeile will und nicht als halbe Seite.

**Der Verlauf fing auf halber Höhe schon mit 55 % Deckung an** und wurde
erst bei 85 % durchsichtig. Von einem starken Bild blieb dadurch vor
allem Grau übrig. Jetzt kurz und steil: unten dunkel genug, dass die
Schrift trägt, und die obere Hälfte frei. Der Text sitzt unten links —
genau dort muss es tragen, und darüber nicht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-12 19:03:45 +02:00
ScarriffleandClaude Opus 5 0a394b9b3b „Wartet" für immer, obwohl der Server längst fertig war
Der Eintrag ging nach einer 202 zurück auf „wartet" und rief danach
`resume`. Das nimmt aber nur auf, was **angehalten oder gescheitert**
ist — ein wartender lief in die Schutzklausel und kam nie wieder heraus.
Im Protokoll packte ffmpeg um, in der App stand „wartet", und dazwischen
lag nichts.

Jetzt wird die Warteschlange abgearbeitet statt ein einzelner Eintrag
aufgenommen; „wartet" steht darin.

Dazu zwei Dinge, um die du gebeten hast:

**Das Protokoll liest sich wie eine Kommandozeile.** Älteste Zeile oben,
neueste unten, die Ansicht steht am Ende. Mitgeschoben wird nur, wenn man
unten steht — wer hochgescrollt hat, liest etwas, und ihn bei jeder neuen
Zeile ans Ende zu reissen wäre, als nähme man ihm die Seite aus der Hand.

**Ein Tipp auf eine Kachel führt auf die Detailseite**, am Telefon wie am
iPad wie am Mac. Nur in „Weiterschauen" spielt er ab: dort steht der
Titel, *weil* man ihn angefangen hat. Vorher war es umgekehrt, mit dem
Argument „wer eine Kachel antippt, weiss schon, was er sehen will". Im
Gebrauch stimmte das nicht — wer nachsehen wollte, wie viele Staffeln
eine Serie hat, bekam den Film. Ein Umweg von einem Schritt ist
ärgerlich; eine Wiedergabe, die man nicht wollte, ist schlimmer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-11 20:56:39 +02:00
ScarriffleandClaude Opus 5 ce5dc66047 Eine 500, die der Benutzer sieht und das Protokoll nicht
Im Spieler stand „der Server hat den Download mit Fehler 500 abgelehnt",
und im Tagesprotokoll war davon nichts zu finden. Der Haken, der
Ausnahmen aufschreibt, fängt nur Ausnahmen; ein Endpunkt, der von sich
aus `Results.Problem(… 500)` zurückgibt, läuft daran vorbei.

Jetzt wird jede Antwort ab 500 vermerkt, mit Verfahren, Weg und Abfrage —
egal woher sie kommt. Dieselbe Lehre wie beim ffmpeg-Fehler: eine
Fehlermeldung, die nur der Benutzer sieht, ist eine Sackgasse.

Dazu, weil es beim Suchen im Weg stand: „Hole Metadaten zu Phineas und
Ferb 4×23 — 1334 von 1347" steht nicht mehr im Protokoll. Ein Auffrischen
schrieb vierzehnhundert solche Zeilen und schob alles andere aus der
Ansicht. Das ist Fortschritt, keine Auskunft; er gehört in die
Fortschrittszeile, wo er auch steht. Was bleibt, sind die Vermerke — sie
erklären, warum etwas so zugeordnet wurde — und die Zusammenfassung am
Ende.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-11 20:41:47 +02:00
ScarriffleandClaude Opus 5 a44d55e71c 163 Byte als Film verbucht, in einer Sekunde heruntergeladen
Muss der Server eine Datei umpacken, antwortet er mit **202** und einem
kurzen Text: noch nicht, komm wieder. Die Prüfung im Download verwarf
alles ausserhalb von 200 bis 299 — und 202 liegt mittendrin. Der
Antworttext lag danach als Film auf dem Gerät.

Jetzt ist 202 ein eigener Fall: der Eintrag geht zurück in die
Warteschlange und fragt alle fünfzehn Sekunden erneut, bis zu fünf
Minuten lang. Es ist nichts schiefgegangen, es ist nur noch nicht fertig
— und im Sekundentakt nachzufragen hiesse, dieselbe Datei hundertmal
anzufangen und wegzuwerfen.

Gezählt wird im Arbeitsspeicher, nicht im Eintrag: nach einem Neustart
beginnt das Zählen von vorn, und das ist richtig — der Server hat
inzwischen vermutlich fertig gepackt.

Dazu, aus derselben Meldung: bei 21∶9 auf einem Telefon reichte das Bild
hinter die Dynamic Island. Im Vollbild bleibt das so — wer es wählt, hat
sich fürs Beschneiden entschieden. Im normalen Modus nicht mehr: dort ist
der Anspruch gerade, dass nichts fehlt, und dann darf auch nichts
verdeckt sein.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-11 20:33:32 +02:00
ScarriffleandClaude Opus 5 c05004f586 Untertitel kamen an, der Ton nicht — sie sahen woanders nach
Die Vorwahl auf der Filmseite legt beides unter der Kennung des Films ab.
Beim Untertitel habe ich das beim Lesen berücksichtigt, beim Ton nicht:
dort stand `item.seriesID`, und die ist bei einem Film nichts. Die
Einstellung wurde gespeichert und nie wieder gelesen.

Jetzt gibt es eine Stelle, die sagt, wo die Vorwahl eines Titels liegt:
bei einer Folge die Serie, bei einem Film er selbst. Beides ist dieselbe
Frage auf der Ebene, die der Benutzer vor sich hatte, als er sie
beantwortet hat.

Dasselbe betraf das Merken einer von Hand gewählten Spur und die Anzeige
im Spurenblatt: bei einem Film merkte sich der Spieler nichts, weil die
Kennung fehlte. Jetzt lesen alle vier Stellen dieselbe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-11 13:58:44 +02:00
ScarriffleandClaude Opus 5 94458ef41c Fünf Knöpfe in einer Reihe wurden auf dem Telefon zu Säulen
In einem `HStack` teilen sich die Knöpfe die Breite. Abspielen, Von vorn,
Herunterladen und zwei Sprachknöpfe passten auf einem Telefon nicht
nebeneinander — heraus kamen Säulen aus einzelnen Buchstaben, senkrecht
untereinander. Lesbar war nichts mehr; angetippt hätte man trotzdem das
Richtige.

`Flusszeile` bricht um, statt zu quetschen: was nicht mehr hinpasst,
kommt in die nächste Zeile. Zwei Zeilen sind kein Mangel, sie sind, was
dort hinpasst — und ein Knopf, der auf schmalen Geräten verschwindet,
wäre eine zweite Oberfläche, die gepflegt werden will.

Kein `ViewThatFits`: das wählt zwischen fertigen Entwürfen, und die
müsste man für jede Zahl von Knöpfen von Hand hinschreiben. Hier wird
gerechnet.

Dazu bleibt die Beschriftung eines Sprachknopfs einzeilig. Umbrochen wird
die Reihe, nicht das Wort darin.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 23:20:57 +02:00
ScarriffleandClaude Opus 5 f85891aba4 Die Sprachwahl gehört neben den Knopf, der sie anwendet
Auf der Filmseite standen „Tonsprache für diesen Titel" und „Untertitel
für diesen Titel" als zwei breite Zeilen unter der Beschreibung — weit
weg von „Abspielen", und mit so viel Platz dazwischen, dass sie wie eine
Einstellung aussahen und nicht wie eine Wahl für diesen Film.

Jetzt stehen sie als „Ton: Deutsch" und „Untertitel: Keine" in der Reihe
mit Abspielen, Von vorn und Herunterladen.

Der Auswahlknopf hat dafür eine zweite Form bekommen statt eines zweiten
Typs: neben „Abspielen" ist kein Platz für eine Zeile mit Spalten, und
Beschriftung plus Wert in einem sagt dasselbe in einem Wort mehr. Auf der
Serienseite bleibt es bei der Zeile — dort stehen sie in einer Liste.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 22:16:12 +02:00
ScarriffleandClaude Opus 5 84612335ec Sprachwahl in der App — bei Serien und bei Filmen
Auf der Serienseite stand ein Menü für den Ton, gefüllt mit zwanzig
Sprachen, von denen die Serie zwei hatte. Für Untertitel gab es keines,
und auf der Filmseite überhaupt nichts.

Jetzt beides an beiden Orten, und zwar nur mit dem, was es wirklich gibt:

Bei einer **Serie** über den neuen Endpunkt — die Schnittmenge über alle
Folgen. Was dadurch wegfällt, steht als Satz darunter, sonst sähe eine
gekürzte Liste aus wie die ganze Wahrheit.

Bei einem **Film** aus den Spuren der Datei. Kein Serverweg nötig: dort
ist die Datei der Titel, und ihre Spuren stehen in der Antwort, die die
Seite ohnehin geholt hat.

Ton und Untertitel teilen sich einen Typ. Sie unterscheiden sich in genau
zwei Punkten — woher der Wert kommt und ob es „Keine" gibt; ein zweiter
Typ wäre dieselbe Datei mit zwei geänderten Zeilen. „Keine" gibt es nur
beim Untertitel: ein Film ohne Tonspur ist kein Wunsch, sondern ein
Fehler.

Die Untertitelsprache liegt je Titel, in einem Topf für Serien und Filme
— eine Filmkennung kollidiert mit keiner Serie, und zwei Wörterbücher für
dieselbe Frage liefen auseinander. Der Spieler liest sie jetzt: vorher
kannte er nur die allgemeine, und eine Serie im Original mit deutschen
Untertiteln liess sich nicht einstellen, ohne sie überall einzuschalten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 21:56:15 +02:00
ScarriffleandClaude Opus 5 95d7eee8c3 Die Staffelwahl klebte am Untertitelknopf
Die Sprachwahl einer Serie steht zwischen dem Kopf und den Staffeln und
hatte als einziger Abschnitt dort keinen Abstand nach unten. Jetzt
denselben wie jeder andere.

Dazu: der Hinweissatz darunter verschwindet, wenn er leer ist. Ein leeres
Feld nimmt sonst Platz für einen Satz, den es nicht gibt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 21:45:33 +02:00
ScarriffleandClaude Opus 5 fc36bb7ddb Eine Serie, eine Sprachwahl — nicht zwanzig
Auf der Serienseite im Web stand bei jeder einzelnen Folge ein Knopf für
Ton und einer für Untertitel. Zwanzig Folgen hiessen zwanzigmal dieselbe
Frage, und am Ende wusste niemand, welche Antwort gilt. „Dieser Anime
läuft auf Japanisch mit deutschen Untertiteln" ist eine Aussage über die
Serie, nicht über Folge 7.

Die Wahl steht jetzt einmal oben bei den Angaben zur Serie und an den
Folgen gar nicht mehr. Beim Film bleibt sie, wo sie war — dort ist die
Datei der Titel.

Angeboten werden nur Sprachen, die in **jeder** Folge vorkommen; was
dadurch wegfällt, steht als Satz darunter. Gemerkt wird die Sprache, nicht
die Spurnummer: die unterscheidet sich von Folge zu Folge, und beim Start
wird sie für diese Datei nachgeschlagen.

Dazu die Staffeln. Sie standen alle untereinander — nach Folge 8 kam
wieder eine Folge 1, und wer zur dritten Staffel wollte, scrollte an
zwanzig Folgen vorbei. Die Überschrift ist jetzt das Menü. Bei einer
einzigen Staffel bleibt es bei der Überschrift: ein Menü, das nur sich
selbst anbietet, ist keine Wahl.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 21:43:17 +02:00
ScarriffleandClaude Opus 5 22be288fc3 Welche Sprachen eine Serie durchgehend führt
Das Menü auf der Serienseite bot zwanzig Sprachen an, von denen die Serie
zwei hatte. Um das zu ändern, muss jemand wissen, welche es wirklich
gibt — und zwar in einer Abfrage: zwanzig Folgen einzeln zu holen wären
zwanzig Rundreisen, und am Ende müsste der Client dieselbe Rechnung
anstellen.

`GET /api/v1/series/{id}/languages` nennt Ton- und Textsprachen als
**Schnittmenge** über alle Folgen. Eine Sprache anzubieten, die es nur in
Staffel 1 gibt, hiesse: eine Einstellung für die Serie, die ab Staffel 2
stillschweigend etwas anderes tut. Was dabei wegfällt, wird gezählt —
damit die Oberfläche es sagen kann, statt es zu verschweigen.

Zwei Dinge, die sonst falsche Ergebnisse gäben:

Gruppiert wird nach dem **Namen**, nicht nach dem Kürzel. Eine gewachsene
Sammlung trägt „ger" und „deu" nebeneinander; nach dem Kürzel gezählt
fiele Deutsch aus der Schnittmenge, obwohl es überall liegt.

Gezählt werden nur Folgen, die eine **Datei** haben. Eine angekündigte
Folge kann keine Sprache beisteuern; sie als fehlend zu zählen liesse das
Menü bei jeder laufenden Serie leer.

Die Rechnung steht in `Flaro.Core`, nicht im Endpunkt: sie hängt an keiner
Datenbank und lässt sich so prüfen, ohne eine Serie anzulegen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 21:38:19 +02:00
ScarriffleandClaude Opus 5 2c51f639be Untertitel vorher wählen, wie den Ton auch
Auf der Detailseite stand „Ton: Deutsch" und liess sich vor dem Start
umstellen — aus gutem Grund: im Spieler umzuschalten heisst, den Strom
neu aufzubauen. Für Untertitel gab es das nicht, obwohl dort dieselbe
Überlegung gilt und die Spuren ohnehin schon dastehen.

Jetzt steht „Untertitel: Keine" daneben. Auch bei nur einer Spur: anders
als beim Ton gibt es hier immer mindestens zwei Möglichkeiten — diese
eine, oder gar keine.

Der Wunsch wird gemerkt wie beim Ton, mit einem dritten Zustand. „Keine"
ist eine Antwort und kein Fehlen einer: wer sie abgewählt hat, will sie
beim nächsten Film auch nicht, während „nie etwas gesagt" offen lässt,
ob eine erzwungene Spur erscheinen darf.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 21:33:35 +02:00
ScarriffleandClaude Opus 5 ab43656f71 Nach Folge 8 kam wieder Folge 1, und nichts sagte warum
Der Server liefert die Folgen einer Serie am Stück. Auf der Seite stand
unter „Staffeln" eine durchgehende Liste, in der nach der achten Folge
wieder eine erste kam — die der zweiten Staffel, aber das stand nirgends.

Jetzt wählt ein Menü die Staffel, dort wo vorher nur „Folgen" stand. Bei
einer einzigen Staffel bleibt es beim Wort: ein Menü mit einem Eintrag
ist keine Wahl.

Kein `Picker`: diese Seite ist eine `ScrollView`, kein `Form`, und dort
hat ein `Picker` kein Aussehen, auf das man sich verlassen kann —
dieselbe Begründung wie beim Sprachmenü darüber.

„Alle auswählen" meint jetzt die gezeigte Staffel. Vorher hätte ein Griff
sechzehn Folgen heruntergeladen statt acht. Beim Wechsel der Staffel
fällt eine bestehende Auswahl weg: stehen zu lassen, was man nicht mehr
sieht, lädt unsichtbare Folgen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 21:27:58 +02:00
ScarriffleandClaude Opus 5 fa31adf3d1 Deutsch gewählt, Englisch gesehen
„Die erste ist die richtige" stand hier, und es stimmte — solange der
Server genau eine Textspur auslieferte, nämlich die bestellte. Seit die
Wiedergabe über einen Strom läuft, stehen alle Spuren in der
Abspielliste, und dann ist die erste schlicht die erste.

Gesucht wird jetzt die Spur, die zur Bestellung passt: erst über das
Sprachkürzel — `ger`, `deu` und `de` meinen dasselbe, dafür gibt es
`LanguageCode` längst —, bei gleicher Sprache über das Merkmal
„erzwungen", und zuletzt über den Namen. Findet sich keine, bleibt es bei
der ersten: bei einem umgerechneten Strom gibt es nur sie, und gar kein
Untertitel wäre schlechter als der eine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 21:13:52 +02:00
ScarriffleandClaude Opus 5 5657cd9e4b Der Sprung ging ins Leere, und die Prüfung dagegen griff nie
Nach vorn ziehen, Regler springt zurück. Im Pausieren nicht — dort wuchs
die Abspielliste weiter und holte die Stelle irgendwann ein.

Der Spieler sollte einen Sprung ausserhalb des Stroms daran erkennen,
dass er hinter dessen Ende liegt. Das Ende stand in `streamEnd`, und das
wird gesetzt, wenn der Player eine Dauer meldet — was er bei einer
wachsenden Liste nie tut. `streamEnd` blieb also nichts, jeder Sprung
galt als innerhalb, AVPlayer bekam ein Ziel ohne Schnipsel und verwarf
es.

Gefragt wird jetzt der Vorrat: so weit, wie Daten da sind, springt der
Spieler selbst; darüber hinaus wird der Strom neu gebaut. Weiss niemand,
wie weit es reicht, wird ebenfalls neu gebaut — ein neuer Strom dauert
ein paar Sekunden, ein Sprung, der nichts tut, ist kaputt.

Entschieden wird vor dem Aufräumen: `seek` verwirft den Vorrat, und
genau an dem hängt die Antwort.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 21:01:35 +02:00
ScarriffleandClaude Opus 5 064f8f61af Eine wachsende Abspielliste hat keine Länge, also kam nie eine
Mein letzter Versuch griff an der falschen Stelle: er verbesserte, was
`durationResolved` einträgt — nur kommt dieses Ereignis bei einem Strom
aus Flaro gar nicht. Die Abspielliste wächst und trägt kein
`EXT-X-ENDLIST`; für AVPlayer ist die Dauer damit unbestimmt.

`duration` blieb also auf nichts, und die Ansicht rechnet dann mit einer
Sekunde (`model.duration ?? .seconds(1)`). Darum stand der Regler bei
1:50:07 am Anschlag, egal was noch kam.

Jetzt wird die Länge gesetzt, sobald der Strom steht — aus der Datei, die
der Spieler ohnehin in der Hand hat. Auf den Player zu warten hiesse, auf
etwas zu warten, das er nicht wissen kann.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 20:50:44 +02:00
ScarriffleandClaude Opus 5 693a6cc867 Cookie heisst Cookie
„Keks", „Keksglas", „Kekse" — eingedeutscht, wo es nichts zu
verdeutschen gibt. Ein Cookie ist ein Cookie; wer danach sucht, sucht
nicht nach Keksen, und wer den Quelltext liest, liest daneben die
Schnittstelle, in der es `HTTPCookieStorage` heisst.

Betrifft Kommentare und Prüfungsnamen, kein Verhalten.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 20:42:29 +02:00
ScarriffleandClaude Opus 5 f789c40594 Der Vorrat holte unangemeldet, und das stand im Protokoll
20:32:40  Umpacken … Vorbereitung 3203 ms
    20:32:40  FlaroToken was challenged
    20:32:52  Umkodieren … 0 ms
    20:32:55  erstes Stück nach 2750 ms

Einmal je Wiedergabe eine abgewiesene Anfrage, gefolgt von zwölf
Sekunden Stille und einer zweiten Bestellung. Die zwölf Sekunden sind
AVPlayer, der auf etwas wartet, das nie kommt.

Der Vorrat, der dem Spieler die Schnipsel voraushält, benutzt eine
flüchtige URLSession — und die bringt ihren eigenen, leeren Keksspeicher
mit. Jede Anfrage von dort ging unangemeldet hinaus. Bei Jellyfin fiel
das nie auf, weil der Schlüssel dort in der Adresse steht; Flaro meldet
über ein Keks an. Und bisher kam der Vorrat bei Flaro nie zum Zug: er
springt nur bei einer Abspielliste an, und die App hat bis gestern eine
fertige Datei abgespielt.

Dass die zweite Bestellung lief, passt dazu: nach dem Fehlschlag gibt der
Vorrat auf, und der Spieler holt unmittelbar vom Server — mit dem Keks,
den er selbst hat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 20:35:37 +02:00
ScarriffleandClaude Opus 5 347ddfea01 Das Protokoll kannte nur, was jemand ausdrücklich hineinschrieb
Start, Ende, ein paar Fehler — mehr stand nie drin. Dabei meldet der
Server längst, was er tut: „Scan gestartet", „Strom angelegt",
„Untertitel aus … gezogen", „Bibliothek ohne Treffer". Das ging alles an
`ILogger` und damit in die Container-Ausgabe, wo es zwischen den
EF-Abfragen untergeht.

Eine Senke hängt das Tagebuch jetzt an die Protokollkette. Nur Flaros
eigene Kategorien — `Microsoft.*` käme mit einer Zeile je Datenbank-
abfrage und machte das Protokoll nach einem Scan unlesbar. Debug und
Trace bleiben draussen, die sind fürs Entwickeln.

Damit fallen die beiden Stellen weg, an denen ich gestern von Hand ins
Tagebuch geschrieben habe; sie kommen jetzt über denselben Weg wie alles
andere. Der Name der Quelle steht davor: „Streamkoordinator: …".

Nebenbei: das Tagebuch wird von Hand gebaut statt aus dem Behälter
geholt. Die Senke braucht es, bevor der Behälter steht, und ein
`BuildServiceProvider()` dafür legte eine zweite Ausgabe an — zwei
Tagebücher mit zwei Schlössern, die sich beim Schreiben ins Gehege
kommen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 20:30:23 +02:00
ScarriffleandClaude Opus 5 19ec17da19 Zwölf Sekunden für eine Hülle um nichts
Die Messung sagt es deutlich:

    20:15:53  Umpacken    — Schlüsselbildsuche 2348 ms, Vorbereitung 2394 ms.
    20:16:05  Umkodieren  — Schlüsselbildsuche 0 ms, Vorbereitung 0 ms.
    20:16:08  erstes Stück nach 2750 ms.

Fünfzehn Sekunden, und zwölf davon liegen zwischen zwei Bestellungen für
denselben Film. Der erste Strom wurde angelegt und dann nie abgeholt —
keine Medienliste, kein Stück, kein ffmpeg-Fehler. Danach gab die App auf
und bestellte neu, diesmal mit Umkodieren, und das lief nach knapp drei
Sekunden.

Dazwischen lag die Hauptliste. Es gibt sie allein wegen der
Untertitelspuren, und bei diesem Film waren die noch gar nicht aus der
Datei gezogen — sie war also leer bis auf einen Verweis auf die
Medienliste. Eine Hülle um nichts, und keine umsonst: ohne `CODECS` muss
ein Spieler sie erst aufmachen, um zu sehen, was darin liegt.

Jetzt gibt es sie nur, wenn wenigstens eine Spur abholbar ist. Sonst
bekommt die App die Medienliste unmittelbar — denselben Weg wie der
Browser, der nie gestolpert ist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 20:20:16 +02:00