Add tag-based fallback to orphan detector to prevent false positives
When suffix path matching fails, reads file tags (title+artist) and checks against DB tracks. Prevents false orphan detection from path mismatches in Docker where DB paths differ from filesystem paths. Only runs for files that fail suffix matching — zero overhead in normal cases.
This commit is contained in:
parent
c53583716a
commit
dadc489b08
1 changed files with 27 additions and 0 deletions
|
|
@ -46,6 +46,7 @@ class OrphanFileDetectorJob(RepairJob):
|
||||||
# of depth 1-3 (filename, album/filename, artist/album/filename) which
|
# of depth 1-3 (filename, album/filename, artist/album/filename) which
|
||||||
# covers all realistic path-prefix mismatches.
|
# covers all realistic path-prefix mismatches.
|
||||||
known_suffixes = set()
|
known_suffixes = set()
|
||||||
|
known_titles = set() # (title_lower, artist_lower) for tag-based fallback
|
||||||
conn = None
|
conn = None
|
||||||
try:
|
try:
|
||||||
conn = context.db._get_connection()
|
conn = context.db._get_connection()
|
||||||
|
|
@ -57,6 +58,18 @@ class OrphanFileDetectorJob(RepairJob):
|
||||||
for depth in range(1, min(4, len(parts) + 1)):
|
for depth in range(1, min(4, len(parts) + 1)):
|
||||||
suffix = '/'.join(parts[-depth:]).lower()
|
suffix = '/'.join(parts[-depth:]).lower()
|
||||||
known_suffixes.add(suffix)
|
known_suffixes.add(suffix)
|
||||||
|
|
||||||
|
# Build title+artist set for tag-based fallback matching
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT t.title, ar.name FROM tracks t
|
||||||
|
LEFT JOIN artists ar ON ar.id = t.artist_id
|
||||||
|
WHERE t.title IS NOT NULL AND t.title != ''
|
||||||
|
""")
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
title = (row[0] or '').lower().strip()
|
||||||
|
artist = (row[1] or '').lower().strip()
|
||||||
|
if title:
|
||||||
|
known_titles.add((title, artist))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error reading known file paths from DB: %s", e, exc_info=True)
|
logger.error("Error reading known file paths from DB: %s", e, exc_info=True)
|
||||||
result.errors += 1
|
result.errors += 1
|
||||||
|
|
@ -108,6 +121,20 @@ class OrphanFileDetectorJob(RepairJob):
|
||||||
is_known = True
|
is_known = True
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# Fallback: read file tags and check if title+artist exists in DB
|
||||||
|
# Catches path mismatches where the file is tracked but under a different path
|
||||||
|
if not is_known and known_titles:
|
||||||
|
try:
|
||||||
|
from mutagen import File as MutagenFile
|
||||||
|
audio = MutagenFile(fpath, easy=True)
|
||||||
|
if audio:
|
||||||
|
file_title = ((audio.get('title') or [None])[0] or '').lower().strip()
|
||||||
|
file_artist = ((audio.get('artist') or [None])[0] or '').lower().strip()
|
||||||
|
if file_title and (file_title, file_artist) in known_titles:
|
||||||
|
is_known = True
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
if not is_known:
|
if not is_known:
|
||||||
orphan_files.append(fpath)
|
orphan_files.append(fpath)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue