Skip to main content

Music Metadata Fixer

Python 3.8+ License: MIT Tests

Automatically fix audio file metadata using AcoustID fingerprinting and MusicBrainz database. Supports MP3, FLAC, and M4A formats with both CLI and optional GUI interfaces.

Features

  • 🎵 Automatic Identification – Fingerprints audio files using AcoustID
  • 🗄️ Metadata Lookup – Fetches comprehensive metadata from MusicBrainz
  • 📝 Multi-Format Support – MP3 (ID3), FLAC (Vorbis), M4A (MP4 tags)
  • 🎛️ Dual Interface – Command-line or Tkinter GUI (optional)
  • 🔄 Batch Processing – Process entire folders at once
  • ⏸️ Cancellation – Stop processing cleanly at any time
  • 🔧 Configurable – Customize API keys, timeouts, preview duration
  • 📋 Full Logging – Detailed error tracking and debugging
  • 🧪 Well-Tested – Comprehensive test coverage including edge cases

Quick Start

Installation

From PyPI (Recommended)

pip install music-metadata-fixer

From Source

git clone https://github.com/yourusername/music-metadata-fixer.git
cd music-metadata-fixer
pip install -e .[dev]

Setup

  1. Get AcoustID API Key (free): https://acoustid.org/api

  2. Create config file:

    cp config.json.example config.json
    
  3. Edit config.json and add your API key:

    {
      "acoustid_api_key": "YOUR_KEY_HERE",
      "preview_duration_ms": 30000,
      ...
    }
    

Usage

Command Line

# Interactive mode (prompts for confirmation on each file)
music-metadata-fixer --directory /path/to/music

# Batch mode (no prompts, requires --batch flag)
music-metadata-fixer --directory /path/to/music --batch

# Disable audio preview
music-metadata-fixer --directory /path/to/music --no-audio

# GUI mode (if available)
music-metadata-fixer --gui

Python API

from config import Config
from providers import AcoustIDProvider
from engine import MetadataFixerEngine

# Initialize
config = Config('config.json')
provider = AcoustIDProvider(config.get('acoustid_api_key'))
engine = MetadataFixerEngine(provider)

# Process folder
results = engine.batch_process(
    directory='/path/to/music',
    interactive=False,
    auto_confirm=True
)

print(f"Success: {results['success']}, Failed: {results['failed']}")

Requirements

System Dependencies

  • ffmpeg – For audio conversion (optional but recommended)

  • fpcalc – AcoustID fingerprint calculator

Python Dependencies

All installed automatically via pip install:

  • pyacoustid ≥ 1.2.2
  • musicbrainzngs ≥ 0.7
  • mutagen ≥ 1.46.0
  • pydub ≥ 0.25.1
  • pygame ≥ 2.1.0 (audio playback, optional)

Configuration

config.json

{
  "acoustid_api_key": "YOUR_API_KEY",           # Required: AcoustID API key
  "preview_duration_ms": 30000,                 # Audio preview duration (ms)
  "log_file": "music_fixer_errors.log",         # Log file path
  "supported_formats": [".mp3", ".flac", ".m4a"], # File formats to process
  "feature_preview": true,                      # Enable audio playback
  "feature_auto_identify": true,                # Auto-identify files
  "feature_manual_edit": true,                  # Allow manual editing
  "console_log": false,                         # Log to console
  "log_level": "INFO"                           # Logging level (DEBUG, INFO, WARNING, ERROR)
}

Architecture

┌─────────────────────────────────────────┐
│             CLI / GUI                    │
│    (music_fixer.py / gui_interface.py)   │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────▼───────────────────────┐
│      MetadataFixerEngine                 │
│  (orchestrates identify → fetch → apply) │
└─────────────────┬───────────────────────┘
    ┌─────────────┼─────────────┐
    │             │             │
┌───▼──┐   ┌─────▼─────┐  ┌────▼────┐
│Provider  │FileHandler │  │AudioPlayer
│(AcoustID │  (MP3,     │  │(Preview)
│+Brainz)  │FLAC,M4A)   │  │
└──────┘   └───────────┘  └─────────┘

Module Overview

Module Purpose
music_fixer.py CLI entry point & argument handling
engine.py Core processing workflow orchestration
providers.py AcoustID + MusicBrainz integration
file_handler.py Format-specific tag readers/writers
config.py Configuration file management
audio_player.py Audio preview with pygame
gui_interface.py Optional Tkinter GUI
logger.py Centralized logging
cancellable.py Cancellation token for clean shutdown

Testing

# Run all tests
pytest

# Run with coverage
pytest --cov=. --cov-report=html

# Run specific test file
pytest tests/test_engine.py -v

# Run specific test class
pytest tests/test_providers.py::ProviderCancellationTests -v

Test Coverage

  • ✓ Engine workflow (identify → fetch → apply)
  • ✓ Provider retries, timeouts, and error handling
  • ✓ Cancellation token propagation
  • ✓ Batch processing with partial failures
  • ✓ File format handlers (MP3, FLAC, M4A)
  • ✓ GUI components and threading
  • ✓ Configuration loading and validation

