CLI for downloading, searching, and enriching MP3 metadata via Soulseek, Bandcamp, MusicBrainz, and Discogs
Project description
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 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 an MP3 file's metadata (artist, album, genre, label, styles, track number, artwork, etc.) from Bandcamp, MusicBrainz, and Discogs
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
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 |
|---|---|---|
--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 an MP3 file 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"
The 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.
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.
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
│ ├── 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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file track_id-0.2.0.tar.gz.
File metadata
- Download URL: track_id-0.2.0.tar.gz
- Upload date:
- Size: 140.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c9beb40277af9a368111340b2eb3581530a3846fdaadec00492cbf83cf74ad9
|
|
| MD5 |
b0b914452d0d7a14efb496220091b2c9
|
|
| BLAKE2b-256 |
0b7b588bdd997971f41c0c6dd0150c2ac1262c7cc4f67fdbab0639419b2e1d8e
|
Provenance
The following attestation bundles were made for track_id-0.2.0.tar.gz:
Publisher:
publish-pypi.yml on vtasca/track-id
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
track_id-0.2.0.tar.gz -
Subject digest:
2c9beb40277af9a368111340b2eb3581530a3846fdaadec00492cbf83cf74ad9 - Sigstore transparency entry: 1697285918
- Sigstore integration time:
-
Permalink:
vtasca/track-id@6eaae88831ecbc3e63e07c657428aa941c1eefde -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vtasca
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@6eaae88831ecbc3e63e07c657428aa941c1eefde -
Trigger Event:
push
-
Statement type:
File details
Details for the file track_id-0.2.0-py3-none-any.whl.
File metadata
- Download URL: track_id-0.2.0-py3-none-any.whl
- Upload date:
- Size: 29.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca8db9d3b027580e00d4d9dbe5abb3a45cf9946e46cd742facbcb5ef4bd6016d
|
|
| MD5 |
1f7d33b8bb1b1a41a2cf8a54b4bb4746
|
|
| BLAKE2b-256 |
cb033ea3f3ab00945cb496eb45b4af7ce3fa06abd23541bb78e2c9d43c4c58ad
|
Provenance
The following attestation bundles were made for track_id-0.2.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on vtasca/track-id
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
track_id-0.2.0-py3-none-any.whl -
Subject digest:
ca8db9d3b027580e00d4d9dbe5abb3a45cf9946e46cd742facbcb5ef4bd6016d - Sigstore transparency entry: 1697286056
- Sigstore integration time:
-
Permalink:
vtasca/track-id@6eaae88831ecbc3e63e07c657428aa941c1eefde -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/vtasca
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@6eaae88831ecbc3e63e07c657428aa941c1eefde -
Trigger Event:
push
-
Statement type: