Commit Graph
6 Commits
Author SHA1 Message Date
ScarriffleandClaude Opus 5 dc9d1cea85 Meine Rundung war eine Klinge, und ich bin hineingelaufen
Du hast recht, und zwar doppelt.

**Der Versatz stand im falschen Menü.** „Später (+100 ms)" unter den
Tonspuren liest sich wie der Name einer Spur. Jetzt hat er einen eigenen
Knopf in der Leiste, mit eigenem Zeichen und festen Stufen von „Ton 1 s
früher" bis „Ton 1 s später", dazwischen „Ohne Versatz" — mit Haken, wie
bei der Qualität. Im Tonmenü stehen wieder nur Sprachen.

**Und das Schlimmere: die Rundung aufs Schlüsselbild hat es verschlechtert.**
Sie musste auf die Millisekunde stimmen, sonst nimmt ffmpeg das
Schlüsselbild davor. Gemessen an einer Datei mit Schlüsselbildern alle
fünf Sekunden:

    -ss 15.015  →  Bild ab 0,000 | Ton ab 0,004
    -ss 15.014  →  Bild ab 0,000 | Ton ab 4,983

Eine Millisekunde. Und die Zeile, die den Wert an ffmpeg gibt, rundete auf
drei Nachkommastellen — bei 23,976 Bildern je Sekunde liegen
Schlüsselbilder auf Werten wie 3,336667, und die überleben das nicht
zuverlässig. Damit konnte jede Fortsetzung schlechter werden als vorher.
Das war mein Fehler, eingebaut in E8GSRE.

**Der richtige Hebel ist `-noaccurate_seek`**, und er braucht gar keine
Genauigkeit. Damit schneidet ffmpeg auch den Ton nicht auf die Sekunde,
sondern lässt ihn beim selben Schlüsselbild anfangen wie das kopierte
Bild. Gemessen, dieselbe Datei, fünf verschiedene Sprungwerte quer durch
die Bildgruppe:

    15,014 → 0,015 | 17 → 0,004 | 19,9 → 0,004 | 12,5 → 0,015 | 3,2 → 0,011

Statt bis zu fünf Sekunden also überall unter zwanzig Millisekunden, und
zwar ohne dass irgendein Wert getroffen werden muss. Fünf Testfälle quer
durch die Bildgruppe halten das jetzt fest; vorher prüfte der Sprungtest
nur, ob überhaupt Segmente entstehen.

Die Schlüsselbildsuche bleibt — aber nur noch, um dem Spieler eine
ehrliche Uhr zu geben. Vergreift sie sich, geht die Uhr falsch; Bild und
Ton bleiben zusammen. Vorher hing die Ausrichtung daran, und das war der
schlechte Tausch.

Und die Sekundenangaben gehen jetzt mit sechs Nachkommastellen hinaus
statt mit drei.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-07 20:24:21 +02:00
ScarriffleandClaude Opus 5 cf272f20aa Ton und Bild: ein Versatz zum Einstellen, und zwei gemessene Fehler weniger
Du meldest Ton, der drei, vier Sekunden neben dem Bild liegt.
**Nachstellen konnte ich es nicht** — und das sage ich lieber, als eine
Vermutung als Befund zu verkaufen.

Gemessen habe ich alle vier Wege, jeweils mit ffprobe am Ergebnis, erster
Zeitstempel je Spur:

| Weg | Bild ab | Ton ab |
|---|---|---|
| Umpacken, ab 0 | 0,021 | 0,000 |
| Umpacken, ab 12 | 0,000 | 1,979 |
| Umkodieren, ab 0 | 0,021 | 0,000 |
| Umkodieren, ab 12 | 0,021 | 0,000 |

Alle vier sind **zueinander richtig**. Auch eine Quelle mit einem echten
Loch in der Tonspur blieb ausgerichtet. Die naheliegende Erklärung — `-ss`
vor `-i` mit kopiertem Bild und neu gerechnetem Ton — ist damit widerlegt.

