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>
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>
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>
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>