using System.Diagnostics; using Flaro.Media; using Microsoft.Extensions.Logging.Abstractions; namespace Flaro.Media.Tests; /// Die Blätter der Vorschau — Zahl, Masse, Namen. /// /// /// /// Die einzige Prüfung hier, die ffmpeg braucht, und sie ist es /// wert: zwischen „der Filtergraph ist richtig geschrieben" und „die /// Kacheln liegen da, wo der Spieler sie sucht" liegt alles. Eine um eine /// Kachel verschobene Vorschau sieht niemand als Fehler — man hält sie /// für ein ungenaues Bild. /// /// /// Erzeugt wird ein Film von 250 Sekunden. Bei einem Bild alle zehn /// Sekunden sind das 25 Kacheln, und die passen auf ein Blatt von zehn /// mal zehn. /// /// public class VorschaubilderTests { private string _ordner = ""; private string _datei = ""; [OneTimeSetUp] public void Erzeugen() { _ordner = Directory.CreateDirectory(Path.Combine( Path.GetTempPath(), "flaro-vorschau-" + Guid.CreateVersion7().ToString("N"))).FullName; _datei = Path.Combine(_ordner, "quelle.mp4"); var start = new ProcessStartInfo("ffmpeg") { ArgumentList = { "-hide_banner", "-loglevel", "error", "-y", "-f", "lavfi", "-i", "testsrc2=size=640x360:rate=25:duration=250", "-c:v", "libx264", "-preset", "ultrafast", "-g", "50", "-pix_fmt", "yuv420p", _datei, }, RedirectStandardError = true, UseShellExecute = false, }; try { using var prozess = Process.Start(start); prozess!.WaitForExit(120_000); if (prozess.ExitCode != 0 || !File.Exists(_datei)) Assert.Ignore("ffmpeg konnte die Prüfdatei nicht erzeugen."); } catch (Exception) { Assert.Ignore("Ohne ffmpeg lässt sich das nicht prüfen."); } } [OneTimeTearDown] public void Aufraeumen() { try { Directory.Delete(_ordner, recursive: true); } catch (IOException) { } } [Test] public async Task Ein_Lauf_ergibt_ein_Blatt_mit_richtigen_Massen() { var ziel = Path.Combine(_ordner, "blaetter"); var bilder = new Vorschaubilder( FfmpegOptions.FromEnvironment(), NullLogger.Instance); var plan = await bilder.ErzeugenAsync(_datei, ziel, "pruef-123"); Assert.That(plan, Is.Not.Null, "der Lauf muss Blätter ergeben"); Assert.Multiple(() => { Assert.That(plan!.Value.Blaetter, Is.EqualTo(1), "25 Kacheln passen auf ein Blatt von zehn mal zehn"); Assert.That(plan.Value.KachelBreite, Is.EqualTo(Vorschaubilder.Breite)); // 640×360 ist 16:9 — bei 320 Breite also 180 hoch. Assert.That(plan.Value.KachelHoehe, Is.EqualTo(180).Within(2)); Assert.That(plan.Value.Intervall, Is.EqualTo(Vorschaubilder.Intervall)); }); Assert.Multiple(() => { Assert.That(File.Exists(Path.Combine(ziel, "pruef-123-000.jpg")), "die Blätter heissen nach dem Präfix und ihrer Nummer"); Assert.That(Directory.GetFiles(ziel, "*.teil-*"), Is.Empty, "nichts Halbes bleibt liegen"); }); } /// Eine Datei, die es nicht gibt, ergibt nichts — und wirft nicht. [Test] public async Task Ohne_Quelle_kein_Plan() { var bilder = new Vorschaubilder( FfmpegOptions.FromEnvironment(), NullLogger.Instance); var plan = await bilder.ErzeugenAsync( Path.Combine(_ordner, "gibtsnicht.mkv"), Path.Combine(_ordner, "leer"), "x"); Assert.That(plan, Is.Null); } }