music library manager and MusicBrainz tagger
This release is our first experiment with time-based releases! We are aiming to publish a new release of beets every 3 months. We therefore have a healthy but not dizzyingly long list of new features and fixes.
With this release, beets now requires Python 3.6 or later (it removes support for Python 2.7, 3.4, and 3.5). There are also a few other dependency changes---if you're a maintainer of a beets package for a package manager, thank you for your ongoing efforts, and please see the list of notes below.
Major new features:
albumtypes
field. Thanks to edgars-supe
{.interpreted-text role="user"}. #2200albumtypes
includes some options for formatting this new albumtypes
field. Thanks to edgars-supe
{.interpreted-text role="user"}.Other new things:
permissions
: The plugin now sets cover art permissions to match the audio file permissions.unimported
: A new configuration option supports excluding specific subdirectories in library.info
: Add support for an --album
flag.export
: Similarly add support for an --album
flag.beet move
now highlights path differences in color (when enabled).fetchart
: Add a new option to store cover art as non-progressive image. This is useful for DAPs that do not support progressive images. Set deinterlace: yes
in your configuration to enable this conversion.fetchart
: Add a new option to change the file format of cover art images. This may also be useful for DAPs that only support some image formats.%aunique
. #2678 #3553%aunique
faster, especially when using inline fields. #4145Bug fixes:
lyrics
: Fix a crash when Beautiful Soup is not installed. #4027discogs
: Support a new Discogs URL format for IDs. #4080discogs
: Remove built-in rate-limiting because the Discogs Python library we use now has its own rate-limiting. :bug: 4108
export
: Fix some duplicated output.aura
: Fix a potential security hole when serving image files. #4160For plugin developers:
beets.library.Item.destination
{.interpreted-text role="meth"} now accepts a replacements
argument to be used in favor of the default.pluginload
event is now sent after plugin types and queries are available, not before.album_removed
, is called when an album is removed from the library (even when its file is not deleted from disk).Here are some notes for packagers:
test_album_art
in the test_zero.py
file, that some distributions had disabled. Disabling this test should no longer be necessary. #4037 #4038gmusic
plugin was removed since Google Play Music has been shut down. Thus, the optional dependency on gmusicapi
does not exist anymore. #4089This long overdue release of beets includes far too many exciting and useful features than could ever be satisfactorily enumerated. As a technical detail, it also introduces two new external libraries: MediaFile and Confuse used to be part of beets but are now reusable dependencies---packagers, please take note. Finally, this is the last version of beets where we intend to support Python 2.x and 3.5; future releases will soon require Python 3.6.
One non-technical change is that we moved our official #beets
home on IRC from freenode to Libera.Chat.
Major new features:
beet list foo:bar
will not only find tracks with the foo
attribute; it will also find tracks on albums that have the foo
attribute. This may be particularly useful in the path-format-config`, which matches individual items to decide which path to use. Thanks to @FichteFoll. #2797 #2988reflink
config option instructs the importer to create fast, copy-on-write file clones on filesystems that support them. Thanks to @rubdos.unimported
lets you find untracked files in your library directory.aura
has arrived! Try out the future of remote music library access today.work
(the title), mb_workid
(the MBID), and work_disambig
(the disambiguation string). Thanks to @dosoe. #2580 #3272parentwork
gets information about the original work, which is useful for classical music. Thanks to @dosoe. #2580 #3279bpd
: BPD now supports most of the features of version 0.16 of the MPD protocol. This is enough to get it talking to more complicated clients like ncmpcpp, but there are still some incompatibilities, largely due to MPD commands we don't support yet. (Let us know if you find an MPD client that doesn't get along with BPD!) #3214 #800deezer
can autotag tracks and albums using the Deezer database. Thanks to @rhlahuja. #3355bareasc
provides a new query type: "bare ASCII" queries that ignore accented characters, treating them as though they were plain ASCII characters. Use the #
prefix with list
or other commands. #3882fetchart
: The plugin can now get album art from last.fm. #3530web
: The API now supports the HTTP DELETE
and PATCH
methods for modifying items. They are disabled by default; set readonly: no
in your configuration file to enable modification via the API. #3870Other new things:
beet remove
now also allows interactive selection of items from the query, similar to beet modify
.https
for custom servers. See musicbrainz-config
for more details.mpdstats
: Add a new strip_path
option to help build the right local path from MPD information.convert
: Conversion can now parallelize conversion jobs on Python 3.lastgenre
: Add a new title_case
config option to make title-case formatting optional.beet config
when there's no available configuration file. #3779chroma
: The plugin now updates file metadata after generating fingerprints through the submit
command.lastgenre
: Added more heavy metal genres to the built-in genre filter lists.subsonicplaylist
can import playlists from a Subsonic server.subsonicupdate
: The plugin now automatically chooses between token- and password-based authentication based on the server version.extra_tags
configuration option lets you use more metadata in MusicBrainz queries to further narrow the search.fish
adds Fish shell tab autocompletion to beets.plugins/fetchart
and plugins/embedart
: Added a new quality
option that controls the quality of the image output when the image is resized.plugins/keyfinder
: Added support for keyfinder-cli. Thanks to @BrainDamage.plugins/fetchart
: Added a new high_resolution
config option to allow downloading of higher resolution iTunes artwork (at the expense of file size). #3391plugins/discogs
: The plugin applies two new fields: discogs_labelid
and discogs_artistid
. #3413export
: Added a new -f
(--format
) flag, which can export your data as JSON, JSON lines, CSV, or XML. Thanks to @austinmm. #3402convert
: Added a new -l
(--link
) flag and link
option as well as the -H
(--hardlink
) flag and hardlink
option, which symlink or hardlink files that do not need to be converted (instead of copying them). #2324replaygain
: The plugin now supports a per_disc
option that enables calculation of album ReplayGain on disc level instead of album level. Thanks to @samuelnilsson. #293replaygain
: The new ffmpeg
ReplayGain backend supports R128_
tags. #3056plugins/replaygain
: A new r128_targetlevel
configuration option defines the reference volume for files using R128_
tags. targetlevel
only configures the reference volume for REPLAYGAIN_
files. #3065discogs
: The plugin now collects the "style" field. Thanks to @thedevilisinthedetails. #2579 #3251absubmit
: By default, the plugin now avoids re-analyzing files that already have AcousticBrainz data. There are new force
and pretend
options to help control this new behavior. Thanks to @SusannaMaria. #3318discogs
: The plugin now also gets genre information and a new discogs_albumid
field from the Discogs API. Thanks to @thedevilisinthedetails. #465 #3322acousticbrainz
: The plugin now fetches two more additional fields: moods_mirex
and timbre
. Thanks to @malcops. #2860playlist
and smartplaylist
: A new forward_slash
config option facilitates compatibility with MPD on Windows. Thanks to @MartyLake. #3331 #3334data_source
field, which indicates which metadata source was used during an autotagging import, is now also applied as an album-level flexible attribute. #3350 #1693beatport
: The plugin now gets the musical key, BPM, and genre for each track. #2080bpsync
can synchronize metadata changes from the Beatport database (like the existing mbsync
for MusicBrainz).hook
: The plugin now treats non-zero exit codes as errors. #3409subsonicupdate
: A new url
configuration replaces the older (and now deprecated) separate host
, port
, and contextpath
config options. As a consequence, the plugin can now talk to Subsonic over HTTPS. Thanks to @jef. #3449discogs
: The new index_tracks
option enables incorporation of work names and intra-work divisions into imported track titles. Thanks to cole-miller
. #3459web
: The query API now interprets backslashes as path separators to support path queries. Thanks to @nmeum. #3567beet import
now handles tar archives with bzip2 or gzip compression. #3606beet import
also now handles 7z archives, via the py7zr library. Thanks to @arogl. #3906plexupdate
: Added an option to use a secure connection to Plex server, and to ignore certificate validation errors if necessary. #2871convert
: A new delete_originals
configuration option can delete the source files after conversion during import. Thanks to logan-arens
. #2947--plugins
(or -p
) CLI flag to specify a list of plugins to load.genres
option fetches genre information from MusicBrainz. This functionality depends on functionality that is currently unreleased in the python-musicbrainzngs library: see PR #266 _. Thanks to :user:
aereaux`.replaygain
: Analysis now happens in parallel using the command
and ffmpeg
backends. #3478plugins/replaygain
: The bs1770gain backend is removed. Thanks to @SamuelCook.trackdisambig
which stores the recording disambiguation from MusicBrainz for each track. #1904plugins/fetchart
: The new max_filesize
configuration sets a maximum target image file size.badfiles
: Checkers can now run during import with the check_on_import
config option.export
: The plugin is now much faster when using the --include-keys
option is used. Thanks to @ssssam.metasync
: The plugin now also fetches the "Date Added" field from iTunes databases and stores it in the itunes_dateadded
field. Thanks to @sandersantema.lyrics
: Added a new Tekstowo.pl lyrics provider. Thanks to various people for the implementation and for reporting issues with the initial version. #3344 #3904 #3905 #3994beet update
will now confirm that the user still wants to update if their library folder cannot be found, preventing the user from accidentally wiping out their beets database. Thanks to user: logan-arens
. #1934Fixes:
ast
module in Python 3.8.beatport
: Fix the assignment of the genre
field, and rename musical_key
to initial_key
. #3387lyrics
: Fixed the Musixmatch backend for lyrics pages when lyrics are divided into multiple elements on the webpage, and when the lyrics are missing.web
: Allow use of the backslash character in regex queries. #3867web
: Fixed a small bug that caused the album art path to be redacted even when include_paths
option is set. #3866discogs
: Fixed a bug with the index_tracks
option that sometimes caused the index to be discarded. Also, remove the extra semicolon that was added when there is no index track.subsonicupdate
: The API client was using the POST
method rather the GET
method. Also includes better exception handling, response parsing, and tests.the
: Fixed incorrect regex for "the" that matched any 3-letter combination of the letters t, h, e. #3701fetchart
: Fixed a bug that caused the plugin to not take environment variables, such as proxy servers, into account when making requests. #3450fetchart
: Temporary files for fetched album art that fail validation are now removed.inline
: In function-style field definitions that refer to flexible attributes, values could stick around from one function invocation to the next. This meant that, when displaying a list of objects, later objects could seem to reuse values from earlier objects when they were missing a value for a given field. These values are now properly undefined. #2406bpd
: Seeking by fractions of a second now works as intended, fixing crashes in MPD clients like mpDris2 on seek. The playlistid
command now works properly in its zero-argument form. #3214replaygain
: Fix a Python 3 incompatibility in the Python Audio Tools backend. #3305importadded
: Fixed a crash that occurred when the after_write
signal was emitted. #3301plugins/replaygain
: Fix the storage format for R128 gain tags. #3311 #3314discogs
: Fixed a crash that occurred when the master URI isn't set in the API response. #2965 #3239spotify
: Fix handling of year-only release dates returned by the Spotify albums API. Thanks to @rhlahuja. #3343per_disc_numbering
option was set. #3346none_rec_action
does not import automatically when timid
is enabled. Thanks to @RollingStar. #3242beet import
now logs which files are ignored when in debug mode. #3764bpd
: Fix the transition to next track when in consume mode. Thanks to @aereaux. #3437lyrics
: Fix a corner-case with Genius lowercase artist names #3446parentwork
: Don't save tracks when nothing has changed. #3492include
directive of the configuration file fail to be imported. #3498bpm
would sometimes store non-integer values. #762 #3507 #3508lyrics
: Tolerate a missing lyrics div in the Genius scraper. Thanks to @thejli21. #3535 #3554lyrics
: Use the artist sort name to search for lyrics, which can help find matches when the artist name has special characters. Thanks to @hashhar. #3340 #3558replaygain
: Trying to calculate volume gain for an album consisting of some formats using ReplayGain
and some using R128
will no longer crash; instead it is skipped and and a message is logged. The log message has also been rewritten for to improve clarity. Thanks to @autrimpo. #3533lyrics
: Adapt the Genius backend to changes in markup to reduce the scraping failure rate. #3535 #3594lyrics
: Fix a crash when writing ReST files for a query without results or fetched lyrics. #2805fetchart
: Attempt to fetch pre-resized thumbnails from Cover Art Archive if the maxwidth
option matches one of the sizes supported by the Cover Art Archive API. Thanks to @trolley. #3637ipfs
: Fix Python 3 compatibility. Thanks to @musoke. #2554mpdstats
: Don't record a skip when stopping MPD, as MPD keeps the current track in the queue. Thanks to @aereaux. #3722fetchart
and the discogs
together. #3773 #3774plugins/keyfinder
: Catch output from keyfinder-cli
that is missing key. #2242plugins/replaygain
: Disable parallel analysis on import by default. #3819mpdstats
: Fix Python 2/3 compatibility #3798discogs
: Replace the deprecated official discogs-client
library with the community supported python3-discogs-client library. #3608chroma
: Fixed submitting AcoustID information for tracks that already have a fingerprint. #3834--set
option to the beet import
command. #2984%ifdef
now produce the expected behavior when used in conjunction with non-string fields from the types
. #3852lyrics
: Fix crashes when a website could not be retrieved, affecting at least the Genius source. #3970duplicates
: Fix a crash when running the dup
command with a query that returns no results. #3943beatport
: Fix the default assignment of the musical key. #3377lyrics
: Improved searching on the Genius backend when the artist contains special characters. #3634parentwork
: Also get the composition date of the parent work, instead of just the child work. Thanks to @aereaux. #3650lyrics
: Fix a bug in the heuristic for detecting valid lyrics in the Google source. #2969thumbnails
: Fix a crash due to an incorrect string type on Python 3. #3360fetchart
: The Cover Art Archive source now iterates over all front images instead of blindly selecting the first one.lyrics
: Removed the LyricWiki source (the site shut down on 21/09/2020).subsonicupdate
: The plugin is now functional again. A new auth
configuration option is required in the configuration to specify the flavor of authentication to use. #4002For plugin developers:
from beets import mediafile
, now just do import mediafile
. Beets re-exports MediaFile at the old location for backwards-compatibility, but a deprecation warning is raised if you do this since we might drop this wrapper in a future release.from beets.util import confit
, now just do import confuse
. The code is almost identical apart from the name change. Again, we'll re-export at the old location (with a deprecation warning) for backwards compatibility, but we might stop doing this in a future release.beets.util.command_output
now returns a named tuple containing both the standard output and the standard error data instead of just stdout alone. Client code will need to access the stdout
attribute on the return value. Thanks to @zsinskri. #3329test.test_player
. Hopefully these are fixed. If they resurface, please reopen the relevant issue. #3309 #3330beets.plugins.MetadataSourcePlugin
base class has been added to simplify development of plugins which query album, track, and search APIs to provide metadata matches for the importer. Refer to the spotify
and the deezer
for examples of using this template class. #3355Item
now falls back to the album's attributes. So, for example, item.foo
will first look for a field foo
on item
and, if it doesn't exist, next tries looking for a field named foo
on the album that contains item
. If you specifically want to access an item's attributes, use Item.get(key, with_album=False)
. #2988Item.keys
also has a with_album
argument now, defaulting to True
.revision
attribute has been added to Database
. It is increased on every transaction that mutates it. #2988AlbumInfo
and TrackInfo
now convey arbitrary attributes instead of a fixed, built-in set of field names (which was important to address #1547). Thanks to @dosoe.mb_album_extract
and mb_track_extract
, let plugins add new fields based on MusicBrainz data. Thanks to @dosoe.For packagers:
mediafile
. Beets now depends on this new package. Beets now depends on Mutagen transitively through MediaFile rather than directly, except in the case of one of beets' plugins (in particular, the scrub
).confuse
. Beets now depends on this package. Confuse has existed separately for some time and is used by unrelated projects, but until now we've been bundling a copy within beets.This small update is part of our attempt to release new versions more often! There are a few important fixes, and we're clearing the deck for a change to beets' dependencies in the next version.
The new feature is:
There are some fixes in this release:
gmusic
: The oauth_file
config option now supports more flexible path values, including ~
for the home directory. #3270gmusic
: Fix a crash when using version 12.0.0 or later of the gmusicapi
module. #3270Here's a note for packagers:
pathlib
is now an optional test dependency on Python 3.4+, removing the need for a Debian patch. #3275This release is far too long in coming, but it's a good one. There is the usual torrent of new features and a ridiculously long line of fixes, but there are also some crucial maintenance changes. We officially support Python 3.7 and 3.8, and some performance optimizations can (anecdotally) make listing your library more than three times faster than in the previous version.
The new core features are:
config-aunique
configuration option allows setting default options for the aunique
template function.albumdisambig
field no longer includes the MusicBrainz release group disambiguation comment. A new releasegroupdisambig
field has been added. #3024modify
command now allows resetting fixed attributes. For example, beet modify -a artist:beatles artpath!
resets artpath
attribute from matching albums back to the default value. #2497ignore_data_tracks
, lets you skip audio tracks contained in data files. #3021There are some new plugins:
playlist
can query the beets library using M3U playlists. Thanks to @Holzhaus and @Xenopathic. #123 #3145loadext
allows loading of SQLite extensions, primarily for use with the ICU SQLite extension for internationalization. #3160 #3226subsonicupdate
can automatically update your Subsonic library. Thanks to @maffo999. #3001And many improvements to existing plugins:
lastgenre
: Added option -A
to match individual tracks and singletons. #3220 #3219play
: The plugin can now emit a UTF-8 BOM, fixing some issues with foobar2000 and Winamp. Thanks to @mz2212. #2944gmusic
:
replaygain
: albumpeak
on large collections is calculated as the average, not the maximum. #3008 #3009chroma
:
preferred
configuration options. Thanks to @archer4499. #3017beet write
. Thanks to @Holzhaus. #3097 #2942convert
: The plugin now has an id3v23
option that allows you to override the global id3v23
option. Thanks to @Holzhaus. #3104spotify
:
ipfs
: The plugin now supports a nocopy
option which passes that flag to ipfs. Thanks to @wildthyme.discogs
: The plugin now has rate limiting for the Discogs API. #3081mpdstats
, mpdupdate
: These plugins now use the MPD_PORT
environment variable if no port is specified in the configuration file. #3223bpd
:
consume
and single
are now supported along with updated semantics for repeat
and previous
and new fields for status
. The bpd server now understands and ignores some additional commands. #3200 #800idle
is now supported, allowing the MPD version to be bumped to 0.14. #3205 #800decoders
is now supported. #3222--debug
flag has been removed. Thanks to @arcresu. #3196mbsync
: The plugin no longer queries MusicBrainz when either the mb_albumid
or mb_trackid
field is invalid. See also the discussion on Google Groups Thanks to @arogl.export
: The plugin now also exports path
field if the user explicitly specifies it with -i
parameter. This only works when exporting library fields. #3084acousticbrainz
: The plugin now declares types for all its fields, which enables easier querying and avoids a problem where very small numbers would be stored as strings. Thanks to @rain0r. #2790 #3238Some improvements have been focused on improving beets' performance:
absubmit
, badfiles
: Analysis now works in parallel (on Python 3 only). Thanks to @bemeurer. #2442 #3003mpdstats
: Use the currentsong
MPD command instead of playlist
to get the current song, improving performance when the playlist is long. Thanks to @ray66. #3207 #2752Several improvements are related to usability:
move
command now lists the number of items already in-place. Thanks to @RollingStar. #3117convert
plugin copies the art covers. #3063Many fixes have been focused on issues where beets would previously crash:
fetchart
: Added network connection error handling to backends so that beets won't crash if a request fails. Thanks to @Holzhaus. #1579badfiles
: Avoid a crash when the underlying tool emits undecodable output. #3165beatport
: Avoid a crash when the server produces an error. #3184bpd
: Fix crashes in the bpd server during exception handling. #3200bpd
: Fix a crash triggered when certain clients tried to list the albums belonging to a particular artist. #3007 #3215replaygain
: Avoid a crash when the bs1770gain
tool emits malformed XML. #2983 #3247There are many fixes related to compatibility with our dependencies including addressing changes interfaces:
jellyfish
requirement to version 0.6.0 for compatibility.re
module. #2978web
: Fix an error when using more recent versions of Flask with CORS enabled. Thanks to @rveachkc. #2979: #2980python-itunes
, which had gone unmaintained and was not Python-3-compatible. Thanks to @ocelma for creating python-itunes
in the first place. Thanks to @nathdwek. #2371 #2551 #2718lastgenre
, edit
: Avoid a deprecation warnings from the PyYAML
library by switching to the safe loader. Thanks to @translit and @sbraz. #3192 #3225PIL
/pillow
on Python 3. Thanks to @architek. #2504 #3029And there are many other fixes:
artist_credit
configuration option is set. #2953from_scratch
configuration option set, only writable fields are cleared. Beets now no longer ignores the format your music is saved in. #2972%aunique
template function now works correctly with the -f/--format
option. #3043%title
template function now works correctly with apostrophes. Thanks to @GuilhermeHideki. #3033lastgenre
: It's now possible to set the prefer_specific
option without also setting canonical
. #2973fetchart
: The plugin now respects the ignore
and ignore_hidden
settings. #1632hook
: Fix byte string interpolation in hook commands. #2967 #3167the
: Log a message when something has changed, not when it hasn't. Thanks to @arcresu. #3195lastgenre
: The force
config option now actually works. #2704 #3054convert
command that is not ImageMagick's by using the magick
executable when it is available. Thanks to @ababyduck. #2093 #3236There is one new thing for plugin developers to know about:
playlist
supports queries like playlist:name
although there is no field named playlist
. See extend-query
for details.And some messages for packagers:
jellyfish
and munkres
.python-itunes
dependency has been removed.This new release includes lots of new features in the importer and the metadata source backends that it uses. We've changed how the beets importer handles non-audio tracks listed in metadata sources like MusicBrainz:
There are other subtle improvements to metadata handling in the importer:
musicbrainz_releasetrackid
field. This is a first step toward #406. Thanks to @Rawrmonkeys.And there are even more new features:
replaygain
: The beet replaygain
command now has --force
, --write
and --nowrite
options. #2778fetchart
: The configuration options now support finer-grained control via the sources
option. You can now specify the search order for different matching strategies within different backends.web
: A new cors_supports_credentials
configuration option lets in-browser clients communicate with the server even when it is protected by an authorization mechanism (a proxy with HTTP authentication enabled, for example).sonosupdate
plugin automatically notifies Sonos controllers to update the music library when the beets library changes. Thanks to @cgtobi.discogs
: The plugin now stores master release IDs into mb_releasegroupid
. It also "simulates" track IDs using the release ID and the track list position. Thanks to @dbogdanov. #2336discogs
: Fetch the original year from master releases. #1122There are lots and lots of fixes:
replaygain
: Fix a corner-case with the bs1770gain
backend where ReplayGain values were assigned to the wrong files. The plugin now requires version 0.4.6 or later of the bs1770gain
tool. #2777lyrics
: The plugin no longer crashes in the Genius source when BeautifulSoup is not found. Instead, it just logs a message and disables the source. #2911lyrics
: Handle network and API errors when communicating with Genius. #2771lyrics
: The lyrics
command previously wrote ReST files by default, even when you didn't ask for them. This default has been fixed.lyrics
: When writing ReST files, the lyrics
command now groups lyrics by the albumartist
field, rather than artist
. #2924edit
provides show up more reliably after doing a secondary import search. #2441 #2731importadded
: Fix a crash on non-autotagged imports. Thanks to @m42i. #2601 #1918plexupdate
: The Plex token is now redacted in configuration output. Thanks to @Kovrinic. #2804convert
: The plugin now runs before other plugin-provided import stages, which addresses an issue with generating ReplayGain data incompatible between the source and target file formats. Thanks to @autrimpo. #2814ftintitle
: The drop
config option had no effect; it now does what it says it should do. #2817web
: The time display in the web interface would incorrectly jump at the 30-second mark of every minute. Now, it correctly changes over at zero seconds. #2822web
: Fetching album art now works (instead of throwing an exception) under Python 3. Additionally, the server will now return a 404 response when the album ID is unknown (instead of throwing an exception and producing a 500 response). #2823web
: Fix an exception on Python 3 for filenames with non-Latin1 characters. (These characters are now converted to their ASCII equivalents.) #2815replaygain
: Really fix album gain calculation using the GStreamer backend. #2846discogs
: Fix the medium
and medium_index
values, which were occasionally incorrect for releases with two-sided mediums such as vinyl. Also fix the medium_total
value, which now contains total number of tracks on the medium to which a track belongs, not the total number of different mediums present on the release. Thanks to @dbogdanov. #2887keyfinder
: Avoid a crash when trying to process unmatched tracks. #2537mbsync
: Support MusicBrainz recording ID changes, relying on release track IDs instead. Thanks to @jdetrey. #1234mbsync
: We can now successfully update albums even when the first track has a missing MusicBrainz recording ID. #2920There are a couple of changes for developers:
early_import_stages
list instead of plain import_stages
to request this behavior. #2814albuminfo_received
and trackinfo_received
in all cases, most notably when using the mbsync
plugin. This was a regression since version 1.4.1. #2921The highlight of this release is "album merging," an oft-requested option in the importer to add new tracks to an existing album you already have in your library. This way, you no longer need to resort to removing the partial album from your library, combining the files manually, and importing again.
Here are the larger new features in this release:
lyrics
: The plugin can now produce reStructuredText files for beautiful, readable books of lyrics. Thanks to @anarcat. #2628from_scratch
configuration option makes the importer remove old metadata before applying new metadata. This new feature complements the zero
and scrub
plugins but is slightly different: beets clears out all the old tags it knows about and only keeps the new data it gets from the remote metadata source. Thanks to @tummychow. #934 #2755There are also somewhat littler, but still great, new features:
convert
: A new no_convert
option lets you skip transcoding items matching a query. Instead, the files are just copied as-is. Thanks to @Stunner. #2732 #2751fetchart
: A new quiet switch that only prints out messages when album art is missing. Thanks to @euri10. #2683mbcollection
: You can configure a custom MusicBrainz collection via the new collection
configuration option. #2685mbcollection
: The collection update command can now remove albums from collections that are longer in the beets library.fetchart
: The clearart
command now asks for confirmation before touching your files. Thanks to @konman2. #2708 #2427mpdstats
: The plugin now correctly updates song statistics when MPD switches from a song to a stream and when it plays the same song multiple times consecutively. #2707acousticbrainz
: The plugin can now be configured to write only a specific list of tags. Thanks to @woparry.There are lots and lots of bug fixes:
hook
: Fixed a problem where accessing non-string properties of item
or album
(e.g., item.track
) would cause a crash. Thanks to @broddo. #2740play
: When relative_to
is set, the plugin correctly emits relative paths even when querying for albums rather than tracks. Thanks to @j000. #2702BrokenPipeError
being ignored. This was an issue when using beets in simple shell scripts. Thanks to @Azphreal. #2622 #2631replaygain
: Fix a regression in the previous release related to the new R128 tags. #2615 #2623lyrics
: The MusixMatch backend now detects and warns when the server has blocked the client. Thanks to @anarcat. #2634 #2632importfeeds
: Fix an error on Python 3 in certain configurations. Thanks to @djl. #2467 #2658edit
: Fix a bug when editing items during a re-import with the -L
flag. Previously, diffs against against unrelated items could be shown or beets could crash. #2659kodiupdate
: Fix the server URL and add better error reporting. #2662edit
plugin when saving the text file without making changes to some music. #2667chroma
: Fix a crash when running the submit
command on Python 3 on Windows with non-ASCII filenames. #2671absubmit
: Fix an occasional crash on Python 3 when the AB analysis tool produced non-ASCII metadata. #2673duplicates
: Use the default tiebreak for items or albums when the configuration only specifies a tiebreak for the other kind of entity. Thanks to @cgevans. #2758duplicates
: Fix the --key
command line option, which was ignored.replaygain
: Fix album ReplayGain calculation with the GStreamer backend. #2636scrub
: Handle errors when manipulating files using newer versions of Mutagen. #2716fetchart
: The plugin no longer gets skipped during import when the "Edit Candidates" option is used from the edit
plugin. #2734fromfilename
: Recognize file names that contain only a track number, such as 01.mp3
. Also, the plugin now allows underscores as a separator between fields. Thanks to @Vrihub. #2738 #2759maxwidth
config option in the fetchart
and embedart
plugins.There are some changes for developers:
None
sometimes instead of just showing up as an empty string. #2605beets.library
module and the manipulate_files
function in beets.importer
to use a single parameter describing the file operation instead of multiple Boolean flags. There is a new numerated type describing how to move, copy, or link files. #2682Version 1.4.5 adds some oft-requested features. When you're importing files, you can now manually set fields on the new music. Date queries have gotten much more powerful: you can write precise queries down to the second, and we now have relative queries like -1w
, which means one week ago.
Here are the new features:
--set field=value
command-line flag or a new set_fields
configuration option under the importer
section. Thanks to @bartkl. #1881 #2581added:-1w..
to match music added in the last week, for example. Thanks to @euri10. #2598gmusic
lets you interact with your Google Play Music library. Thanks to @tigranl. #2553 #2586replaygain
: We now keep R128 data in separate tags from classic ReplayGain data for formats that need it (namely, Ogg Opus). A new r128
configuration option enables this behavior for specific formats. Thanks to @autrimpo. #2557 #2560move
command gained a new --export
flag, which copies files to an external location without changing their paths in the library database. Thanks to @SpirosChadoulos. #435 #2510There are also some bug fixes:
lastgenre
: Fix a crash when using the prefer_specific
and canonical
options together. Thanks to @yacoob. #2459 #2583web
: Fix a crash on Windows under Python 2 when serving non-ASCII filenames. Thanks to @robot3498712. #2592 #2593metasync
: Fix a crash in the Amarok backend when filenames contain quotes. Thanks to @aranc23. #2595 #2596This release built up a longer-than-normal list of nifty new features. We now support DSF audio files and the importer can hard-link your files, for example.
Here's a full list of new features:
kodiupdate
lets you keep your Kodi library in sync with beets. Thanks to @Pauligrinder. #2411import
section enables a terminal bell when input is required. Thanks to @SpirosChadoulos. #2366 #2495composer_sort
, is now supported and fetched from MusicBrainz. Thanks to @dosoe. #2519 #2529discogs
now both provide a new attribute called track_alt
that stores more nuanced, possibly non-numeric track index data. For example, some vinyl or tape media will report the side of the record using a letter instead of a number in that field. #1831 #2363web
: Added a new endpoint, /item/path/foo
, which will return the item info for the file at the given path, or 404.web
: Added a new config option, include_paths
, which will cause paths to be included in item API responses if set to true.%aunique
template function for aunique now takes a third argument that specifies which brackets to use around the disambiguator value. The argument can be any two characters that represent the left and right brackets. It defaults to []
and can also be blank to turn off bracketing. #2397 #2399--move
or -m
option to the importer so that the files can be moved to the library instead of being copied or added "in place." #2252 #2429badfiles
: Added a --verbose
or -v
option. Results are now displayed only for corrupted files by default and for all the files when the verbose option is set. #1654 #2434embedart
: The explicit embedart
command now asks for confirmation before embedding art into music files. Thanks to
@Stunner. #1999python -m beets
. #2453smartplaylist
: Different playlist specifications that generate identically-named playlist files no longer conflict; instead, the resulting lists of tracks are concatenated. #2468missing
: A new mode lets you see missing albums from artists you have in your library. Thanks to @qlyoung. #2481web
: Add new reverse_proxy
config option to allow serving the web plugins under a reverse proxy.play
: A new -y
or --yes
parameter lets you skip the warning message if you enqueue more items than the warning threshold usually allows.convert
. Thanks to @jansol. #2488 #2524There are also quite a few fixes:
absubmit
: We no longer filter audio files for specific formats---we will attempt the submission process for all formats. #2471mpdupdate
: Fix Python 3 compatibility. #2381replaygain
: Fix Python 3 compatibility in the bs1770gain
backend. #2382bpd
: Report playback times as integers. #2394mpdstats
: Fix Python 3 compatibility. The plugin also now requires version 0.4.2 or later of the python-mpd2
library. #2405mpdstats
: Improve handling of MPD status queries.badfiles
: Fix Python 3 compatibility.badfiles
: The command no longer bails out if the validator command is not found or exits with an error. #2430 #2433lyrics
: The Google search backend no longer crashes when the server responds with an error. #2437discogs
: You can now authenticate with Discogs using a personal access token. #2447duplicates
: Fix Python 3 compatibility when using the copy
and move
options. #2444mbsubmit
: The tracks are now sorted properly. Thanks to
@awesomer. #2457thumbnails
: Fix a string-related crash on Python 3. #2466beatport
: More than just 10 songs are now fetched per album. #2469convert
: The default configuration uses FFmpeg's built-in AAC codec instead of faac. Thanks to @jansol. #2484web
: Avoid a crash when sending binary data, such as Chromaprint fingerprints, in music attributes. #2542 #2532We removed backends from two metadata plugins because of bitrot:
lyrics
: The Lyrics.com backend has been removed. (It stopped working because of changes to the site's URL structure.) #2548 #2549fetchart
: The documentation no longer recommends iTunes Store artwork lookup because the unmaintained python-itunes is broken. Want to adopt it? #2371 #1610Happy new year! This new version includes a cornucopia of new features from contributors, including new tags related to classical music and a new AcousticBrainz Submit plugin for performing acoustic analysis on your music. The Random plugin has a new mode that lets you generate time-limited music---for example, you might generate a random playlist that lasts the perfect length for your walk to work. We also access as many Web services as possible over secure connections now---HTTPS everywhere!
The most visible new features are:
absubmit
lets you run acoustic analysis software and upload the results for others to use. Thanks to @inytar. #2253 #2342play
: The plugin now provides an importer prompt choice to play the music you're about to import. Thanks to @diomekes. #2008 #2360random
: A new --time
option lets you generate a random playlist that takes a given amount of time. Thanks to @diomekes. #2305 #2322Some smaller new features:
zero
: A new zero
command manually triggers the zero plugin. Thanks to @SJoshBrown. #2274 #2329acousticbrainz
: The plugin will avoid re-downloading data for files that already have it by default. You can override this behavior using a new force
option. Thanks to @SusannaMaria. #2347 #2349bpm
: The import.write
configuration option now decides whether or not to write tracks after updating their BPM. #1992And the fixes:
bpd
: Fix a crash on non-ASCII MPD commands. #2332scrub
: Avoid a crash when files cannot be read or written. #2351scrub
: The image type values on scrubbed files are preserved instead of being reset to "other." #2339web
: Fix a crash on Python 3 when serving files from the filesystem. #2353discogs
: Improve the handling of releases that contain subtracks. #2318discogs
: Fix a crash when a release does not contain format information, and increase robustness when other fields are missing. #2302lyrics
: The plugin now reports a beets-specific User-Agent header when requesting lyrics. #2357embyupdate
: The plugin now checks whether an API key or a password is provided in the configuration.play
: The misspelled configuration option warning_treshold
is no longer supported.For plugin developers: when providing new importer prompt choices (see append_prompt_choices), you can now provide new candidates for the user to consider. For example, you might provide an alternative strategy for picking between the available alternatives or for looking up a release on MusicBrainz.
This is just a little bug fix release. With 1.4.2, we're also confident enough to recommend that anyone who's interested give Python 3 a try: bugs may still lurk, but we've deemed things safe enough for broad adoption. If you can, please install beets with pip3
instead of pip2
this time and let us know how it goes!
Here are the fixes:
badfiles
: Fix a crash on non-ASCII filenames. #2299%asciify{}
path formatting function and the asciify-paths setting properly substitute path separators generated by converting some Unicode characters, such as ½ and ¢, into ASCII.convert
: Fix a logging-related crash when filenames contain curly braces. Thanks to @kierdavis. #2323Also, we've removed some special handling for logging in the discogs
that we believe was unnecessary. If spurious log messages appear in this version, please let us know by filing a bug.