Ein doppelter Platzhalter riss jede Serie mit

`log.LogInformation("… {Folgen} … {Folgen}.", a, b, c, d, e)` — sechs
Platzhalter, fünf Argumente. Vorlagen sind positionsbezogen: auch ein
wiederholter Name verbraucht ein weiteres Argument. Der Logger warf eine
Ausnahme, die riss `StaffelMeldenAsync` mit, und die wiederum den ganzen
Serienlauf. Gefunden war dann alles umsonst — „A Knight of the Seven
Kingdoms" und „Alice in Borderland" haben ihre Marken deshalb verloren,
nachdem sie längst berechnet waren.

**CA2017 hatte das gemeldet.** Als Warnung, unter hundert anderen Zeilen,
und ich habe beim Bauen nach „warning CS" gegriffen. Eine neue
`Directory.Build.props` macht genau diese eine Regel zum Fehler — nicht
alle Warnungen, das wäre eine andere Entscheidung. Gegengeprüft: mit der
kaputten Zeile bricht der Bau jetzt ab.

**Und der zweite Fund, aus „Alice im Wunderland".** Die Zeile meldete
„Schwelle 247,6", und das kann bei 0–255 nicht entstehen: die Schwelle
ist Grundton mal 0,55, das wären 450 gewesen. `signalstats` rechnet in
der Skala des Bildformats — bei acht Bit 0–255, bei zehn Bit 0–1023.
Gemessen am selben erzeugten Bild: YAVG 127 gegen YAVG 500. Alle
Schwellen hier sind an acht Bit gemessen; bei einer 10-Bit-Datei bedeutete
dieselbe Zahl ein Viertel.

`format=gray` vor `signalstats` bringt jede Datei auf dieselbe Skala. Es
rechnet dabei auch den Fernsehbereich 16–235 auf 0–255 um — linear, und
die dunklen Werte trifft das am stärksten: der gemessene Abspann liegt
jetzt bei 28 statt bei 40. Der Boden wandert entsprechend von 35 auf 22.

Dazu: die Schlusszeile je Serie trennt Vorspann und Abspann, statt eine
Zahl aus beidem zu machen — „14 Marken" beantwortet nicht, ob die Serie
ihre Vorspänne bekommen hat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-15 14:06:16 +02:00
co-authored by Claude Opus 5
parent 259996c5ad
commit f2752e6c05
5 changed files with 147 additions and 12 deletions
@@ -184,3 +184,82 @@ public class BildabtasterLaufTests
});
}
}
/// <summary>Dieselbe Helligkeit, gleich welche Bittiefe die Datei hat.</summary>
///
/// <remarks>
/// <para>
/// <b>Der Fehler, für den diese Prüfung steht.</b> <c>signalstats</c>
/// rechnet in der Skala des Bildformats: bei acht Bit 0–255, bei zehn Bit
/// 0–1023. Alle Schwellen der Abspannsuche sind an acht Bit gemessen —
/// bei einer 10-Bit-Datei bedeutete dieselbe Zahl ein Viertel.
/// </para>
/// <para>
/// Aufgefallen ist es an einer Protokollzeile: „Schwelle 247,6". Die kann
/// bei 0–255 nicht entstehen, denn sie ist Grundton mal 0,55 — das wären
/// 450 gewesen.
/// </para>
/// </remarks>
public class BildabtasterBittiefeTests
{
private string _ordner = "";
[OneTimeSetUp]
public void Erzeugen() =>
_ordner = Directory.CreateDirectory(Path.Combine(
Path.GetTempPath(), "flaro-bittiefe-" + Guid.CreateVersion7().ToString("N"))).FullName;
[OneTimeTearDown]
public void Aufraeumen()
{
try { Directory.Delete(_ordner, recursive: true); } catch (IOException) { }
}
private string Erzeugen(string pixelformat)
{
var datei = Path.Combine(_ordner, $"{pixelformat}.mp4");
var start = new ProcessStartInfo("ffmpeg")
{
ArgumentList =
{
"-hide_banner", "-loglevel", "error", "-y",
"-f", "lavfi", "-i", "testsrc2=size=320x180:rate=24:duration=4",
"-c:v", "libx264", "-preset", "ultrafast", "-pix_fmt", pixelformat, datei,
},
RedirectStandardError = true,
UseShellExecute = false,
};
try
{
using var prozess = Process.Start(start);
prozess!.WaitForExit(60_000);
if (prozess.ExitCode != 0 || !File.Exists(datei))
Assert.Ignore($"ffmpeg kann {pixelformat} hier nicht erzeugen.");
}
catch (Exception)
{
Assert.Ignore("Ohne ffmpeg lässt sich das nicht prüfen.");
}
return datei;
}
[Test]
public async Task Acht_und_zehn_Bit_ergeben_dieselbe_Zahl()
{
var abtaster = new Bildabtaster(
FfmpegOptions.FromEnvironment(), NullLogger<Bildabtaster>.Instance);
var acht = await abtaster.HelligkeitAsync(Erzeugen("yuv420p"), bei: 2);
var zehn = await abtaster.HelligkeitAsync(Erzeugen("yuv420p10le"), bei: 2);
Assert.Multiple(() =>
{
Assert.That(acht, Is.Not.Null);
Assert.That(zehn, Is.Not.Null.And.EqualTo(acht!.Value).Within(3),
"ohne `format=gray` stünde hier das Vierfache");
Assert.That(zehn, Is.LessThan(256), "die Skala muss 0–255 sein");
});
}
}