github beetbox/beets v2.6.0
Release v2.6.0

7 hours ago

Beets now requires Python 3.10 or later since support for EOL Python 3.9 has been dropped.

New features

  • Added support for Python 3.13.
  • Convert Plugin: force can be passed to override checks like no_convert, never_convert_lossy_files, same format, and max_bitrate
  • Discogs Plugin: Added support for multi value fields. 🐛 (#6068)
  • EmbedArt Plugin: Embedded arts can now be cleared during import with the clearart_on_import config option. Also, beet clearart is only going to update the files matching the query and with an embedded art, leaving untouched the files without.
  • FetchArt Plugin: Added config setting for a fallback cover art image.
  • FetchArt Plugin: Fix colorized output text.
  • Fish Plugin: Filenames are now completed in more places, like after import.
  • FtInTitle Plugin: Added album template value album_artist_no_feat.
  • FtInTitle Plugin: Added argument for custom feat. words in ftintitle.
  • FtInTitle Plugin: Added argument to skip the processing of artist and album artist are the same in ftintitle.
  • FtInTitle Plugin: Featured artists are now inserted before brackets containing remix/edit-related keywords (e.g., "Remix", "Live", "Edit") instead of being appended at the end. This improves formatting for titles like "Song 1 (Carol Remix) ft. Bob" which becomes "Song 1 ft. Bob (Carol Remix)". A variety of brackets are supported and a new bracket_keywords configuration option allows customizing the keywords. Setting bracket_keywords to an empty list matches any bracket content regardless of keywords.
  • ImportSource Plugin: Added new plugin that tracks original import paths and optionally suggests removing source files when items are removed from the library.
  • LastGenre Plugin: For tuning plugin settings -vvv can be passed to receive extra verbose logging around last.fm results and how they are resolved. The extended_debug config setting and --debug option have been removed.
  • MusicBrainz Plugin: Allow selecting tags or genres to populate the genres tag.
  • MusicBrainz Pseudo-Release Plugin: Add a new MusicBrainz Pseudo-Release Plugin plugin to proactively receive MusicBrainz pseudo-releases as recommendations during import.
  • Play Plugin: Added $playlist marker to precisely edit the playlist filepath into the command calling the player program.
  • Random Plugin: Added --field option to specify which field to use for equal-chance sampling (default: albumartist).
  • Spotify Plugin: Added support for multi-artist albums and tracks, saving all contributing artists to the respective fields.
  • Titlecase Plugin: Add the Titlecase Plugin plugin to allow users to resolve differences in metadata source styles.

Bug fixes

  • Errors in metadata plugins during autotage process will now be logged but won't crash beets anymore. If you want to raise exceptions instead, set the new configuration option raise_on_error to yes 🐛 (#5903), 🐛 (#4789).
  • Fix a bug introduced in release 2.4.0 where import from any valid import-log-file always threw a "none of the paths are importable" error.
  • Handle potential OSError when unlinking temporary files in ArtResizer. 🐛 (#5615)
  • Running beet --config <mypath> config -e now edits <mypath> rather than the default config path. 🐛 (#5652)
  • Sanitize log messages by removing control characters preventing terminal rendering issues.
  • When hardlinking from a symlink (e.g. importing a symlink with hardlinking enabled), dereference the symlink then hardlink, rather than creating a new (potentially broken) symlink 🐛 (#5676)
  • When using FromFilename Plugin together with Edit Plugin, temporary tags extracted from filenames are no longer lost when discarding or cancelling an edit session during import. 🐛 (#6104)
  • Command-Line Interface: Fix 'from_scratch' option for singleton imports: delete all (old) metadata when new metadata is applied. 🐛 (#3706)
  • Convert Plugin: auto_keep now respects no_convert and never_convert_lossy_files when deciding whether to copy/transcode items, avoiding extra lossy duplicates.
  • Discogs Plugin: Fixed unexpected flex attr from the Discogs plugin. 🐛 (#6177)
  • FtInTitle Plugin: Fixed artist name splitting to prioritize explicit featuring tokens (feat, ft, featuring) over generic separators (&, and), preventing incorrect splits when both are present.
  • Inline Plugin: Fix recursion error when an inline field definition shadows a built-in item field (e.g., redefining track_no). Inline expressions now skip self-references during evaluation to avoid infinite recursion. 🐛 (#6115)
  • LastGenre Plugin: Canonicalize genres when force and keep_existing are on, yet no genre info on lastfm could be found. 🐛 (#6303)
  • LastGenre Plugin: Fix the issue where last.fm doesn't return any result in the artist genre stage because "concatenation" words in the artist name (like "feat.", "+", or "&") prevent it. Using the albumartists list field and fetching a genre for each artist separately improves the chance of receiving valid results in that stage.
  • Lyrics Plugin: Accepts strings for lyrics sources (previously only accepted a list of strings). 🐛 (#5962)
  • Smart Playlist Plugin: Fixed an issue where multiple queries in a playlist configuration were not preserving their order, causing items to appear in database order rather than the order specified in the config. 🐛 (#6183)
  • Spotify Plugin: The plugin now gracefully handles audio-features API deprecation (HTTP 403 errors). When a 403 error is encountered from the audio-features endpoint, the plugin logs a warning once and skips audio features for all remaining tracks in the session, avoiding unnecessary API calls and rate limit exhaustion.
  • Spotify Plugin: Updated Spotify API credentials. 🐛 (#6270)
  • Web Plugin: repair broken /item/values/… and /albums/values/… endpoints. Previously, due to single-quotes (ie. string literal) in the SQL query, the query eg. GET /item/values/albumartist would return the literal "albumartist" instead of a list of unique album artists.
  • update Edit Plugin fix display formatting of field changes to clearly show added and removed flexible fields.

For plugin developers

For packagers

  • An unused dependency on mock has been removed.
  • The minimum supported Python version is now 3.10.

Other changes

  • Finally removed gmusic plugin and all related code/docs as the Google Play Music service was shut down in 2020.
  • Moved beets/random.py into beetsplug/random.py to cleanup core module.
  • Refactored the beets/ui/commands.py monolithic file (2000+ lines) into multiple modules within the beets/ui/commands directory for better maintainability.
  • The documentation chapter Handling Paths has been moved to the "For Developers" section and revised to reflect current best practices (pathlib usage).
  • Updated color documentation with bright_* and bg_bright_* entries.
  • BPD Plugin: Raise ImportError instead of ValueError when GStreamer is unavailable, enabling importorskip usage in pytest setup.
  • dbcore: Allow models to declare SQL indices; add an items.album_id index to speed up album.items() queries. 🐛 (#5809)

Don't miss a new beets release

NewReleases is sending notifications on new releases.