No description
  • Python 96.9%
  • Dockerfile 2.1%
  • Nix 1%
Find a file
2026-08-13 08:17:00 -05:00
.gitignore ignore library dirs, fix readme formatting 2026-08-13 08:17:00 -05:00
docker-compose.yml better metadata recovery with acoustid and musicbrainz 2026-02-08 09:26:26 -06:00
Dockerfile better metadata recovery with acoustid and musicbrainz 2026-02-08 09:26:26 -06:00
music_sorter.py Make the artist extraction slightly smarter 2026-02-10 22:32:42 -06:00
README.md ignore library dirs, fix readme formatting 2026-08-13 08:17:00 -05:00
requirements.txt better metadata recovery with acoustid and musicbrainz 2026-02-08 09:26:26 -06:00
shell.nix Write the tags to the file 2026-02-10 07:32:11 -06:00
test_acoustid_tagging.py Write the tags to the file 2026-02-10 07:32:11 -06:00
test_recovery.py initial 2026-02-06 08:09:29 -06:00
test_sorter.py initial 2026-02-06 08:09:29 -06:00
test_watcher.py initial 2026-02-06 08:09:29 -06:00

Music Sorter

Sorts music files based on metadata.

Prerequisites

  1. AcoustID API Key: This project uses AcoustID for audio fingerprinting to identify files with missing metadata.
    • Go to https://acoustid.org/login and log in.
    • Click on "My applications" (or "Register a new application") to get an API key.
    • You will need to set this key as ACOUSTID_API_KEY in your environment or docker-compose.yml.

A Python-based utility to organize your music library into a folder structure optimized for Navidrome.

The tool reads metadata tags from your audio files and organizes them into Artist/Album/Disc-Track - Title.ext structure.

Features

  • Metadata-based Sorting: Uses Album Artist (or Artist), Album, Disc Number, Track Number, and Title.
  • Metadata Recovery: Attempts to recover missing tags from file paths or using a local LLM (Ollama).
  • Supports Multiple Formats: mp3, flac, ogg, m4a, opus, wav.
  • Safe Modes: Default behavior attempts to move files, but --copy and --dry-run modes are available.
  • File Watcher: Optional service to continuously watch download directories and sort new files automatically.
  • Dockerized: Easy to run anywhere without installing Python/dependencies locally.

Usage

Run with Docker Compose:

  1. Place your messy music in a folder (e.g., ./music_in).
  2. Run the sorter:
    docker-compose up -d music-sorter    # Run once
    docker-compose up -d music-watcher   # Run continuously
    
    Note: Modify environment variables in docker-compose.yml to change settings.

Run with Docker CLI:

docker build -t music-sorter .
docker run --rm \
  -v /path/to/source:/data/input \
  -v /path/to/destination:/data/output \
  -e OLLAMA_URL=http://host.docker.internal:11434 \
  -e OLLAMA_MODEL=llama3 \
  --add-host=host.docker.internal:host-gateway \
  music-sorter --input /data/input --output /data/output --copy

Option 2: Local (Nix)

If you have Nix installed:

nix-shell shell.nix
python3 music_sorter.py --input /path/to/source --output /path/to/destination --dry-run

Option 3: Local (Python)

Requires Python 3.11+ and mutagen.

pip install -r requirements.txt
python3 music_sorter.py --input /path/to/source --output /path/to/destination

Troubleshooting

AcoustID Error: status: error

If you see AcoustID WebServiceError: status: error in the logs:

  1. Verify your ACOUSTID_API_KEY is correct in docker-compose.yml.
  2. Ensure you have not exceeded your API limit (though our rate limiter helps).
  3. Check if your API key application is active on acoustid.org.

Configuration

You can use CLI arguments or Environment Variables (prefixed with MSC_).

Argument Env Var Description
--input MSC_INPUT Input directory path(s) (comma separated for Env).
--output MSC_OUTPUT Output directory path.
--dry-run MSC_DRY_RUN Set to true to simulate without moving.
--copy MSC_COPY Set to true to copy instead of move.
--verbose MSC_VERBOSE Set to true for debug logging.
--watch MSC_WATCH Set to true to enable file watcher mode.
OLLAMA_URL URL to Ollama instance (e.g., http://localhost:11434).
OLLAMA_MODEL Model to use (default: llama3).
ACOUSTID_API_KEY AcoustID API Key for audio fingerprinting.