Enforce strict version matching for track confidence
Adds strict checks to ensure Soulseek track versions (live, remix, acoustic, instrumental) are only matched if the Spotify track title contains corresponding version indicators. This prevents mismatched versions from being accepted and applies a reduced penalty for matching non-original versions.
This commit is contained in:
parent
dead8da5ee
commit
09b4638279
1 changed files with 79 additions and 6 deletions
|
|
@ -613,16 +613,89 @@ class MusicMatchingEngine:
|
|||
"""
|
||||
Enhanced version of calculate_slskd_match_confidence with version-aware scoring.
|
||||
Returns (confidence, version_type) tuple.
|
||||
|
||||
STRICT VERSION MATCHING:
|
||||
- Live versions are ONLY accepted if Spotify track title contains "live" or "live version"
|
||||
- Remixes are ONLY accepted if Spotify track title contains "remix" or "mix"
|
||||
- Acoustic versions are ONLY accepted if Spotify track title contains "acoustic"
|
||||
- etc.
|
||||
"""
|
||||
# Get base confidence using existing logic
|
||||
base_confidence = self.calculate_slskd_match_confidence(spotify_track, slskd_track)
|
||||
|
||||
# Detect version type and get penalty
|
||||
|
||||
# Detect version type in Soulseek result
|
||||
version_type, penalty = self.detect_version_type(slskd_track.filename)
|
||||
|
||||
# Apply version penalty
|
||||
|
||||
# Check if Spotify track title contains version indicators
|
||||
spotify_title_lower = spotify_track.name.lower()
|
||||
|
||||
# STRICT VERSION MATCHING: Reject mismatched versions
|
||||
if version_type == 'live':
|
||||
# Only accept live versions if Spotify title has live as a VERSION INDICATOR
|
||||
# Patterns: (Live), - Live, [Live], Live at, Live from, Live in, Live Version
|
||||
# NOT: words ending with 'live' like "Let Me Live" or starting like "Lively"
|
||||
live_patterns = [
|
||||
r'\(live\)', # (Live) or (Live at Wembley)
|
||||
r'\[live\]', # [Live]
|
||||
r'[-–—]\s*live\b', # - Live or – Live
|
||||
r'\blive\s+at\b', # Live at
|
||||
r'\blive\s+from\b', # Live from
|
||||
r'\blive\s+in\b', # Live in
|
||||
r'\blive\s+version\b', # Live Version
|
||||
r'\blive\s+recording\b' # Live Recording
|
||||
]
|
||||
has_live_indicator = any(re.search(pattern, spotify_title_lower) for pattern in live_patterns)
|
||||
|
||||
if not has_live_indicator:
|
||||
# Reject: Soulseek has live version but Spotify doesn't want it
|
||||
return 0.0, 'rejected_version_mismatch'
|
||||
|
||||
elif version_type == 'remix':
|
||||
# Only accept remixes if Spotify title has remix as a VERSION INDICATOR
|
||||
# Patterns: (Remix), - Remix, [Remix], Remix, Mix
|
||||
remix_patterns = [
|
||||
r'\(.*?(remix|mix|rmx).*?\)', # (Remix) or (DJ Remix)
|
||||
r'\[.*?(remix|mix|rmx).*?\]', # [Remix]
|
||||
r'[-–—]\s*(remix|mix|rmx)\b', # - Remix
|
||||
r'\b(remix|mix|rmx)\s*$', # Remix at end
|
||||
]
|
||||
has_remix_indicator = any(re.search(pattern, spotify_title_lower) for pattern in remix_patterns)
|
||||
|
||||
if not has_remix_indicator:
|
||||
# Reject: Soulseek has remix but Spotify wants original
|
||||
return 0.0, 'rejected_version_mismatch'
|
||||
|
||||
elif version_type == 'acoustic':
|
||||
# Only accept acoustic if Spotify title has acoustic as a VERSION INDICATOR
|
||||
acoustic_patterns = [
|
||||
r'\(.*?acoustic.*?\)', # (Acoustic)
|
||||
r'\[.*?acoustic.*?\]', # [Acoustic]
|
||||
r'[-–—]\s*acoustic\b', # - Acoustic
|
||||
r'\bacoustic\s+version\b', # Acoustic Version
|
||||
]
|
||||
has_acoustic_indicator = any(re.search(pattern, spotify_title_lower) for pattern in acoustic_patterns)
|
||||
|
||||
if not has_acoustic_indicator:
|
||||
# Reject: Soulseek has acoustic but Spotify wants original
|
||||
return 0.0, 'rejected_version_mismatch'
|
||||
|
||||
elif version_type == 'instrumental':
|
||||
# Only accept instrumental if Spotify title has instrumental as a VERSION INDICATOR
|
||||
instrumental_patterns = [
|
||||
r'\(.*?instrumental.*?\)', # (Instrumental)
|
||||
r'\[.*?instrumental.*?\]', # [Instrumental]
|
||||
r'[-–—]\s*instrumental\b', # - Instrumental
|
||||
r'\binstrumental\s+version\b', # Instrumental Version
|
||||
]
|
||||
has_instrumental_indicator = any(re.search(pattern, spotify_title_lower) for pattern in instrumental_patterns)
|
||||
|
||||
if not has_instrumental_indicator:
|
||||
# Reject: Soulseek has instrumental but Spotify wants original
|
||||
return 0.0, 'rejected_version_mismatch'
|
||||
|
||||
# Apply version penalty (for matching versions, slight penalty for quality differences)
|
||||
if version_type != 'original':
|
||||
adjusted_confidence = max(0.0, base_confidence - penalty)
|
||||
adjusted_confidence = max(0.0, base_confidence - (penalty * 0.5)) # Reduced penalty since it's a match
|
||||
# Store version info on the track object for UI display
|
||||
slskd_track.version_type = version_type
|
||||
slskd_track.version_penalty = penalty
|
||||
|
|
@ -630,7 +703,7 @@ class MusicMatchingEngine:
|
|||
adjusted_confidence = base_confidence
|
||||
slskd_track.version_type = 'original'
|
||||
slskd_track.version_penalty = 0.0
|
||||
|
||||
|
||||
return adjusted_confidence, version_type
|
||||
|
||||
def find_best_slskd_matches_enhanced(self, spotify_track: SpotifyTrack, slskd_results: List[TrackResult]) -> List[TrackResult]:
|
||||
|
|
|
|||
Loading…
Reference in a new issue