A native macOS app that fills in missing ID3 / iTunes metadata for your music library. iTunes' own catalog is the primary source — drop a file or folder in, and Minmeta searches Apple's free public Search API for each track and writes title / artist / album / album-artist / year / genre / track number back into the file.
For tracks that aren't in Apple's catalog (bootlegs, demos, very obscure
indie) or whose filenames are too messy to identify (audio_export.mp3,
01 - track 1.mp3, random YouTube ID stubs), an optional OpenAI-compatible
model can be plugged in as a fallback. iTunes is consulted again for cover
art after the model returns.
⚠ Heads-up about accuracy. AI-suggested metadata can be wrong — especially for ambiguous filenames, covers, live versions, regional releases, or anything outside the well-documented mainstream. Always spot-check the results in your music player before trusting them. Minmeta writes whatever the model returns; it does not double-check. If the AI produces nothing or you don't trust it, leave the API key blank and Minmeta will run iTunes-only — anything iTunes can't find is left untouched.
For each file:
- Read existing tags + technical info via AVFoundation.
- Hint extraction — pull artist / title / album from existing tags first,
then from the filename (handles
Artist - Title,01 - Title,01. Artist - Title, strips[Official Video]/ YouTube IDs etc.) and the last 1–2 parent folder names. - iTunes Search — query the
songentity, score the top 5 hits against the hints, take the best match. If the artist+title score ≥ 4 (one field matched exactly OR both as substring) iTunes is trusted as the primary source. - AI fallback — only if iTunes scored too low and an API key is configured: ask the model to interpret the filename, then re-query iTunes with the model's canonical artist/title for cleaner art and any final backfill.
- Skip — if neither iTunes nor AI produced metadata (or no key is set
for the AI fallback), the file is marked
SKIPPED · NO ITUNES MATCH · SET API KEY IN CFG TO ENABLE AI FALLBACK. Existing tags stay intact.
The queue UI shows which path each row took: a ITUNES · … prefix in the
detail line means iTunes was the source; AI · … means the model was used.
When an AI key is configured, both sources run in parallel for every file. iTunes is the primary source for catalog fields; AI tops up composer / copyright (which iTunes doesn't return) and fills any field iTunes left empty.
| Field | iTunes | AI |
|---|---|---|
| Title | ✓ (primary) | ✓ (fills empties) |
| Artist | ✓ (primary) | ✓ (fills empties) |
| Album | ✓ (primary) | ✓ (fills empties) |
| Album artist | ✓ (primary) | ✓ (fills empties) |
| Year | ✓ (primary) | ✓ (fills empties) |
| Genre | ✓ (primary) | ✓ (fills empties) |
| Track number | ✓ (primary) | ✓ (fills empties) |
| Composer | — | ✓ (always) |
| Copyright | — | ✓ (always) |
| Cover art | ✓ (600 × 600 JPEG) | ✓ (re-queries iTunes) |
| Lyrics (USLT) | — | — |
| Bitrate / sample rate / duration / channels / codec | shown read-only | shown read-only |
If no API key is set, the columns marked "AI" don't run — composer / copyright stay empty, and any field iTunes couldn't return is left as whatever was already on disk.
| Format | Read | Write |
|---|---|---|
| MP3 | ✓ | ✓ ID3v2.3 — TIT2 TPE1 TALB TPE2 TYER TCON TRCK TCOM TCOP USLT APIC |
| M4A / MP4 / AAC | ✓ | ✓ via AVAssetExportSession passthrough + atomic replace |
| FLAC / WAV / AIFF / OGG | ✓ | — marked SKIPPED; suggestion is still shown in the queue row |
Requires macOS 14+ and the Swift toolchain that ships with Xcode 15+.
./build.sh
open build/Minmeta.appThe script regenerates App/AppIcon.icns if App/icon-source.png is newer,
runs swift build -c release, and produces an ad-hoc-signed
build/Minmeta.app.
- Launch the app — it boots straight into the main UI in iTunes-only mode by default. No login.
- (Optional) click the
CFGbutton in the title bar to open the settings window and add an OpenAI-compatible API key. The status bar in the main panel will showAI: gpt-4o-mini · FALLBACK READY. ClickFORGET KEYto go back to iTunes-only. - Drop files / folders onto the dropzone, or click
BROWSE…. Folders are walked recursively for supported extensions. - Each row goes through the phases WAIT → READ → ITNS → (AI if fallback) → TAG → DONE. The LED pulses through phase-coloured states and a per-row progress bar shimmers during the long phases. 3 files run in parallel.
- Buttons —
CLEARempties the queue (keeps in-flight items),REMOVE DONEpurges completed/skipped rows,RETRY FAILEDre-queues anything that errored.
- The optional API key is stored at
~/Library/Application Support/Minmeta/credentials.json(mode 0600, owner-only). The macOS Keychain is not used: every ad-hoc rebuild has a different code signature, which would prompt the "Allow / Always Allow" dialog on each launch. - For each track, filename + parent folder names + existing tags are
sent to
https://itunes.apple.com/search(Apple, no key) and — only on the AI-fallback path — to your configured OpenAI base URL. Audio bytes never leave the machine. - Album art is downloaded from Apple's iTunes CDN (whatever URL the search result links to) and embedded locally.
Sources/Minmeta/
├── MinmetaApp.swift # @main + RootView + Settings Window scene
├── AppState.swift # ObservableObject, queue, models
├── Theme.swift # Winamp colour palette + bevel modifiers
├── Views/
│ ├── Panel.swift # reusable Winamp-style panel chrome
│ ├── MainScreenView.swift # drop zone + status + activity meter
│ ├── QueuePanelView.swift # playlist-style queue with live updates
│ └── SettingsWindowView.swift # API key + base URL + model + FieldRow
└── Services/
├── CredentialsStore.swift # 0600 JSON file in Application Support
├── MetadataReader.swift # AVFoundation tag + tech-info read
├── ITunesArtClient.swift # iTunes Search → match + 600×600 JPEG
├── OpenAIClient.swift # /chat/completions JSON-mode prompt
├── ID3Writer.swift # ID3v2.3 frame writer (incl. APIC, USLT)
├── M4AWriter.swift # AVAssetExportSession passthrough
└── ProcessingEngine.swift # iTunes-first flow + AI fallback
Tools/
└── make_icon.swift # source PNG → AppIcon.iconset (squircle)
- Unsupported containers (FLAC / WAV / OGG) are intentionally
SKIPPED, notFAILED; the metadata suggestion is still surfaced in the row's detail line for reference.