**Zwei echte Fehler hat dieselbe Messung aber gefunden**, und beide sehen
aus wie „um Sekunden daneben":

Zeile zwei der Tabelle. Beim Umpacken fängt das Bild beim Schlüsselbild
*vor* dem Sprung an, der Ton genau beim Sprung — bei Sekunde 12 also zwei
Sekunden Bild **ohne Ton** am Anfang. Zueinander stimmen beide, aber jeder
Spieler darf diese Lücke deuten, wie er will. Und der Server meldete dem
Spieler „beginnt bei 12", obwohl er bei 10 beginnt: die Uhr, die
Zeitleiste und der gespeicherte Stand lagen um diesen Unterschied daneben.

Beides geht weg, indem der Sprung **auf das Schlüsselbild gerundet** wird
und derselbe Wert zurückgemeldet wird. Dann fangen Bild und Ton zusammen
an, es gibt keine Stille davor, und die Uhr stimmt. Beim Umkodieren
entfällt das Runden — dort schneidet das neu gerechnete Bild genau.

**Und: ffmpeg durfte bisher nichts sagen.** `-loglevel error` versteckt
genau die Meldungen, die einen Tonversatz ankündigen, und der
Fehlerkanal wurde bei Rückgabewert 0 weggeworfen. Jetzt steht er auf
`warning`, und Warnungen landen auch bei einem geglückten Lauf im
Protokoll. Wenn es bei dir wieder auftritt, steht diesmal etwas da.

**Der Versatz zum Einstellen** sitzt im Tonmenü des Spielers: „Später"
und „Früher" in Hundertmillisekundenschritten, bis ±5 s, dazu
„Zurücksetzen". Gemerkt wird er **je Datei in diesem Browser** — ein
Versatz ist meist eine Eigenschaft der Datei, kann aber auch an der
Anlage liegen, und über Bluetooth stimmt etwas anderes als am Fernseher.

Verschoben wird serverseitig: die Datei wird ein zweites Mal mit
`-itsoffset` geöffnet und von dort nur der Ton genommen. Mit einer
Eingabe verschöbe sich beides gemeinsam. Der Preis: der Strom startet neu,
und eine durchgereichte Datei muss dafür umgepackt werden — ohne ffmpeg
lässt sich nichts verschieben.

Zwei neue Läufe halten das fest: dass Bild und Ton zusammen anfangen, und
dass ein halbe-Sekunde-Versatz den Ton um eine halbe Sekunde verschiebt
und das Bild gar nicht. Der Sprungtest daneben lief bisher genau durch
diesen Fall und sah nur nach, ob überhaupt Segmente entstehen.

Ein Test musste umgeschrieben werden: er stand auf „Einstiegspunkt ist
genau 2" und hielt damit die falsche Meldung fest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-07 19:37:21 +02:00
ScarriffleandClaude Opus 5 9c2e2b5f47 „Kenne ich" heisst nicht „kann ich diese Datei"
Der Spieler schickte sein Profil aus `canPlayType` — und das ist eine
Auskunft des `<video>`-Elements. Ein Strom läuft aber nicht durch das
Element, sondern durch den MSE-Puffer, und die beiden sind sich nicht
einig.

Gemessen in Chromium:

| | canPlayType | MediaSource.isTypeSupported |
|---|---|---|
| `audio/flac` | probably | **false** |
| `audio/mp4; codecs="mp3"` | probably | **false** |

Der Server glaubte dem Profil, packte die Datei pflichtschuldig um und
liess die Spur unberührt — und der Browser stand vor etwas, das er nach
eigener Auskunft können müsste. Heraus kam „Dieser Browser kann die
Spuren dieser Datei nicht öffnen".

Jetzt zählt ein Codec nur, wenn **beide** Auskünfte ihn bestätigen; welcher
der beiden Wege es wird, entscheidet der Server erst danach. Und geprüft
wird jeder Typ in der Form, in der er wirklich ankommt — `audio/mp4` und
nicht `audio/flac`: genau dieser Unterschied entschied bei FLAC zwischen
„geht" und „geht nicht". Gemessen: MP3 fällt dadurch aus dem Profil, der
Server rechnet es um, statt es durchzureichen.

