mudio is a powerful, friendly command-line music metadata editor and Python library. It provides a unified API for handling metadata across MP3, FLAC, M4A, and more, making batch processing and automation simple and safe.
- For full command details, see the CLI Reference.
- For code API details, see the API Reference.
- Unified API: Write code once, run it on MP3, FLAC, M4A, WAV, OGG, and OPUS.
- Batch Processing: robust CLI for processing thousands of files.
- Parallel Execution: Automatically uses multi-threading for large batches.
- Safety First: Built-in backup system, dry-run mode, and careful validation.
- Powerful Operations:
- Find & Replace: Regex-supported search and replace in tags.
- Mass Edits: Set, overwrite, append, prefix, or clear tags.
- Filtering: Apply changes only to files matching specific criteria (e.g.
artist="The Beatles").
- MP3 (
.mp3) - ID3v2.3/v2.4 - FLAC (
.flac) - Vorbis Comments - M4A / MP4 (
.m4a,.mp4) - MP4 Tags - Ogg Vorbis (
.ogg) - Opus (
.opus) - WAV (
.wav)
pip install mudio# Set album name for all MP3 files
mudio *.mp3 --operation write --fields album --value "Greatest Hits"# Fix title formatting for 1990s Rock tracks, with backups and regex
mudio /music --recursive --backup ./backups \
--filter-regex --filter "date=^199" --filter "genre=Rock" \
--operation find-replace --fields title --find "\s+" --replace " " --regex💡 Tip: Use
--dry-runto preview changes before applying them.
from mudio.processor import process_file
from mudio.operations import write
# Update a single file with automatic verification
result = process_file(
"song.mp3",
ops=[write('artist', 'The Beatles')]
)
print(f"Success: {result['passed']}") # True if successfulfrom mudio.processor import process_files
from mudio.operations import write, enlist, find_replace
from pathlib import Path
# Process multiple files with complex operations
results = process_files(
Path('music').rglob('*.flac'),
ops=[
enlist('genre', 'Rock;Classic'), # Add genres if not present
find_replace('title', r'\s+', ' ', regex=True), # Normalize whitespace
write('albumartist', 'Various Artists')
],
filters=[('date', '^199', True)], # Only 1990s tracks (regex)
backup_dir='./backups',
max_workers=4
)
print(f"Updated {sum(r['passed'] for r in results)} files")You can configure mudio's default behavior using environment variables:
MUDIO_SCHEMA: Set default schema for reading metadata (canonical,extended, orraw). Default:extended.MUDIO_MAX_WORKERS: Default thread count for parallel processing.MUDIO_VERBOSE: Default verbosity (0or1).MUDIO_NAMESPACE: Namespace for custom MP4/M4A fields (default:com.apple.iTunes). Setting this to something else (e.g.org.myproject) allows isolating your custom tags.
# Example: Use extended schema by default (canonical + custom fields)
export MUDIO_SCHEMA=extended
python your_script.pymudio normalizes metadata to a case-insensitive canonical schema and applies consistent rules across formats.
- Canonical fields: Tags are normalized to standard names (e.g.,
TIT2→title). - Strict whitespace handling: All values are stripped of leading/trailing whitespace. Empty or whitespace-only values are dropped.
- Empty field representation: If a field exists but all values are empty after stripping, it returns
[''](a list with a single empty string). - Deduplication: All field values are deduplicated case-insensitively, and identical frames are merged.
- Canonical fields: Written to format-specific native tags.
- Strict whitespace handling: Values are stripped; empty strings are dropped from lists.
- Smart empty: A single
[''](e.g. fromclear()) is preserved and written, allowing explicit "empty" tags. - Deletion: Writing
[](empty list) deletes the field entirely. - All fields are multi-valued: All unique values are written.
- Custom fields: Keys are sanitized to caps snake case (e.g.,
MY_CUSTOM_FIELD).
Example - Custom Field Writing:
# Writing with various custom key formats
sm.write_fields({
'my-custom-field': ['value1'], # Written as: MY_CUSTOM_FIELD
'AnotherField': ['value2'], # Written as: ANOTHERFIELD
})The following canonical fields are recognized by mudio across all audio formats:
title · artist · album · albumartist · genre · comment · composer · performer · date · track · totaltracks · disc · totaldiscs
Note: All field names are case-insensitive. Common variations (e.g., album_artist, tracknumber, discnumber) are automatically mapped to their canonical form.
- Mutagen is the low-level library that
mudiouses. It is powerful but requires learning different APIs for ID3, Vorbis, and MP4 tags. - mudio abstracts these differences. Use
mudioif you want a simple, unified API (e.g.sm.write_fields({'title': ...})works on everything). Usemutagenif you need byte-level control or support for obscure frame types.
- music_tag is a library primarily for Python scripts, offering a dictionary-like interface. It is excellent for simple script usage.
- mudio offers similar library features but includes a robust CLI for batch processing, filtering, and safety operations (backups, dry-runs) out of the box.
- Beets is a complete library manager with a centralized database, autotagger, and plugin system. It implies a workflow where it "owns" your library.
- mudio is a stateless tool. It modifies files directly without a database. Use
mudiofor quick fixes, batch scripting, or if you prefer managing your file structure manually.
- MusicBrainz Picard is a GUI application focused on matching files to the MusicBrainz database.
- mudio is a CLI/Library tool. It's better for automation, headless servers, or mass-editing tags based on patterns rather than database matching.
- EyeD3 is excellent but specific to MP3/ID3.
- mudio supports FLAC, M4A, OGG, and more with the same commands.
# Install dependencies
pip install -e ".[dev]"
# Run tests
pytest