4907d0d5a4
Adds the AudioProbe seam (probe.py, _probe.py MutagenProbe with a lazy mutagen import, FakeAudioProbe) and scan_library, which walks /music, resolves each album against MusicBrainz (falling back to embedded tags when the folder name doesn't resolve), and idempotently records matched albums as have (LibraryItem), monitored (MonitoredRelease, fulfilled), and followed (WatchedArtist, autoMonitorFuture=false). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
33 lines
1.1 KiB
Python
33 lines
1.1 KiB
Python
import os
|
|
|
|
from lyra_worker.probe import ProbeResult
|
|
from lyra_worker.quality import quality_class
|
|
from lyra_worker.types import Quality
|
|
|
|
_LOSSLESS_EXT = {".flac", ".wav", ".alac", ".aiff", ".aif"}
|
|
|
|
|
|
class MutagenProbe:
|
|
"""Real AudioProbe via mutagen (imported lazily; not unit-tested offline)."""
|
|
|
|
def probe(self, path: str) -> ProbeResult:
|
|
import mutagen
|
|
|
|
ext = os.path.splitext(path)[1].lower()
|
|
audio = mutagen.File(path, easy=True)
|
|
artist = album = ""
|
|
bit_depth = sample_rate = None
|
|
if audio is not None:
|
|
artist = (audio.get("artist") or [""])[0]
|
|
album = (audio.get("album") or [""])[0]
|
|
info = getattr(audio, "info", None)
|
|
bit_depth = getattr(info, "bits_per_sample", None)
|
|
sample_rate = getattr(info, "sample_rate", None)
|
|
q = quality_class(Quality(
|
|
fmt=ext.lstrip(".").upper(),
|
|
lossless=ext in _LOSSLESS_EXT,
|
|
bit_depth=bit_depth,
|
|
sample_rate=sample_rate,
|
|
))
|
|
return ProbeResult(artist=artist, album=album, fmt=ext.lstrip(".").upper(), quality_class=q)
|