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>
This commit is contained in:
co-authored by
Claude Opus 5
parent
57fff63516
commit
51d1db4641
@@ -0,0 +1,122 @@
|
||||
namespace Flaro.Media.Tests;
|
||||
|
||||
/// <summary>Untertitel auf der Zeitachse eines Stroms, der mittendrin anfängt.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// <b>Der Fehler, den diese Prüfung festhält.</b> Die Zeitstempel zählen ab
|
||||
/// Dateianfang, der Strom zählt ab null. Beim Einstieg bei Minute 30 lag
|
||||
/// damit jeder Satz dreissig Minuten in der Zukunft — und weil ein Strom nur
|
||||
/// bis zum Filmende reicht, erschien überhaupt keiner mehr. Gemeldet wurde
|
||||
/// das als „auf keiner Spur kommt Text".
|
||||
/// </remarks>
|
||||
public class UntertitelversatzTests
|
||||
{
|
||||
private const string Probe = """
|
||||
WEBVTT
|
||||
|
||||
1
|
||||
00:00:01.000 --> 00:00:04.000
|
||||
Ganz am Anfang
|
||||
|
||||
2
|
||||
00:00:09.000 --> 00:00:12.000
|
||||
Über den Einstieg hinweg
|
||||
|
||||
3
|
||||
00:00:20.000 --> 00:00:24.000
|
||||
Weit dahinter
|
||||
|
||||
""";
|
||||
|
||||
[Test]
|
||||
public void Ohne_Versatz_bleibt_alles_wie_es_war() =>
|
||||
Assert.That(Untertitelversatz.Verschieben(Probe, 0), Is.EqualTo(Probe));
|
||||
|
||||
[Test]
|
||||
public void Die_Zeiten_rutschen_um_den_Einstieg_nach_vorn()
|
||||
{
|
||||
var heraus = Untertitelversatz.Verschieben(Probe, 10);
|
||||
|
||||
Assert.That(heraus, Does.Contain("00:00:10.000 --> 00:00:14.000"),
|
||||
"Sekunde 20 im Film ist Sekunde 10 in einem Strom, der bei 10 beginnt.");
|
||||
}
|
||||
|
||||
/// <summary>Was schon vorbei war, fällt weg.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// Und zwar samt seinem Text: bliebe der Absatz ohne Zeitzeile stehen,
|
||||
/// hinge er als Fliesstext in der Datei und der Browser verschluckt sich
|
||||
/// daran.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void Was_vor_dem_Einstieg_endet_faellt_weg()
|
||||
{
|
||||
var heraus = Untertitelversatz.Verschieben(Probe, 10);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(heraus, Does.Not.Contain("Ganz am Anfang"));
|
||||
Assert.That(heraus, Does.Not.Contain("00:00:01.000"));
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>Ein Satz, der beim Einstieg schon lief, bleibt stehen.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// Abgeschnitten ist er immer noch lesbar — ihn wegzuwerfen hiesse, beim
|
||||
/// Wiedereinstieg mitten in einem Dialog mit Stille zu beginnen.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void Was_ueber_den_Einstieg_hinwegreicht_faengt_bei_null_an()
|
||||
{
|
||||
var heraus = Untertitelversatz.Verschieben(Probe, 10);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(heraus, Does.Contain("Über den Einstieg hinweg"));
|
||||
Assert.That(heraus, Does.Contain("00:00:00.000 --> 00:00:02.000"));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Der_Kopf_bleibt_stehen() =>
|
||||
Assert.That(Untertitelversatz.Verschieben(Probe, 10), Does.StartWith("WEBVTT"));
|
||||
|
||||
/// <summary>Die kurze Schreibweise ohne Stunden ist erlaubt.</summary>
|
||||
[Test]
|
||||
public void Auch_ohne_Stundenangabe()
|
||||
{
|
||||
var kurz = "WEBVTT\n\n01:05.000 --> 01:09.000\nKurz geschrieben\n";
|
||||
|
||||
Assert.That(Untertitelversatz.Verschieben(kurz, 60),
|
||||
Does.Contain("00:00:05.000 --> 00:00:09.000"));
|
||||
}
|
||||
|
||||
/// <summary>Was hinter der Zeitzeile steht, bleibt dran.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// Dort stehen Platzangaben wie <c>line:90% align:center</c>. Sie
|
||||
/// abzuschneiden hiesse, erzwungene Untertitel mitten ins Bild zu setzen.
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void Die_Platzangaben_bleiben_erhalten()
|
||||
{
|
||||
var mitLage = "WEBVTT\n\n00:00:20.000 --> 00:00:24.000 line:90% align:center\nUnten\n";
|
||||
|
||||
Assert.That(Untertitelversatz.Verschieben(mitLage, 10),
|
||||
Does.Contain("00:00:10.000 --> 00:00:14.000 line:90% align:center"));
|
||||
}
|
||||
|
||||
/// <summary>Eine Spur, die ganz vor dem Einstieg liegt, wird leer — aber gültig.</summary>
|
||||
[Test]
|
||||
public void Eine_leere_Spur_bleibt_lesbares_WebVTT()
|
||||
{
|
||||
var heraus = Untertitelversatz.Verschieben(Probe, 3600);
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(heraus, Does.StartWith("WEBVTT"));
|
||||
Assert.That(heraus, Does.Not.Contain("-->"));
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user