**Und wenn doch etwas durchrutscht, wird gerechnet statt gemeldet.**
Scheitert die Wiedergabe mit einem Codec- oder Dekodierfehler, baut der
Spieler den Strom genau einmal neu auf — mit `transcode: true`, an
derselben Stelle. Der Satz „über das Zahnrad lässt sich eine Fassung
wählen, die er versteht" ist weg: wer das liest, weiss weder welche, noch
warum der Server sie nicht gleich gegeben hat.

Lief schon ein gerechneter Strom, unterbleibt der zweite Versuch — dann
liegt es nicht am Codec, und dreissig Sekunden Warten auf dasselbe sind
keine Hilfe.

**Nicht geprüft:** dass der Rückfall im Betrieb auslöst. Jede Datei im
Prüfbestand spielt; ein echtes Scheitern liess sich hier nicht
herbeiführen. Gemessen ist der Serverteil (`remux` wird zu `transcode`)
und das neue Profil.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-06 17:44:11 +02:00
ScarriffleandClaude Opus 5 9622da0284 Eine Sekunde ist kein Anfang
Drei Zahlen standen als Konstante im Quelltext und bestimmten, wie sich
der Server anfühlt. Jetzt stehen sie in der Verwaltung, unter
„Wiedergabe".

**Weiterschauen ab.** Gemessen: `BelongsInContinueWatching` verlangte nur
`Position.Ticks > 0` — ein Tick genügte. Wer im Aufmacher eine Sekunde
hineinschaute, fand den Titel danach in „Fortsetzen". Jetzt gibt es eine
Untergrenze, voreingestellt auf 1½ Minuten.

Was sich dabei **nicht** ändert: die Stelle wird weiter gemerkt. Das ist
der Unterschied zu Jellyfin, um dessentwillen es diesen Server gibt — die
Schwelle entscheidet, ob der Titel in der Reihe steht, nicht ob man ihn
wiederfindet. Nachgemessen: nach dem Umstellen ist „Heat" aus der Reihe
verschwunden und steht weiterhin bei Sekunde 1.

**Gesehen ab.** War 90 % als `const`, ist jetzt 85/90/95.

**Umkodieren.** `-preset veryfast -crf 21` und VAAPI `-qp 23` waren fest
verdrahtet, ohne Einstellung und ohne Umgebungsvariable. Drei Stufen:
Qualität (medium/19, qp 21), Ausgewogen (wie bisher), Tempo
(ultrafast/23, qp 26). Mit dem Warnsatz daneben, und der ist ernst
gemeint: was in Echtzeit laufen muss, darf nicht langsamer rechnen als es
abspielt.

**Und das Vorhandene wird neu bewertet.** `InProgress` ist eine
gespeicherte Spalte — die Bruchrechnung lässt sich nicht nach SQL
übersetzen. Eine neue Schwelle wirkte sonst nur auf künftige Meldungen.
Der Endpunkt läuft deshalb einmal in Stapeln durch und meldet zurück, wie
viele Zeilen das umgeworfen hat: „Übernommen — 2 Einträge wurden neu
bewertet." Ohne diesen Satz änderte sich die Startseite scheinbar von
selbst.

`ProgressRule` bleibt ein reiner Typ: die Regeln kommen als Wert herein.
Nebenbei zieht der doppelte `zeile()`-Bauer nach `teile.ts` — er stand
zweimal wortgleich da.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-06 16:52:53 +02:00
ScarriffleandClaude Opus 5 4853200d5c Er packte um, was gar nicht am Umpacken lag
Der Browser bekam stillschweigend Apples Geräteprofil — und mit ihm HEVC, AC3
und EAC3, von denen er keines öffnet. Der Server packte die Datei
pflichtschuldig nach MP4 um, liess Bild und Ton dabei unberührt, und heraus
kam eine tadellose Datei, mit der Chrome nichts anfangen konnte. Umpacken
fasst das Bild nun einmal nicht an.

