soulsync/tests/matching/test_audio_verification_core.py
dev 8e6820dbdf feat(verification): status vocabulary, DB column, SOULSYNC_VERIFICATION tag
Also: evaluate() treats an empty expected artist as title-only comparison
(old scanner behaviour — a missing DB artist is no evidence of a wrong file),
and the thresholds are now defined once in the core and re-exported.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 01:27:29 +02:00

83 lines
2.9 KiB
Python
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.

"""Shared audio-verification decision core: normalize() + evaluate().
One place for normalization + the PASS/SKIP/FAIL decision used by BOTH import-time
verification and the library AcoustID scan, so the two paths can't drift apart.
"""
from core.matching.audio_verification import normalize, evaluate, Decision
def _rec(title, artist, duration=None):
return {"title": title, "artist": artist, "duration": duration}
def test_cross_script_vocal_credit_clean_match_passes():
# Sawano / 澤野弘之 <Vocal: ...> — <> stripped, alias bridges the artist,
# title matches too -> clean PASS (must never FAIL/quarantine).
out = evaluate(
"Call Your Name", "Sawano Hiroyuki",
[_rec("call your name", "澤野弘之 <Vocal: mpi & CASG>")],
fingerprint_score=0.95,
aliases_provider=lambda: ["澤野弘之"],
)
assert out.decision == Decision.PASS
def test_cross_script_ipa_title_skips_not_fails():
# AcoustID returns an IPA-transcribed title that can't string-match, but the
# artist bridges cross-script -> SKIP (import anyway), never FAIL.
out = evaluate(
"Attack on Titan", "Sawano Hiroyuki",
[_rec("ətˈæk 0N tάɪtn", "澤野弘之")],
fingerprint_score=0.95,
aliases_provider=lambda: ["澤野弘之"],
)
assert out.decision == Decision.SKIP
def test_clean_cross_script_match_passes():
out = evaluate(
"Xl-Tt", "Sawano Hiroyuki",
[_rec("xl-tt", "澤野弘之")],
fingerprint_score=0.95,
aliases_provider=lambda: ["澤野弘之"],
)
assert out.decision == Decision.PASS
def test_genuine_wrong_song_fails():
out = evaluate(
"Yellow", "Coldplay",
[_rec("Rich Interlude", "Kendrick Lamar")],
fingerprint_score=0.85,
)
assert out.decision == Decision.FAIL
def test_no_recordings_skips():
out = evaluate("Whatever", "Someone", [], fingerprint_score=0.9)
assert out.decision == Decision.SKIP
def test_normalize_strips_paren_bracket_angle_and_keeps_cjk():
assert normalize("澤野弘之 <Vocal: MIKA KOBAYASHI>") == "澤野弘之"
assert normalize("Clarity (Live at X) [Remastered]") == "clarity"
assert normalize("Attack on Titan <TV Size>") == "attack on titan"
def test_normalize_strips_version_and_featuring():
assert normalize("In My Feelings - Instrumental") == "in my feelings"
assert normalize("Song feat. Someone") == "song"
def test_normalize_keeps_plain_text():
assert normalize("Sawano Hiroyuki") == "sawano hiroyuki"
def test_empty_expected_artist_does_not_fail():
# Old scanner treated a missing expected artist as artist-match=1.0
# (compare title only). The unified core must not FAIL a track just
# because the DB has no artist value.
out = evaluate("Some Track", "", [_rec("Some Track", "Whoever")],
fingerprint_score=0.95)
assert out.decision == Decision.PASS