Die Untertitel holen, bevor jemand sie einschaltet
Zwei Minuten „wird geholt", und noch immer kein Text. Die Ablage von vorhin
war richtig und reichte nicht: beim ersten Mal musste immer noch jemand
warten, und zwar der, der gerade einen Film anschaut.
Das Lesen selbst lässt sich nicht beschleunigen. Untertitelpakete liegen
über die ganze Datei verteilt; sie zu finden heisst, alles zu lesen. Bei
vierzig Gigabyte auf einem NAS sind das Minuten, und daran ändert kein
Schalter etwas. Also nicht schneller lesen, sondern früher.
Der Vorrat arbeitet die Mediathek jetzt von sich aus durch: beim Start des
Servers und nach jedem Scan, die zuletzt hinzugekommenen zuerst. Eine Datei
nach der anderen, mit zwei Sekunden Pause dazwischen — das Lesen ist von
der Platte begrenzt, und eine laufende Wiedergabe liest von derselben
Platte und ist wichtiger. Wer einen Film startet, drängelt sich vor: seine
Datei ist als Nächstes dran statt als Dreissigste.
Einmal je Datei, nie wieder: der Name der Ablage trägt den
Änderungszeitpunkt. Eine ersetzte Datei bekommt dadurch von selbst einen
neuen Namen, eine unveränderte wird nie zweimal gelesen.
Gemessen am Prüfserver mit leerer Ablage:
Start, ohne jeden Abruf -> „1 Datei(en) werden im Hintergrund
gelesen", danach „2 von 2 Spur(en)"
Klick auf „Deutsch" -> 153 ms bis zum Text, 10 Einblendungen,
die erste bei 0 bis 3 s
Landet jemand trotzdem im Wartefall, gibt der Spieler nicht mehr nach zwei
Minuten auf, sondern fragt zehn Minuten lang nach — und sagt dazu, dass es
einmalig ist.
Die Auswahl der Textspuren stand zweimal im Quelltext und steht jetzt
einmal: im Vorrat. Zwei Listen, von denen eine das Menü füllt und die
andere bestimmt, was geholt wird, laufen sonst irgendwann auseinander.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c2fd2a86fd
commit
1531163bc1
@@ -53,8 +53,7 @@ public static class StreamEndpoints
|
||||
// warten; der Vorrat ist bis dahin längst gefüllt. Wer sie sofort
|
||||
// einschaltet, wartet so lange wie vorher, bekommt aber eine
|
||||
// Antwort statt eines Fehlers.
|
||||
vorrat.Anstossen(gewuenschte.Id, gewuenschte.Path, gewuenschte.ModifiedAt,
|
||||
await Textspuren(db, id, CancellationToken.None));
|
||||
vorrat.Anstellen(gewuenschte.Id, vordraengeln: true);
|
||||
|
||||
var profil = Profil(anfrage);
|
||||
var hoehe = anfrage.Height is { } gewuenscht
|
||||
@@ -238,13 +237,12 @@ public static class StreamEndpoints
|
||||
if (datei is null || !File.Exists(datei.Path))
|
||||
return Einwand.Fehlt("Diese Datei liegt nicht mehr da.");
|
||||
|
||||
var spuren = await Textspuren(db, id, ct);
|
||||
var spuren = await Untertitelvorrat.TextspurenAsync(db, id, ct);
|
||||
if (!spuren.Contains(spur))
|
||||
return Einwand.Fehlt("Diese Spur enthält keinen Text, sondern Bilder.");
|
||||
|
||||
var (stand, text) = await vorrat.HolenAsync(
|
||||
datei.Id, datei.Path, datei.ModifiedAt, spuren, spur,
|
||||
TimeSpan.FromSeconds(20), ct);
|
||||
datei.Id, datei.ModifiedAt, spur, TimeSpan.FromSeconds(20), ct);
|
||||
|
||||
return stand switch
|
||||
{
|
||||
@@ -308,7 +306,7 @@ public static class StreamEndpoints
|
||||
.Select(s => new SpurAuskunft(s.Index, Benennung(s), s.Language, s.IsDefault))
|
||||
.ToList(),
|
||||
SubtitleStreams: spuren.Where(s => s.Kind == MediaStreamKind.Subtitle)
|
||||
.Where(s => s.Codec is null || !IstBild(s.Codec))
|
||||
.Where(s => s.Codec is null || !Untertitelvorrat.IstBild(s.Codec))
|
||||
.Select(s => new SpurAuskunft(s.Index, Benennung(s), s.Language, s.IsDefault))
|
||||
.ToList());
|
||||
}
|
||||
@@ -360,7 +358,7 @@ public static class StreamEndpoints
|
||||
.Select(s => new SpurAuskunft(s.Index, Benennung(s), s.Language, s.IsDefault))
|
||||
.ToList(),
|
||||
SubtitleStreams: spuren.Where(s => s.Kind == MediaStreamKind.Subtitle)
|
||||
.Where(s => s.Codec is null || !IstBild(s.Codec))
|
||||
.Where(s => s.Codec is null || !Untertitelvorrat.IstBild(s.Codec))
|
||||
.Select(s => new SpurAuskunft(s.Index, Benennung(s), s.Language, s.IsDefault))
|
||||
.ToList());
|
||||
}
|
||||
@@ -372,26 +370,6 @@ public static class StreamEndpoints
|
||||
/// PGS ist auf jedem Blu-ray-Rip die Regel — ein Eintrag im Menü, der zu
|
||||
/// nichts führt, ist schlechter als kein Eintrag.
|
||||
/// </remarks>
|
||||
private static bool IstBild(string codec) =>
|
||||
codec is "hdmv_pgs_subtitle" or "pgssub" or "dvd_subtitle" or "dvdsub" or "xsub";
|
||||
|
||||
/// <summary>Die Spurnummern, aus denen sich Text holen lässt.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// Dieselbe Auswahl, die auch im Menü steht — sonst böte der Spieler eine
|
||||
/// Spur an, die der Vorrat gar nicht erst zieht.
|
||||
/// </remarks>
|
||||
private static async Task<IReadOnlyList<int>> Textspuren(
|
||||
FlaroContext db, Guid dateiId, CancellationToken ct)
|
||||
{
|
||||
var alle = await db.MediaStreams.AsNoTracking()
|
||||
.Where(s => s.MediaFileId == dateiId && s.Kind == MediaStreamKind.Subtitle)
|
||||
.OrderBy(s => s.Index)
|
||||
.Select(s => new { s.Index, s.Codec })
|
||||
.ToListAsync(ct);
|
||||
|
||||
return alle.Where(s => s.Codec is null || !IstBild(s.Codec)).Select(s => s.Index).ToList();
|
||||
}
|
||||
|
||||
/// <summary>Wie eine Spur im Menü heisst.</summary>
|
||||
private static string Benennung(MediaStream spur)
|
||||
|
||||
Reference in New Issue
Block a user