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>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6ad4deb634
commit
dc9d1cea85
@@ -152,19 +152,31 @@ public sealed class Streamkoordinator(
|
||||
// Beim Umkodieren entfällt das: dort wird das Bild neu gerechnet und
|
||||
// schneidet auf die Sekunde genau. Dann vorzurunden hiesse, ohne Not
|
||||
// ein Stück zurückzuspringen.
|
||||
// **Gesprungen wird auf den Wunsch, gemeldet wird das Schlüsselbild.**
|
||||
//
|
||||
// Beim Kopieren springt ffmpeg ungenau — siehe `HlsArgumente` — und
|
||||
// landet damit auf dem Schlüsselbild vor dem Wunsch. Bild und Ton
|
||||
// fangen dort gemeinsam an; das ist die Zusage, und sie hängt an
|
||||
// keiner Rechnung hier.
|
||||
//
|
||||
// Wo genau das war, sagt die Suche. Sie ist dafür da, dem Spieler
|
||||
// eine ehrliche Uhr zu geben — nicht dafür, die Ausrichtung
|
||||
// herzustellen. Vergreift sie sich, geht die Uhr falsch; Bild und Ton
|
||||
// bleiben zusammen. Umgekehrt wäre es ein schlechter Tausch: einen
|
||||
// Sprungpunkt auf die Millisekunde zu treffen, ist zu viel verlangt.
|
||||
var gewuenscht = Math.Max(0, ab);
|
||||
var anfang = plan.BildKopieren
|
||||
var gemeldet = plan.BildKopieren
|
||||
? await schluesselbilder.DavorAsync(datei.Path, gewuenscht, ct)
|
||||
: gewuenscht;
|
||||
|
||||
var anfrage = new Stromanfrage(
|
||||
datei.Path, ordner, gelesen, plan, tonspur, anfang, Hardware(), stufe, tonversatz);
|
||||
datei.Path, ordner, gelesen, plan, tonspur, gewuenscht, Hardware(), stufe, tonversatz);
|
||||
|
||||
// **Die tatsächlich benutzte Spur, nicht die gewünschte.** Sonst
|
||||
// stünde im Menü bei keiner ein Haken, obwohl eine davon läuft — und
|
||||
// bei einer Spur, die es nicht mehr gibt, bei der falschen.
|
||||
var sitzung = new Stromsitzung(
|
||||
kennung, dateiId, benutzer, ordner, anfang,
|
||||
kennung, dateiId, benutzer, ordner, gemeldet,
|
||||
plan.Hoehe, HlsArgumente.Tonspur(gelesen, tonspur)?.Index, plan.Art, clock.GetUtcNow());
|
||||
|
||||
var prozess = Starten(anfrage, sitzung);
|
||||
|
||||
@@ -106,8 +106,28 @@ public static class HlsArgumente
|
||||
|
||||
if (anfrage.Ab > 0)
|
||||
{
|
||||
// **Beim Kopieren wird ungenau gesprungen, und das mit Absicht.**
|
||||
//
|
||||
// Genau gesprungen schneidet ffmpeg den Ton auf die Sekunde, das
|
||||
// kopierte Bild aber nicht — es kann erst beim Schlüsselbild davor
|
||||
// anfangen. Dazwischen liegt Bild ohne Ton, und jeder Spieler darf
|
||||
// diese Lücke deuten, wie er will; hls.js schiebt den Ton nach
|
||||
// vorn. Gemessen an einer Datei mit Schlüsselbildern alle fünf
|
||||
// Sekunden: bei einem Sprung auf 17 begann der Ton erst bei 1,96,
|
||||
// bei 15,014 sogar erst bei 4,98.
|
||||
//
|
||||
// `-noaccurate_seek` lässt auch den Ton beim Schlüsselbild
|
||||
// anfangen. Dieselben Sprünge, gemessen: 0,004 und 0,015 — und
|
||||
// zwar bei *jedem* Wert, nicht nur bei gut getroffenen. Das ist
|
||||
// der Unterschied zum Runden auf das Schlüsselbild: das muss auf
|
||||
// die Millisekunde stimmen, sonst wird es schlimmer als vorher.
|
||||
//
|
||||
// Beim Umkodieren nicht: dort wird das Bild neu gerechnet und
|
||||
// schneidet ohnehin genau.
|
||||
if (anfrage.Plan.BildKopieren) argumente.Add("-noaccurate_seek");
|
||||
|
||||
argumente.Add("-ss");
|
||||
argumente.Add(anfrage.Ab.ToString("0.###", CultureInfo.InvariantCulture));
|
||||
argumente.Add(Sekunden(anfrage.Ab));
|
||||
}
|
||||
|
||||
argumente.Add("-i");
|
||||
@@ -122,11 +142,12 @@ public static class HlsArgumente
|
||||
if (zweiteEingabe)
|
||||
{
|
||||
argumente.Add("-itsoffset");
|
||||
argumente.Add(anfrage.Tonversatz.ToString("0.###", CultureInfo.InvariantCulture));
|
||||
argumente.Add(Sekunden(anfrage.Tonversatz));
|
||||
if (anfrage.Ab > 0)
|
||||
{
|
||||
if (anfrage.Plan.BildKopieren) argumente.Add("-noaccurate_seek");
|
||||
argumente.Add("-ss");
|
||||
argumente.Add(anfrage.Ab.ToString("0.###", CultureInfo.InvariantCulture));
|
||||
argumente.Add(Sekunden(anfrage.Ab));
|
||||
}
|
||||
|
||||
argumente.Add("-i");
|
||||
@@ -196,6 +217,18 @@ public static class HlsArgumente
|
||||
/// Haken, obwohl eine davon lief.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <summary>Eine Sekundenangabe für ffmpeg — mit Punkt und voller Genauigkeit.</summary>
|
||||
///
|
||||
/// <remarks>
|
||||
/// <b>Sechs Nachkommastellen, nicht drei.</b> Auf drei gerundet kann ein
|
||||
/// Sprungpunkt um eine Millisekunde zu klein werden, und eine Millisekunde
|
||||
/// entscheidet, ob ffmpeg das gemeinte Schlüsselbild erwischt oder das
|
||||
/// davor. Gemessen: bei 15,015 begann der Ton nach 0,004 s, bei 15,014
|
||||
/// nach 4,98 s.
|
||||
/// </remarks>
|
||||
private static string Sekunden(double wert) =>
|
||||
wert.ToString("0.######", CultureInfo.InvariantCulture);
|
||||
|
||||
public static ProbedStream? Tonspur(IReadOnlyList<ProbedStream> spuren, int? gewuenscht)
|
||||
{
|
||||
var alle = spuren.Where(s => s.Kind == MediaStreamKind.Audio).ToList();
|
||||
|
||||
Reference in New Issue
Block a user