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>
This commit is contained in:
co-authored by
Claude Opus 5
parent
557708b769
commit
4853200d5c
@@ -430,6 +430,47 @@ public sealed record BulkWatchedResponse(int Changed, IReadOnlyList<Guid> Unknow
|
||||
|
||||
/// <summary>Welche Titel neu geholt werden sollen — leer heisst: alle.</summary>
|
||||
public sealed record RefreshRequest(IReadOnlyList<Guid>? Ids);
|
||||
|
||||
/// <summary>Was ein Spieler kann und was er sehen will.</summary>
|
||||
///
|
||||
/// <param name="Containers">Schachteln, die das Gerät öffnet — „mp4", „webm".</param>
|
||||
/// <param name="Height">
|
||||
/// Die gewünschte Stufe: 1080, 720 oder 480. <c>null</c> heisst Originalauflösung.
|
||||
/// </param>
|
||||
/// <param name="AudioStream">
|
||||
/// Welche Tonspur — die Nummer aus der Datei. <c>null</c> nimmt die erste.
|
||||
/// </param>
|
||||
/// <param name="StartSeconds">Ab welcher Sekunde des Films.</param>
|
||||
///
|
||||
/// <remarks>
|
||||
/// <b>Das Gerät sagt, was es kann, statt dass der Server es rät.</b> Vorher
|
||||
/// bekam jeder Browser Apples Profil — und mit ihm HEVC, AC3 und EAC3, von
|
||||
/// denen er keines öffnen kann.
|
||||
/// </remarks>
|
||||
public sealed record StreamRequest(
|
||||
IReadOnlyList<string>? Containers,
|
||||
IReadOnlyList<string>? VideoCodecs,
|
||||
IReadOnlyList<string>? AudioCodecs,
|
||||
int? Height = null,
|
||||
int? AudioStream = null,
|
||||
double? StartSeconds = null);
|
||||
|
||||
/// <summary>Eine wählbare Spur, so wie sie im Menü steht.</summary>
|
||||
public sealed record SpurAuskunft(int Index, string Label, string? Language, bool IsDefault);
|
||||
|
||||
/// <param name="StartSeconds">
|
||||
/// Ab welcher Sekunde des Films dieser Strom beginnt. <b>Der Spieler zählt ab
|
||||
/// null</b> — ohne diesen Wert ginge jeder gemeldete Stand um den Vorlauf daneben.
|
||||
/// </param>
|
||||
public sealed record StreamResponse(
|
||||
Guid SessionId,
|
||||
string Url,
|
||||
string Method,
|
||||
double StartSeconds,
|
||||
int? Height,
|
||||
int? AudioStream,
|
||||
IReadOnlyList<SpurAuskunft> AudioStreams,
|
||||
IReadOnlyList<SpurAuskunft> SubtitleStreams);
|
||||
public sealed record RatingRequest(int? Rating);
|
||||
|
||||
/// <summary>Was ein Benutzer mit einem Titel zu tun hatte.</summary>
|
||||
|
||||
Reference in New Issue
Block a user