Metadata Enrichment
Relevant source files
The following files were used as context for generating this wiki page:
Metadata Enrichment identifies and fills missing information in a music library by querying external providers. It addresses gaps in track tags such as artist names, titles, album names, genres, years, and International Standard Recording Codes (ISRC). The system uses a non-destructive workflow where changes are previewed and verified by the user before being applied to the local database.
Sources: crates/core/src/enrichment.rs:1-12, README.md:129-131
Enrichment Workflow
The enrichment process follows a strictly defined "Preview → Apply → Undo" cycle. This ensures that the user maintains full control over automated metadata updates and can revert any changes that introduce inaccuracies.
1. Gap Detection
The system first calculates a "Tag Health Score" for tracks. This score identifies missing fields in the LocalTrack data structure, prioritizing identity fields like title and artist over secondary metadata.
2. Provider Lookup
Users select an external provider to search for the missing data. The system supports multiple sources, including MusicBrainz, iTunes, and Deezer. For each track with gaps, the system generates search queries and processes the provider's response into standardized ProviderCandidate records.
3. Comparison and Scoring
The system calculates a match_confidence score between the local track and candidates. This score determines if a match is "high" confidence, requires "review", or is a "low" confidence match.
4. User Review and Application
Candidates are presented as FieldProposal objects. Users select which proposals to accept. Accepted changes are written to the database but never modify the original source audio files.
The diagram shows the logical flow from detecting missing metadata to applying verified updates.
Sources: crates/core/src/enrichment.rs:9-12, apps/desktop/src/App.tsx:755-850
External Providers
The system integrates with several external metadata services. Some providers require specific API keys configured in the environment.
| Provider | Access Method | Key Required | Description |
|---|---|---|---|
| MusicBrainz | REST API | No | Open-source music encyclopedia; supports ISRC lookup. |
| iTunes | Search API | No | Apple's music catalog; provides high-quality 600px artwork. |
| Deezer | Public API | No | Supports ISRC-exact matching and fuzzy search. |
| Discogs | REST API | Yes | Personal token required; high-quality release-level data. |
| Last.fm | track.search | Yes | API Key required; provides track and artist metadata. |
| AcoustID | lookup | Yes | Requires API key and local Chromaprint fingerprint. |
Sources: crates/core/src/enrichment.rs:16-56, apps/desktop/src/services/api.ts:109-115
Matching Logic and Confidence
The system normalizes names by converting them to lowercase, dropping punctuation, and collapsing whitespace to ensure robust comparisons.
Confidence Tiers
The match_confidence function returns a float between 0.0 and 1.0 based on the following logic:
- 0.92 (High): Artist and Title match exactly after normalization.
- 0.65 (Review): Either Artist or Title matches exactly.
- 0.50 (Review): Local and candidate strings contain each other.
- 0.35 (Low): Default for mismatched or empty strings.
Sources: crates/core/src/enrichment.rs:141-168
Tag Health Scoring
A track's health is calculated by subtracting weights from a starting score of 100 based on missing fields.
| Field | Weight |
|---|---|
| Title / Artist | 25.0 |
| Album / ISRC / Artwork | 10.0 |
| Genre / Year | 5.0 |
| BPM / Key | 4.0 |
| Duration | 2.0 |
Sources: crates/core/src/enrichment.rs:242-258
Data Structures
ProviderCandidate
Standardized record representing a track found on an external service.
pub struct ProviderCandidate {
pub provider: String,
pub provider_id: String,
pub title: String,
pub artist: String,
pub album: Option<String>,
pub genre: Option<String>,
pub year: Option<i32>,
pub isrc: Option<String>,
pub artwork_url: Option<String>,
pub confidence: f64,
pub source_url: Option<String>,
}
Sources: crates/core/src/enrichment.rs:82-94
FieldProposal
Represents a specific metadata change offered to the user.
pub struct FieldProposal {
pub field: String,
pub current: Option<String>,
pub proposed: String,
}
Sources: crates/core/src/enrichment.rs:98-102
Database Implementation
Enrichment actions are tracked in the database to support undo functionality and maintain a history of changes. The enrichment_runs and enrichment_candidates tables (implemented in migrations 003 and 004) store snapshots of track states before and after application.
- Non-destructive: Changes update the
trackstable in SQLite but do not write tags back to the physical audio files. - Artwork Caching: Downloaded artwork is content-addressed using BLAKE3 hashes and stored in a local cache directory to prevent redundant downloads.
Sources: crates/core/src/metadata.rs:356-360, CHANGELOG.md:104-106, apps/desktop/src-tauri/migrations/001_initial_schema.sql:64-74
Summary
Metadata Enrichment provides a controlled, multi-provider pipeline for improving music library quality. By utilizing weighted health scoring, normalized string matching, and a mandatory preview-apply workflow, the system allows DJs to fix inconsistent or missing tags while protecting the integrity of their local audio files. All operations occur locally or via explicit, user-initiated network requests, adhering to the project's local-first and privacy-focused principles.