track-id
A Python CLI tool for music metadata enrichment, search, and download. Searches and downloads tracks from Soulseek, displays MP3 file info, and enriches MP3 files with metadata from Bandcamp, MusicBrainz, and Discogs.
Features
- Download: Search Soulseek for a track — or a whole wishlist via
--from— and download the best match, with automatic metadata enrichment - Search: Search for tracks across Bandcamp, MusicBrainz, and Discogs
- Info: Display detailed information about an MP3 file including all ID3 tags
- Enrich: Automatically populate the metadata of an MP3 file — or a whole directory — (artist, album, genre, label, styles, track number, artwork, etc.) from Bandcamp, MusicBrainz, and Discogs
- Rename: Rename files from their tags using a template like
{artist} - {title} - Doctor: Scan a library for fake audio files, low bitrates, and missing tags or artwork
- Analyze: Deep-inspect one file — real container format, bitrate mode, encoder, tag completeness
Installation
Using uv
Install from PyPI as a tool:
uv tool install track-id
track-id --version
track-id search "Chaos In The CBD"
Using pip
Install from PyPI with pip:
pip install track-id
track-id --version
track-id search "Chaos In The CBD"
track-id info "path/to/your/file.mp3"
track-id enrich "path/to/your/file.mp3"
Clone and install locally
Mainly for development purposes:
# Clone the repository
git clone https://github.com/vtasca/track-id
cd track-id
# Install dependencies
uv sync
Usage
Download a track from Soulseek
Searches the Soulseek network, ranks candidates by bitrate and filename match, downloads the best result, and automatically enriches the file with metadata from Bandcamp, MusicBrainz, and Discogs:
track-id download "Aphex Twin - Windowlicker"
track-id download "Burial - Archangel" --output-dir ~/Music
track-id download "DJ Krush - Ha Doh" --min-bitrate 320 --timeout 20
# Batch: one 'Artist - Title' query per line (# comments and blanks are skipped),
# all downloaded over a single Soulseek connection
track-id download --from tracks.txt
Files are saved to downloads/ by default. Credentials are required — set them once:
# Option 1: .env file in the project root (copy from .env.example)
cp .env.example .env # then fill in your username and password
# Option 2: environment variables
export SOULSEEK_USERNAME=your_username
export SOULSEEK_PASSWORD=your_password
# Option 3: ~/.config/track-id/config.toml
# [soulseek]
# username = "your_username"
# password = "your_password"
A free Soulseek account can be created at slsknet.org.
Available options:
| Flag | Default | Description |
|---|---|---|
--from |
— | Text file of queries to download in one batch |
--output-dir / -o |
downloads/ |
Directory to save the file |
--min-bitrate |
192 |
Minimum acceptable bitrate in kbps |
--timeout / -T |
10.0 |
Seconds to collect search results |
--attempts |
5 |
Max download attempts before giving up |
--no-enrich |
— | Skip metadata enrichment after download |
Search for tracks
Search across Bandcamp, MusicBrainz, and Discogs simultaneously:
track-id search "Chaos In The CBD"
track-id search "Burial - Archangel" --top 5
The --top / -t flag controls how many results are shown per source (default: 3).
Display MP3 file information
track-id info "path/to/your/file.mp3"
Enrich MP3 files with metadata
Queries Bandcamp, MusicBrainz, and Discogs for a matching track and writes the retrieved metadata directly into the file's ID3 tags:
track-id enrich "path/to/your/file.mp3"
# A whole directory (recursive), with a per-file ledger and summary
track-id enrich ~/Music/incoming/
# Preview without writing, or overwrite fields that already have values
track-id enrich "file.mp3" --dry-run
track-id enrich "file.mp3" --force
Each file must have either existing Artist and Title ID3 tags, or an Artist - Title filename so the tool knows what to search for. All three sources are tried and their results merged — existing tags are never overwritten unless --force is passed.
Tags populated across sources include: Title, Artist, Album Artist, Album, Year, Track Number, Genre, Publisher/Label, Style (Discogs community tags), Artwork, and a Discogs URL reference.
Rename files from their tags
track-id rename "file.mp3" # '{artist} - {title}'
track-id rename ~/Music --template "{year} {artist} - {title}" --dry-run
Available template fields: {artist} {title} {album} {year} {genre} {track}. Files with missing tag values or name collisions are skipped, never clobbered.
Check library health
track-id doctor ~/Music --min-bitrate 256
Recursively flags files that aren't real audio (e.g. an HTML error page saved as .mp3), fall below the bitrate threshold, or lack core tags or artwork.
Analyze a single file
track-id analyze "file.mp3"
Reports the true container format (from magic bytes, not the extension), bitrate and CBR/VBR mode, sample rate, encoder, all tags, and any problems found.
Development
Setting up the development environment
uv sync --dev
Running tests
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=track_id --cov-report=term-missing
# Run a specific file
uv run pytest tests/test_data_sources.py -v
Project Structure
track-id/
├── track_id/
│ ├── track_id.py # CLI commands (Typer app)
│ ├── unified_api.py # Orchestrates search/enrich across all sources
│ ├── data_sources.py # Abstract base class + registry
│ ├── bandcamp_api.py # Bandcamp data source
│ ├── musicbrainz_api.py # MusicBrainz data source
│ ├── discogs_api.py # Discogs data source
│ ├── enrichment_handlers.py# Shared enrichment logic
│ ├── analysis.py # File inspection — format sniffing, stream/tag checks
│ ├── soulseek_downloader.py# Soulseek download via aioslsk
│ ├── config.py # Credential loading (.env / env vars / config file)
│ ├── mp3_utils.py # MP3File class — ID3 read/write, filename parsing
│ ├── display.py # Rich console output
│ ├── id3_tags.py # Canonical ID3 tag name mapping
│ └── __init__.py
├── tests/
│ ├── conftest.py
│ ├── test_data_sources.py
│ ├── test_bandcamp_api.py
│ ├── test_musicbrainz_api.py
│ ├── test_discogs_api.py
│ ├── test_soulseek_downloader.py
│ ├── test_config.py
│ ├── test_artwork.py
│ ├── test_id3_tags.py
│ ├── test_track_id.py
│ └── test_integration.py
├── .env.example # Credential template
├── pyproject.toml
└── README.md
Contributing
- Write tests for new features
- Ensure all tests pass
- Follow the existing code style
- Update documentation as needed
Metadata
Release files for track-id 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| track_id-0.4.0.tar.gz | 168.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| track_id-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 216.3 kB
Release files / track_id-0.4.0.tar.gz
| Download URL | track_id-0.4.0.tar.gz |
|---|---|
| Size | 168.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6e1be2a3087131b64f010894a1de103962c7fc1745539da34a93a922846d944d
|
|
BLAKE2b-256 checksum How to use checksums |
8c7e4e076da43a73ec9f97578bde0ca5cfa686d5ab340140f4fa1988678ed1a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.
Transparency logRelease files / track_id-0.4.0-py3-none-any.whl
| Download URL | track_id-0.4.0-py3-none-any.whl |
|---|---|
| Size | 47.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
581ea57c836427b600d1b2ada3691f98bec2a895636c93f7428bca9f29ef30c5
|
|
BLAKE2b-256 checksum How to use checksums |
a17f37d947986bd1cf1597cd50d313de5c302a61f9e2be996136397a4cbfb304
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.
Transparency log