Files
Flaro/server/tests/Flaro.Core.Tests/EchteFingerprintsTests.cs
T
ScarriffleandClaude Opus 5 ed13d5fa43 Kratzplatz, Markenerkennung, Tonabdruck — erfundene Wörter für Fachbegriffe
„Scratch disk" wörtlich zu übersetzen ist derselbe Fehler wie „Wachhund"
für Watchdog und „Keks" für Cookie. Und „Marke" ist kein Fachbegriff für
das, was gemeint ist: Jellyfin nennt diese Abschnitte Media Segments, und
das ist auch das Wort, in dem sich darüber reden lässt.

    Kratzplatz*       → Transcode*          (was es ist, steht in FLARO_TRANSCODE)
    Marke, Marken     → Segment, Segmente
    Markenerkennung   → Segmenterkennung
    Markenart/-suche  → Segmentart/-suche
    Tonabdruck        → Fingerprint         (Chromaprint nennt es so)
    Tonabgleich       → Fingerprintabgleich
    Schlüsselbild     → Keyframe
    Bildabtaster      → Frameabtaster

Gewöhnliches Deutsch bleibt gewöhnliches Deutsch: Wartung, Freigabe,
Meldung, Abspann, Vorspann. Das war nie das Problem.

**Was sich nicht ändert, und zwar mit Absicht.** Die drei
Einstellungsschlüssel `wartung.kratzplatz.paket.*` bleiben, wie sie sind —
sie stehen in der Datenbank, und ein neuer Name hiesse, dass die Werte
des Nutzers stillschweigend auf die Vorgabe zurückfallen. Dasselbe für
die Endpunktpfade `/marken`: sie sind nicht sichtbar, und ein Umbenennen
wäre Diff ohne Gewinn.

**Die Migration ist von Hand geschrieben.** `dotnet ef` hat ein Gerüst
erzeugt, das beide Tabellen löscht und neu anlegt — es sieht eine
verschwundene und eine neue Tabelle, nicht eine umbenannte. Damit wäre
jedes erkannte Segment und jeder Vermerk „hier wurde schon gesucht" weg
gewesen. `RenameTable` und `RenameIndex` tun dasselbe, ohne eine Zeile
anzufassen; nachgemessen an einer echten SQLite-Datei: Zeilen vorher 1
und 1, nachher 1 und 1, Inhalt unverändert.

Nachgezogen: in `bilder.ts` und `main.ts` heisst „marke" ein Häkchen und
das Logo — die blieben unberührt. Und „Segment" ist sächlich, was eine
Blindersetzung nicht weiss: „eine Segment" stand danach an vierzehn
Stellen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-16 16:26:57 +02:00

57 lines
2.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Flaro.Core.Media;
namespace Flaro.Core.Tests;
/// <summary>Der Abgleich an echten Chromaprint-Abdrücken.</summary>
///
/// <remarks>
/// <b>Bisher nur mit erfundenen Zahlen geprüft.</b> Die sagen, ob die Suche
/// rechnet; sie sagen nicht, ob die Schwellen zu echtem Material passen.
/// Genau dazwischen kann alles liegen: zwei Aufnahmen desselben Stücks sind
/// nie bitgleich, und wie unähnlich sie sind, weiss man erst, wenn man es
/// misst.
///
/// Die beiden Abdrücke liegen als Prüfdaten daneben: zwei Tonspuren mit
/// demselben dreissigsekündigen Stück an verschiedenen Stellen und in
/// verschiedener Bitrate, durch <c>fpcalc</c> gedreht. Zwanzig Kilobyte
/// Text — der Preis dafür, dass diese Zusage nicht bloss behauptet ist.
/// </remarks>
public class EchteFingerprintsTests
{
private const double JeFingerprint = 4096.0 / 3.0 / 11025.0;
private static IReadOnlyList<uint>? Lesen(string name)
{
var pfad = Path.Combine(TestContext.CurrentContext.TestDirectory, "Fingerprints", name);
if (!File.Exists(pfad)) return null;
return File.ReadAllText(pfad)
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Select(t => unchecked((uint)long.Parse(t)))
.ToList();
}
[Test]
public void Dasselbe_Stueck_wird_in_zwei_Aufnahmen_gefunden()
{
var a = Lesen("folgeA.txt");
var b = Lesen("folgeB.txt");
if (a is null || b is null) Assert.Ignore("Keine Abdrücke zum Prüfen da.");
var treffer = Fingerprintabgleich.Finden(a, b, JeFingerprint);
TestContext.Out.WriteLine($"A {a.Count} Werte, B {b.Count} Werte");
TestContext.Out.WriteLine(treffer is null
? "NICHTS GEFUNDEN"
: $"A {treffer.AVon:0.0}–{treffer.ABis:0.0} s, B {treffer.BVon:0.0}–{treffer.BBis:0.0} s");
Assert.That(treffer, Is.Not.Null, "das Stück steckt in beiden");
Assert.Multiple(() =>
{
Assert.That(treffer!.AVon, Is.EqualTo(20).Within(3));
Assert.That(treffer.BVon, Is.EqualTo(75).Within(3));
Assert.That(treffer.Laenge, Is.EqualTo(30).Within(4));
});
}
}