Jetzt sagt das Gerät selbst, was es kann, und es gibt einen zweiten Weg neben
der fertigen Datei: HLS, das nach Sekunden anfängt statt nach Minuten.
Dasselbe Rohr erledigt beides — mkv nach fMP4 mit „-c:v copy", 4K nach 480p
mit libx264 — und eine MP4, die der Browser ohnehin öffnet, geht ganz ohne
ffmpeg hinaus.

Dazu eine eigene Steuerleiste: Tonspur und Untertitel während der Wiedergabe
umschaltbar, vier Auflösungsstufen, Tastenkürzel, und bei einem Fehler ein
deutscher Satz statt eines schwarzen Bildes.

Gemessen statt vermutet: Chromium antwortet auf canPlayType für HLS mit
"maybe" und kann es dann doch nicht — deshalb entscheidet Hls.isSupported().
hls.js wiegt 372 KB und wird erst beim Abspielen geholt; die Oberfläche
bleibt bei 109.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-05 18:52:27 +02:00
ScarriffleandClaude Opus 5 a7cf6c5def Halo heisst ab hier Flaro — die Marke stand im Weg
Der Upload zu App Store Connect scheiterte am Namen. „Halo" ist eine
eingetragene Marke von Microsoft; im App Store heisst zwar keine App exakt
so, aber reservierte und markenrechtlich belegte Namen tauchen in keiner
Suche auf. Der einzige verlässliche Test war die Eingabe dort, und die ging
daneben.

**Der Name wurde diesmal vorher geprüft.** Zwanzig Kandidaten gegen den
deutschen und amerikanischen App Store, auf exakte Treffer und auf ähnliche
Namen. „Kavo" wäre dieselbe Wand gewesen — exakt belegt in beiden Stores, in
Deutschland von KaVo Dental GmbH. „Flare" ist mit 42 ähnlichen Apps je Store
der am dichtesten besetzte Name der ganzen Runde. **Flaro** ist in beiden
frei und liest sich als eigenes Wort, nicht als Flare mit Tippfehler.

Das bleibt eine Store-Suche und keine Markenrecherche — reservierte Namen
ohne veröffentlichte App sieht sie nicht. Aber es ist mehr Prüfung, als beim
letzten Mal stattfand.

---

2160 Textvorkommen in 273 Dateien, 49 Pfade. Betroffen ist diesmal auch der
Server: `Flaro.Api`, `Flaro.Core`, `Flaro.Data`, `Flaro.Media`,
`Flaro.Metadata`, `FlaroContext`, `FlaroPaths`, `flaro.db`, die Variablen
`FLARO_DATA`, `FLARO_CACHE`, `FLARO_TRANSCODE`, `FLARO_WRITE_SIDECARS`, und
das Image.

**Vor dem Ersetzen geprüft**, ob „halo" irgendwo als Teil eines anderen
Wortes steckt — und ob es im TMDB-Token vorkommt. Tat es nicht; ein blindes
Ersetzen hätte den sonst zerlegt.

`docs/superpowers/specs/` bleibt wie beim letzten Mal unangetastet: datierte
Entwurfsdokumente sind ein Protokoll getroffener Entscheidungen. Das
Server-Dokument hat stattdessen einen Nachtrag bekommen, damit es niemanden
in die Irre führt.

**Die Bundle-ID wandert mit**, zum zweiten Mal an einem Tag:
`com.scarriffleservices.flaro`. Wer die vorige Fassung installiert hat, hat
jetzt zwei Karteileichen auf dem Gerät — beide löschen, dann ist Ruhe.

308 Server-Tests grün, 368 im Swift-Paket, null Warnungen. iOS und tvOS
bauen, das Image baut, und ein frischer Container läuft durch Einrichtung
und Anmeldung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-03 19:38:27 +02:00