c13d1e78d2f8e935379a00dd2786b2b174016369
10
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c4af182d31 |
Der Kratzplatz räumt sich auf
39,1 GB in FLARO_TRANSCODE, und das war kein Normalzustand, sondern ein
Leck: für jede Mitnahme baut der Server eine MP4 in Quellgrösse und löschte
sie nie. Die einzige Löschung, die es gab, räumte ältere Fassungen
derselben Datei weg. Stromordner verschwanden nur beim geordneten
Herunterfahren, Untertitel gar nicht.
**Zuerst: fertig heisst fertig.** ffmpeg schrieb direkt auf den Endnamen.
Nach einem harten Abbruch lag dort eine abgeschnittene Datei, `IsReady`
meldete „fertig", und sie ging so hinaus — und ein Aufräumer konnte
vollständig und abgeschnitten nicht unterscheiden. Gebaut wird jetzt unter
`.teil`, umbenannt erst nach Erfolg. Dabei muss das Format ausdrücklich
gesetzt werden: ffmpeg wählt den Muxer an der Endung und antwortet auf
`.teil` mit „Unable to choose an output format". Das hätte jedes Umpacken
zerlegt; die Prüfung hat es gefunden, bevor es jemand zu spüren bekam.
**Zwei Stufen für die Pakete.** Verwaiste gehen bedingungslos: unleserlicher
Name, fremde Bauart, kein Eintrag in der Mediathek, oder der Zeitstempel im
Namen passt nicht mehr. Der Rest fällt unter Obergrenze (20 GB) und Alter
(7 Tage), Ältestes zuerst.
Beides, und nicht eines: ein Alter allein löst den Fall nicht, denn die 39
GB waren gültige, aktuelle Dateien, jede für sich berechtigt. Eine
Obergrenze allein ist zu grob — ein Topf knapp darunter, in dem seit Wochen
nichts gebraucht wurde, besetzt ein Volume, das anderes braucht.
„Zuletzt gebraucht" ist die Änderungszeit der Paketdatei selbst, bei jeder
Auslieferung neu gestempelt. Die Zugriffszeit wäre das Naheliegende, nur
führt sie nicht jedes Dateisystem — mit `noatime` steht sie still, und der
Aufräumer hielte alles für uralt.
Ein laufender Download wird nie gelöscht: ein Benutzungszähler hält die
Datei fest, solange die Antwort läuft, dazu eine Schonfrist von 30 Minuten.
Der Zähler ist auch unter Linux nötig — der laufende Strom überlebt ein
Entfernen, die Fortsetzung einer Bereichsanfrage nicht, und der Client finge
von vorn an.
**Stromordner** werden beim Start bedingungslos geleert — nach einem Start
gibt es keine einzige Sitzung, also ist jeder Ordner verwaist. Im Betrieb
nur die ohne passende Sitzung, deren Änderungszeit älter ist als die
Geduld; das fängt auch den Fall, dass `Abraeumen` an einem IOException
scheitert und der Ordner für immer liegenbleibt.
**Untertitel** nur, wenn sie verwaist sind. Keine Obergrenze: eine .vtt ist
Kilobytes, und eine gültige wird wieder gebraucht — sie nach Platz zu
löschen hiesse, Minuten Lesearbeit gegen Megabytes zu tauschen. Eine leere
bleibt ausdrücklich liegen: sie ist das Ergebnis „diese Spur hat keinen
Text", und wer sie wegräumt, lässt bei jedem Start eine vierzig Gigabyte
grosse Datei neu durchlesen.
**Vier Anlässe, kein Dienst.** Start, vor jedem Umpacken, nach einem Scan,
auf Knopfdruck — wie alles Wiederkehrende in diesem Server. Einer zur Zeit;
wer nicht hineinkommt, geht weiter.
Gemessen am laufenden Server mit Attrappen:
vorher packages 17408 KB (4), untertitel 5 KB (3), 1 Stromordner
nachher 14 MB freigegeben, 4 Dateien
gültiges Paket blieb, verwaistes/veraltetes/Teilstück weg,
verwaiste .vtt weg, gültige blieben, Stromordner weg
Obergrenze 1 MB, Datei in der Schonfrist -> bleibt
Obergrenze 1 MB, Schonfrist vorbei -> 3072 KB freigegeben
In der Übersicht steht die Belegung je Unterordner mit Dateizahl und
daneben „Jetzt aufräumen"; die drei Zahlen stehen unter Wiedergabe, wo
Transcoder-Stufe und Schwellen schon stehen — der Kratzplatz ist, was die
Wiedergabe hinterlässt.
714 Tests grün, davon 36 neue.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
40f41f0cee |
Zwei Tonspuren sind eine Wahl, kein Chor
„Auf der App höre ich einfach alle Audiospuren gleichzeitig."
MP4 ordnet Spuren derselben Art einer `alternate_group` zu, und ein
Abspieler nimmt daraus genau eine. ffmpeg leitet diese Gruppe aus der
Markierung der Quelle ab — sind dort zwei Tonspuren als Vorgabe markiert,
hält es sie für Verschiedenes und legt sie in getrennte Gruppen. Dann ist
jede für sich eingeschaltet, und man hört beide übereinander. Bei Rips aus
freier Wildbahn ist die doppelte Markierung eher Regel als Ausnahme; in
Matroska stört sie niemanden, in MP4 ist sie der Unterschied zwischen Wahl
und Chor.
Gemessen an einer Quelle mit zwei markierten Tonspuren, am Spurkopf der
fertigen MP4:
vorher Spur 2: an, Gruppe 1
Spur 3: an, Gruppe 2 <- beide laufen
nachher Spur 2: an, Gruppe 1
Spur 3: aus, Gruppe 1 <- eine zur Wahl
Das Umpacken schreibt jetzt genau eine Vorgabe je Spurart: die, die es in
der Quelle schon war, sonst die erste. Auch die Nullen gehören
hingeschrieben — ffmpeg übernähme sonst die Markierung der Quelle für alle
übrigen, und genau die ist ja das Problem. „Erzwungen" wird dabei
ausdrücklich erhalten, weil `-disposition` die ganze Markierung ersetzt
statt sie zu ergänzen.
Untertitel bekommen dieselbe Behandlung. War in der Quelle keiner
vorgesehen, bleibt es dabei — sonst erschienen auf einmal zwei übereinander.
Der Name im Zwischenspeicher trägt jetzt die Bauart mit. Ohne das bliebe
auf einem NAS, das schon umgepackt hat, die fehlerhafte Datei liegen und
würde weiter ausgeliefert, obwohl der Server es längst besser kann.
Geprüft an der echten Datei, am `tkhd` und nicht an der Disposition: was
ein Abspieler tut, hängt an „enabled" und `alternate_group`, und ffprobe
zeigt davon nur einen Teil. Ohne die Korrektur fällt die Prüfung um
(Gruppe 1 gegen 2).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
c2fd2a86fd |
Einmal aus der Datei holen, nicht bei jedem Abruf
„Diese Untertitelspur liess sich nicht laden", und auf der zweiten Spur kam gar nichts. Nicht das Format war schuld und auch nicht das Verschieben, sondern die Zeit: jeder Abruf startete ffmpeg, ffmpeg musste die ganze Datei durchlesen, und nach dreissig Sekunden wurde abgebrochen. An einem Prüffilm von fünfzehn Megabyte fällt das nie auf; bei einem Dreistünder auf einem NAS reicht es nie. Schlimmer wurde es durch meine eigene Korrektur von gestern: seit die Adresse den Einstiegspunkt mitführt (`?ab=`), ändert sie sich bei jedem Sprung — der Browser konnte nichts mehr aus seinem Zwischenspeicher nehmen, und jeder Sprung stiess einen neuen Durchlauf an. Jetzt: - Ein ffmpeg-Durchlauf holt alle Textspuren auf einmal. Das Lesen der Datei ist der teure Teil und wird nicht mehr je Spur bezahlt. - Das Ergebnis bleibt liegen, ungeschoben; das Verschieben ist eine Zeilenersetzung und kostet nichts. Gemessen: erster Abruf 0,42 s, jeder weitere 2 bis 3 ms — und der zweite Sprung in derselben Datei trifft dieselbe Ablage statt eines neuen Durchlaufs. - Angestossen wird beim Start des Stroms, nicht erst beim Einschalten. Wer nach einer halben Stunde Untertitel will, wartet dann gar nicht. - Geschrieben wird unter `.teil` und erst danach umbenannt. Eine abgebrochene Datei am richtigen Namen gälte sonst für immer als fertig. - Die Geduld steigt von 30 Sekunden auf 30 Minuten. Sie ist jetzt eine Obergrenze gegen einen hängenden Prozess, keine Wartezeit mehr. Und der Spieler kann endlich unterscheiden, was los ist. Ein `<track>` meldet jeden Misserfolg gleich — „es gibt sie nicht", „sie enthält keinen Text" und „der Server holt sie gerade" sahen identisch aus. Geholt wird deshalb selbst, mit Token statt Keks (gemessen: ohne Keks kam jeder Abruf mit 401 zurück, ohne dass irgendwo etwas stand), und bei 503 fragt der Spieler nach, statt aufzugeben. Der Text geht als Blob an den `<track>` — dieselbe Anzeige, ein ehrlicher Weg dahin. Dazu eine Unsauberkeit im Verschieben: die Trennzeile eines weggefallenen Blocks blieb stehen. Gemessen am echten Film 52 Leerzeilen vor dem ersten Satz. Geprüft im Spieler, kalter Vorrat, Einstieg bei Sekunde 500: Blob am `<track>`, zehn Einblendungen, die erste bei 0 bis 3 s mit „Deutsch bei 500 s". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
51d1db4641 |
Zwei Uhren, und niemand hatte sie verglichen
Untertitel zeigten auf keiner Spur Text. Der Grund: die Zeitstempel einer WebVTT-Spur zählen ab Dateianfang, der Strom zählt ab null. Wer bei Minute 30 einstieg, bekam jeden Satz dreissig Minuten in die Zukunft geschoben — und weil ein Strom nur bis zum Filmende reicht, erschien überhaupt keiner mehr. Gemessen im Spieler, vorher: „Fortsetzen ab 8:37" geklickt, deutsche Spur gewählt, Standanzeige 8:38 — angezeigt wurde der Satz von Sekunde 0. Versatz 515 Sekunden, also genau der Einstiegspunkt. Nachher, derselbe Weg: Standanzeige 9:02, angezeigt „Deutsch bei 540 s". Verschoben wird auf dem Server, nicht im Browser: dort hiesse es, die Spur selbst zu zerlegen und als VTTCue neu aufzubauen — ein eigener Parser für ein Format, das der Browser schon kann. Hier ist es eine Zeilenersetzung, und sie lässt sich prüfen. Was vor dem Einstieg endet, fällt samt Text weg; was darüber hinwegreicht, fängt bei null an. Zwei Kleinigkeiten lagen daneben und sind mit erledigt: - `srclang` bekam „ger".slice(0, 2) und damit „ge" — kein gültiges Kürzel. Jetzt bleibt das Feld leer, wenn das Kürzel nicht zweistellig ist. - Scheiterte das Laden einer Spur, geschah nichts Sichtbares. Jetzt sagt es der Spieler. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |