feat: extract MusicBrainz IDs from audio tags and store in library DB
Migration 13 adds nullable mbid TEXT columns to artists, release_groups, and recordings with partial indexes. Metadata extraction (tags.go) now reads MusicBrainz IDs from Raw() tags — handles both Vorbis (musicbrainz_artistid) and ID3v2 (MusicBrainz Artist Id) key formats. Scan pipeline (library.go) updates MBIDs after entity upsert via raw SQL UPDATE. Only sets mbid if currently NULL (preserves existing values on rescan). LibraryMBIDIndex (librarymbid.go) provides: - CheckMBIDs: batch lookup for 'In Library' badges - GetArtistMBID: single artist name→MBID lookup - AllArtistMBIDs: full dump for search index Tier 3 MBIDs will be populated on next library rescan. Existing files need a rescan to backfill.
This commit is contained in:
@@ -1234,9 +1234,59 @@ func (l *Library) processMetadata(
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Update MusicBrainz IDs (if present in tags).
|
||||
if releaseGroupID.Valid {
|
||||
l.updateMBIDs(cache, tags, artistName, releaseGroupID.Int64, recording.ID)
|
||||
} else {
|
||||
l.updateMBIDs(cache, tags, artistName, 0, recording.ID)
|
||||
}
|
||||
|
||||
return recording.ID, nil
|
||||
}
|
||||
|
||||
// updateMBIDs writes MusicBrainz IDs from audio file tags to the
|
||||
// corresponding database entities. Uses raw SQL since the sqlc
|
||||
// queries predate the mbid columns. Skips silently if tags have
|
||||
// no MBIDs.
|
||||
func (l *Library) updateMBIDs(
|
||||
cache *entityCache,
|
||||
tags *metadata.TrackMetadata,
|
||||
artistName string,
|
||||
releaseGroupID int64,
|
||||
recordingID int64,
|
||||
) {
|
||||
// Artist MBID — prefer album artist, fall back to track artist.
|
||||
artistMBID := tags.AlbumArtistMBID
|
||||
if artistMBID == "" {
|
||||
artistMBID = tags.ArtistMBID
|
||||
}
|
||||
|
||||
if artistMBID != "" {
|
||||
if artist, ok := cache.artists[artistName]; ok {
|
||||
_, _ = l.db.ExecContext(
|
||||
"UPDATE artists SET mbid = ? WHERE id = ? AND (mbid IS NULL OR mbid = '')",
|
||||
artistMBID, artist.ID,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Release group MBID.
|
||||
if tags.ReleaseGroupMBID != "" && releaseGroupID > 0 {
|
||||
_, _ = l.db.ExecContext(
|
||||
"UPDATE release_groups SET mbid = ? WHERE id = ? AND (mbid IS NULL OR mbid = '')",
|
||||
tags.ReleaseGroupMBID, releaseGroupID,
|
||||
)
|
||||
}
|
||||
|
||||
// Recording MBID.
|
||||
if tags.RecordingMBID != "" && recordingID > 0 {
|
||||
_, _ = l.db.ExecContext(
|
||||
"UPDATE recordings SET mbid = ? WHERE id = ? AND (mbid IS NULL OR mbid = '')",
|
||||
tags.RecordingMBID, recordingID,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// processCoverArt saves cover art to disk and upserts the DB record,
|
||||
// using the cache to skip work for previously seen images. When
|
||||
// thumbChan is non-nil, thumbnail generation is dispatched to the
|
||||
|
||||
Reference in New Issue
Block a user