Development

Setup Development Environment

pip install -e .[dev]
pre-commit install

Code Quality

# Type checking
mypy .

# Linting
flake8 .
pylint music_fixer.py

# Auto-formatting
black .

Adding New Provider

See DEVELOPMENT.md

Adding File Format Support

See DEVELOPMENT.md

Troubleshooting

"Missing external tools" warning

Install ffmpeg and fpcalc:

# macOS
brew install ffmpeg chromaprint

# Ubuntu/Debian
sudo apt install ffmpeg libchromaprint-tools

# Or download Windows binaries from respective websites

"API key not found"

Ensure config.json has acoustid_api_key field populated:

cp config.json.example config.json
# Edit config.json with your key

Files not being identified

  1. Check file format is supported (MP3, FLAC, M4A)
  2. Ensure file is a valid audio file (try playing in media player)
  3. Verify AcoustID API is responding (check log file)
  4. Try with --no-audio flag (some systems have audio issues)

GUI doesn't start

Tkinter may not be installed:

# Ubuntu/Debian
sudo apt install python3-tk

# macOS
# Should be included; if not: brew install python-tk

# Windows
# Should be included with Python; reinstall Python and select Tcl/Tk

Metadata lookup returns "Unknown"

  • File may not be in MusicBrainz database
  • Fingerprint calculation may have failed
  • Network connectivity issue (check logs)
  • Use --batch --no-audio for faster processing

Examples

Process single folder

music-metadata-fixer --directory ~/Music/unsorted

Batch process multiple folders

for folder in ~/Music/Artist1 ~/Music/Artist2; do
    music-metadata-fixer --directory "$folder" --batch
done

Process with logging

music-metadata-fixer --directory ~/Music --no-audio > processing.log 2>&1

GUI with custom timeout

Edit config.json:

{
  "acoustid_api_key": "YOUR_KEY",
  "timeout": 20  // Longer timeout for slow connections
}

Then run: music-metadata-fixer --gui

Performance

  • Typical file processing: 3-5 seconds (fingerprint + lookup + write)
  • Batch processing: ~100 files in 5-10 minutes (depending on network)
  • Memory usage: ~50MB idle, ~200MB during batch processing
  • Can be reduced by using --no-audio flag

Known Limitations

  • GUI is Tkinter-only (not PyQt/PySide)
  • Cannot process multiple folders simultaneously
  • Requires specific audio file formats (no WAV, OGG, etc. yet)
  • Interactive mode requires user input for each file
  • No proxy support for MusicBrainz API

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Add tests for new functionality
  4. Ensure tests pass (pytest)
  5. Submit a pull request

See DEVELOPMENT.md for detailed guidelines.

Version History

v0.4.0 (Current)

  • Full type hints across all modules
  • Comprehensive test suite (cancellation, failures, GUI)
  • Package entry point (music-metadata-fixer command)
  • Optional dev dependencies for testing/linting
  • GUI validation and documentation

v0.2.0

  • Added FLAC and M4A support
  • Improved error handling and retries
  • Configuration management system

v0.1.0

  • Initial release
  • MP3 support with ID3 tags
  • AcoustID + MusicBrainz integration
  • CLI interface

License

MIT License – see LICENSE for details

Credits

Built with:

Support


Questions? Check out the FAQ or troubleshooting guide.

Metadata

Release files for music-metadata-fixer 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for music-metadata-fixer 0.4.0
File Size Uploaded Provenance Actions
music_metadata_fixer-0.4.0.tar.gz 30.4 kB Without provenance Details for music_metadata_fixer-0.4.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for music-metadata-fixer 0.4.0
File Interpreter ABI Platform Actions
music_metadata_fixer-0.4.0-py3-none-any.whl Python 3 none any Details for music_metadata_fixer-0.4.0-py3-none-any.whl

Total release size: 53.5 kB

Release files / music_metadata_fixer-0.4.0.tar.gz

Download URL music_metadata_fixer-0.4.0.tar.gz
Size 30.4 kB
Tags Source
SHA-256 checksum
How to use checksums
d72a99268fe339b6324b585899a6dae9aa29b4dbd58a71e12d0626699168fb28
BLAKE2b-256 checksum
How to use checksums
48dcfb91d2b4ac21e734e88ec2fb6ed426e6565648f43dd0d4b1ee67ff484f84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / music_metadata_fixer-0.4.0-py3-none-any.whl

Download URL music_metadata_fixer-0.4.0-py3-none-any.whl
Size 23.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
75279bee222a0aed89b9ed46ac33d9aef930edd96115a5067aba32e5e740924d
BLAKE2b-256 checksum
How to use checksums
44746a9b5314472ce48dd17743be413a33c17b1393a1d60105a299ad52bfd4dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Security for music-metadata-fixer 0.4.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page