
beets
Contributing back to the app and plugins that make managing a DJ's music collection possible at scale
- Goal
- Fix bugs and add features to my favorite music tagger
- My role
- Collaborator
- Status
- Active
- Started
- Python
- GitHub Actions
Beets is my favorite music tagger, and maintaining a DJ’s music collection gives me plenty of reasons to care about its behavior. Featured artists, compilations, and multiple versions of the same track make consistent metadata more than a cosmetic preference: it affects how I organize and find music. I started contributing because I wanted the fixes I needed to become part of the tools I already relied on, with less manual cleanup and fewer local workarounds to carry between upgrades.
This work spans Beets itself and two independently maintained plugins, beets-filetote and beets-beatport4. My contributions to Beets have concentrated on featured-artist handling and the reliability of external metadata sources. In the plugin repositories, I have worked on compatibility with newer Beets releases, adoption of its metadata-source interface, and safer configuration output. These are contributions to existing community projects, not applications I created; the scope is making the pieces of my music-management workflow continue to work together as their dependencies change.
The main areas covered by my merged pull requests are:
- Normalize featured-artist credits on compilations and guest-artist tracks, handle parenthesized credits, and place features before remix and version qualifiers.
- Keep featured-artist formatting consistent when refreshing metadata with
mbsync, as well as during imports and manual cleanup. - Restore TIDAL searches after an API change and recover from malformed Discogs search responses with a bounded retry.
- Keep Filetote compatible with changes to Beets’ path-format helpers and multidisc detection, while retaining support for older versions.
- Modernize Beatport4’s metadata-source integration, redact account credentials from configuration output, and align its Python requirements with Beets.
One implementation challenge was getting metadata cleanup to happen at the right point in the workflow. A correctly formatted title is not much help if a later metadata refresh reapplies the unnormalized version. I addressed that by connecting ftintitle to Beets’ metadata-received events, so incoming track and album information is normalized before mbsync applies it. The import path and manual command share the same rewriting logic, with tests covering artist credits, cached metadata properties, empty titles, and configurations that should leave the data alone. That makes the formatting part of the metadata flow instead of a separate correction that has to be repeated afterward.
Compatibility work has required a similar balance: adopt upstream changes without needlessly breaking installations that have not upgraded. For Filetote’s multidisc handling, I used the newer pattern collection when available and reconstructed it from the older constants otherwise, then extended the test matrix to cover the affected Beets versions. My Beatport4 work likewise moved beyond repairing changed imports to using the supported metadata-source interface. The common motivation is practical: keep the tools I use dependable, and contribute those improvements upstream so they can benefit other music collectors too.