5.7 KiB
name, description, category
| name | description | category |
|---|---|---|
| music-library-management | Manage local music libraries — tag, rename, and organize files with beets and mutagen. Absorbed music-renamer (mutagen-based in-place rename workflow). | media |
Music Library Management
Tag, rename, and organize local music files. Covers beets (music library manager) for metadata-aware workflows and mutagen for fast bulk operations when files already have clean ID3 tags.
Triggers
- User wants to rename/tag/organize music files
- User asks about beets, mutagen, or music file metadata
- User has a collection of mp3/flac/m4a files that need cleanup
Prerequisites
Install beets (includes mutagen as a dependency):
pip install --break-system-packages beets
Config lives at ~/.config/beets/config.yaml.
Workflow Decision
Use beets when:
- Files need MusicBrainz tagging (missing or wrong metadata)
- You want to reorganize files into a standard Artist/Album/Track structure
- You need beets' query and library features long-term
- Small batch (<100 files) — even with MusicBrainz timeout, it's manageable
Use mutagen directly when:
- Files already have clean ID3 tags (artist, title, album present)
- Bulk renaming is the only goal (format change, not metadata enrichment)
- Large batch (100+ files) — beets import is too slow per-file
- In-place renaming (keep directory structure, just fix filenames)
Beets Workflow
Configuration (~/.config/beets/config.yaml)
directory: /path/to/music/root
library: /path/to/music/root/musiclibrary.db
import:
copy: no
move: no # no for import-only; yes when ready to reorganize
write: yes
quiet: yes # skip confirmation prompts
# Treat loose singles as a compilation
singletons:
album: Singles
albumartist: Various Artists
compilation: yes
paths:
singleton: %(artist)s - %(title)s
comp: Compilations/%(album)s/%(artist)s - %(title)s
default: %(albumartist)s/%(album)s/%(track)02d - %(title)s
Import files into the library
# Slow — hits MusicBrainz per file. Use -A (no autotag) if tags are already good.
beet import -A -q --singletons /path/to/music/dir/
Query and rename already-imported files
# Dry run: see what would change
beet ls -f '$path || $artist - $title' 'query'
# Actually rename (moves per path template in config)
beet move 'query'
For in-place renaming with beets, the path template must match the directory
structure. Beets always uses directory + path_template — it cannot rename
within arbitrary subdirectories without moving.
Mutagen Bulk Rename
When beets import is too slow and files already have ID3 tags, use the script at
scripts/bulk-rename.py. It walks a directory tree, reads artist/title from tags
via mutagen, and renames in-place to Artist - Title.ext.
Linked files
scripts/bulk-rename.py— Bulk in-place rename using mutagen ID3 tagsscripts/rename_by_tags.py— Alternative rename script (absorbed from music-renamer)
The script handles:
- Collisions (appends
(1),(2)to duplicates in the same directory) - Special characters (strips
/and null bytes) - Files already correctly named (skips)
Quick Rename Workflow (mutagen, absorbed from music-renamer)
For the specific use case of renaming files in-place using embedded ID3 tags
(files already have good tags, just need cleaner filenames), use the script at
scripts/rename_by_tags.py. It walks a directory tree, reads artist/title from
mutagen, and renames to Artist - Title.ext.
Trigger for this workflow
User asks to rename/organize music files, clean up filenames, strip number prefixes from downloaded music.
Step 1 — Determine scope
CRITICAL: Confirm which directories the user wants renamed. Never assume "all music."
Use find with a -regex pattern to count files with number prefixes:
find /path/to/music -type f -regex ".*/[0-9]+\. .*"
Files with number prefixes (e.g., 123. Title.mp3) are the unrenamed ones.
Step 2 — Run the rename script
Use scripts/rename_by_tags.py via execute_code. The script:
- Walks a base directory recursively
- Reads artist/title from ID3 tags via mutagen
- Renames files to
Artist - Title.extin-place (same directory) - Skips files already in the correct format
- Handles collisions by appending
(1),(2)etc. - Handles slashes in artist/title by replacing with
-
Step 3 — Verify
ls /path/to/music/some-folder/ | head -10
find /path/to/music -regex ".*/[0-9]+\. .*" | wc -l # should be 0
When to use mutagen vs beets
| Scenario | Tool |
|---|---|
| Files already have good ID3 tags, just need renaming | mutagen (scripts/rename_by_tags.py) |
| Files have NO tags, need to be matched against MusicBrainz | beets import (with autotag) |
| Small batch (< 50 files) needing autotag | beets import is fine |
| Large batch (> 100 files) | mutagen — beets import will time out |
User preferences
- Ray prefers mutagen over beets for bulk renaming
- Always confirm directory scope — don't expand beyond what was asked
Pitfalls
- Beets import is slow: Even with
-A(no autotag), beets still does per-file MusicBrainz lookups. Expect ~1-3 seconds per file. For 1000+ files, mutagen is the right choice. - Beets
movevs in-place:beet moverespectsdirectory + path_template. It cannot do truly in-place renames within arbitrary subdirectories. For in-place renames, use mutagen or a script as above. beet update: Updates metadata FROM files TO library — not the reverse. Does not update stored paths after external renames.- Config YAML quoting: Beets path templates use
%(var)ssyntax. The YAML linter may warn about unquoted%characters but beets parses them correctly.