fd79fb402264f540587de63dca583607c44f81e4
11
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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> |
||
|
|
4db2a17e64 |
„Es dauert fünfzehn Sekunden" liess sich nicht beantworten
Zwischen dem Antippen und dem ersten Bild liegen drei Strecken: die Schlüsselbildsuche, der Start von ffmpeg und das Warten auf das erste Stück. Keine davon war irgendwo abzulesen — jede Erklärung wäre Raterei gewesen. Jetzt steht je Wiedergabe eine Zeile im Tagesprotokoll, mit den ersten beiden Zeiten. Dauert das erste Stück länger als zwei Sekunden, kommt eine zweite Zeile dazu. Eine Zeile je Wiedergabe ist kein Lärm; sie ist genau das, wonach man im Protokoll sucht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b88e58d5eb |
Das Gerät war da, die VA-Anzeige dahinter nicht
ffmpeg endete mit 234. No VA display found for device
/dev/dri/renderD128. Device creation failed: -22.
Hier stand `File.Exists("/dev/dri/renderD128")`, und das war keine
Prüfung, sondern eine Vermutung. Auf dem NAS liegt das Gerät
durchgereicht da — eine VA-Anzeige steht nicht dahinter. ffmpeg bricht
dann schon an der globalen Option ab, vor dem ersten Bild, und für den
Zuschauer sieht das aus wie ein kaputter Server: HTTP 500 auf die
Abspielliste, „Die Wiedergabe wurde unterbrochen".
Jetzt wird ffmpeg einmal je Lauf wirklich gefragt: ein Bild aus dem
Nichts, nirgendwohin, mit Frist. Geht die Zeile vor dem ersten Bild nicht
durch, läuft es in Software weiter — langsamer, aber es läuft.
FLARO_HWACCEL=vaapi überspringt die Probe für den, der es ausdrücklich
verlangt.
Dazu, aus derselben Gegend: in der Hauptliste stehen nur Untertitelspuren,
die jetzt sofort abholbar sind. Sie werden beim ersten Bedarf aus der
Datei gezogen, und bei einem Dreistünder dauert das Minuten. Der Browser
verträgt das — er fragt die Spur einzeln an und wartet. AVPlayer bricht
daran die ganze Wiedergabe ab, nicht bloss den Untertitel. Das Füllen
läuft beim Anlegen der Sitzung schon an; beim nächsten Abspielen stehen
sie drin.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
34ade18ed6 |
„Die Einzelheiten stehen im Protokoll von heute" — standen sie nicht
Der Spieler verweist bei einer gescheiterten Wiedergabe aufs Tagesprotokoll. Dort stand nichts: `ILogger` landet in den Container-Ausgaben, und das Tagebuch ist eine eigene Datei, in die nur Scan, Wartung und unbehandelte Ausnahmen schreiben. Der Hinweis war eine Sackgasse — gemessen an einem Protokoll, das einen ganzen Tag Betrieb mit vier Zeilen Start und Ende wiedergab, während eine Wiedergabe mit 500 abgebrochen war. Jetzt geht der ffmpeg-Fehler auch dorthin. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
7df9fa6c01 |
Zwei Dinge in derselben Ecke, und ein Modus, den niemand bestellt hat
Der Gesehen-Haken und die drei Punkte sassen beide oben rechts — auf dem Plakat sah das aus wie ein Fehler. Jetzt hat jede Ecke eine Aufgabe: oben links die Auswahl, oben rechts der Stand, unten links Abspielen, unten rechts das Menü. Der Knopf „Auswählen" ist weg. Gemessen, warum er stören musste: der längere Text „Auswahl beenden" brach die Filterzeile um und schob das Raster um zwanzig Bildpunkte nach unten. Und grundsätzlicher ist ein Modus ein Zustand, den man kennen muss, bevor man etwas tun kann. Jetzt trägt jede Kachel oben links ein Kästchen, das beim Überfahren erscheint — wie die drei Punkte auch. Der erste Haken fängt die Auswahl an, der letzte beendet sie. Der Spieler lässt sich verkleinern. Er rutscht in eine Leiste am unteren Rand und läuft weiter, während man die Mediathek aufräumt; ein Klick darauf holt ihn zurück. Dasselbe Videoelement, nur anders eingerahmt — ein zweiter Spieler unten hiesse, das Video auszuhängen, und dabei hört es auf zu spielen. Das Zahnrad mit acht Strahlen sah aus wie eine Sonne. Jetzt: Wellenform für den Ton, CC-Kasten für die Untertitel, Schieberegler für die Qualität. Alle drei Menüs stehen immer da — vorher verschwanden sie bei nur einer Tonspur oder ohne Untertitel, und wer sie suchte, fand nichts und wusste nicht warum. Dabei gefunden und behoben: die Wiedergabe blieb nach zwanzig Sekunden stehen, obwohl längst der ganze Rest auf der Platte lag. Results.File setzte Last-Modified, der Browser legte die Playlist mit zwei Einträgen ab, und hls.js bekam bei jedem Nachfragen dieselben zwei zurück. Eine wachsende Liste ist das Gegenteil von zwischenspeicherbar. 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> |