Things I know about beets
published: 22 July 2026, tagged: music
god damn lucy I need you to just list everything you know about
beet. You keep saying things that make me go “whaaa what I wish I knew that before”
Sure thing! I’ve been using beets for a few years now to organise my music library, and I’ve picked up a few tricks along the way. In short, beets is a media library management system, which helps you catalogue your music collection and improve its metadata by drawing from databases like MusicBrainz and Discogs. I’m not going to cover the basics here though; for that, I’d recommend going straight to their getting started guide. These are a handful of slightly less common features that I find myself using :)
First, a note on enabling plugins, since I’m about to talk about a few of them. In order to enable a plugin, you can add that plugin’s name to the plugins option in your config.yaml file. You can find the location of your config file either by running beet config -p, or by checking the docs. Open your config file in your text editor, and add a section that looks like this:
plugins:
- fish
- replaygain
- fetchart
- convert
- missing
- duplicates
# whatever else you likefish completions
I use the fish shell, so I really like that beets comes with a plugin to easily get high-quality shell completions for fish. Enable the fish plugin, then run beet fish, and beets will create a file called ~/.config/fish/completions/beet.fish. You should now be able to tab-complete beets commands!
ReplayGain
ReplayGain is a standard for measuring and normalising the perceived loudness of audio tracks. If your music player supports ReplayGain, it can read the relative loudness of each track or album, and adjust the playback gain so that they all sound equally loud.
![]()
what did you mean by "track or album"?
When you’re playing back your music, you can choose whether you’d like every track to sound equally loud, or for gain to be applied equally to every track in an album. With the latter option, differences in perceived loudness between tracks in an album are preserved, but whole albums will be normalised relative to each other. Beets’ ReplayGain analysis will compute both, so you can usually choose which you’d like in your music player’s settings. Personally, I use album mode.
To generate ReplayGain metadata from beets, install beets[replaygain] and enable the replaygain plugin, and optionally choose an alternate backend. I use the ffmpeg backend, since it’s pretty quick and supports lots of audio formats. If you’d like to do that, make sure you have ffmpeg installed, and then add this to your configuration:
replaygain:
backend: ffmpeg
By default, the ReplayGain plugin will automatically analyse new tracks as you import them (which is a little slow, don’t worry if it looks like it’s hanging for a bit), but if you’d like to analyse your existing library, run beet replaygain and it’ll go through everything that isn’t already analysed.
For more details, I refer you to the docs.
fetching album art
I like seeing album art when I’m scrolling through my library! Sometimes you’ll get album art when you download an album, like when you get one from Bandcamp, but sometimes you’ll have to get it yourself. Mercifully, beets can automate the process of trawling the internet looking for album art. Install beets[fetchart] and enable the fetchart plugin, and then whenever you import an album, it’ll automatically search the internet for album art, and save it in the album’s folder as cover.jpg. Like the ReplayGain plugin, you can also add album art to your existing library by running beet fetchart, which will look for album art for any albums in your library that don’t already have it.
Some music players, such as iPods, don’t check for a cover.jpg file, so you’ll have to embed the album art into each audio file. Beets also has a plugin for this: install beets[embedart] and enable the embedart plugin (you’ll also need fetchart to get the images in the first place), and then beets will automatically embed images whenever fetchart gets a new cover.
Once again, for more details, see the docs pages for fetchart and embedart.
converting between formats
The beets convert plugin is a real multi-tool. You can use it to re-encode files in your library, replacing the old ones, or to automatically encode files as you import them. My favourite use, though, is to transcode lossless files to opus in order to save space on music players, while keeping the original lossless files in my library. It’s also useful if you’re using a music player which has limited codec support, like the stock firmware on an iPod, and you need to transcode your library in order to play it at all.
In order to do that, enable the convert plugin, and then add this to your configuration:
convert:
format: opus
never_convert_lossy_files: yes
Then, run beet convert --dest /mnt/media/your_music_player, changing the destination path to the mount point of your own music player. With the settings above, this will transcode any lossless files to opus, but leave lossy files untouched since converting from one lossy codec to another will always decrease quality without necessarily saving much space. If you’re using an iPod and need to convert everything to AAC, for example, then omit the never_convert_lossy_files option from your configuration and change the format to aac.
You can also include a query, in order to transcode only part of your library, but I’ll go into queries later on. Here’s the doc page for convert.
finding missing or duplicate tracks
Nice quick one: do you ever accidentally end up with tracks missing from your albums, or import something twice and end up with duplicates? Enable the missing and duplicates plugins, then you can run beet missing to see which of your albums are missing tracks, or beet duplicates to see duplicate tracks. Here are the docs for missing and duplicates.
querying and list formats
Pretty much any time you run a command in beets that acts on your library, you have the option to supply a query to limit which part of your library the command will act on. The simplest type of query is a keyword search: if I run beet ls gold, I see
David Bowie - Best of Bowie - Golden Years
Fleetwood Mac - Rumours - Gold Dust Woman
MARINA - FROOT - Gold
Panic! at the Disco - Death of a Bachelor - Golden Days
Periphery - Periphery III: Select Difficulty - Marigold
Lena Raine - Celeste Original Soundtrack - Golden
Sting - Ten Summoner’s Tales - Fields of Gold
...
Beets can also search query by specific fields: beet ls artist:green" will turn up Grant Green and Ted Greene, but not Eddi Reader’s Green Grow the Rashes O. I’ll not go through every query feature – the query docs do a good job of that already – but I do have some neat uses for it.
Let’s say we want to figure out the total length of an album. We can start off by getting all the tracks in the album we’re interested in, using the := syntax to search for exact matches, and quote marks to look for a whole phrase rather than a keyword:
$ beet ls album:="The Rainbow Goblins"
高中正義 - The Rainbow Goblins - Prologue
高中正義 - The Rainbow Goblins - Once Upon a Song
高中正義 - The Rainbow Goblins - Seven Goblins
高中正義 - The Rainbow Goblins - The Sunset Valley
高中正義 - The Rainbow Goblins - The Moon Rose
高中正義 - The Rainbow Goblins - Soon
高中正義 - The Rainbow Goblins - Magical Night Light/Rainbow Paradise
高中正義 - The Rainbow Goblins - Thunderstorm
高中正義 - The Rainbow Goblins - Rising Arch
高中正義 - The Rainbow Goblins - Just Chuckle
高中正義 - The Rainbow Goblins - Rainbow Was Reborn
高中正義 - The Rainbow Goblins - Plumed Bird
高中正義 - The Rainbow Goblins - You Can Never Come To This Place
So now we know which songs are in the album, but we’d rather see how long they all are rather than their names. We can use beets’ format syntax to get there:
$ beet ls album:="The Rainbow Goblins" -f '$length'
3:15
5:10
3:12
[...]
We’ll want those in plain seconds:
$ beet ls album:="The Rainbow Goblins" -f '$length' \
| xargs -I '{}' date -u -d "1 jan 1970 0:{}" +%s
195
310
192
[...]![]()
sorry, what did you just do with date??
Ah, that! It takes a duration like 3:15, and turns it into “1 jan 1970 0:3:15” – 3 minutes and 15 seconds after the epoch – and then outputs that timestamp as seconds since the epoch. It’s a hack, and it breaks if you have tracks that are over an hour long, but it’s good enough here.
Now, we can sum up the seconds with awk:
$ beet ls album:="The Rainbow Goblins" -f '$length' \
| xargs -I '{}' date -u -d "1 jan 1970 0:{}" +%s \
| awk '{ total += $1 } END { printf "%s\n", total }'
3797
And then use date again to turn it into hours, minutes, and seconds:
$ beet ls album:="The Rainbow Goblins" -f '$length' \
| xargs -I '{}' date -u -d "1 jan 1970 0:{}" +%s \
| awk '{ total += $1 } END { printf "%s\n", total }' \
| xargs -I '{}' date -u -d "@{}" +%H:%M:%S
01:03:17
And we’re done! It’s worth having a look at the list of format fields that beets can output, since there are heaps of them, and I’ve found it really useful on a few occasions now. I wanted to transcode all of my ALAC files to FLAC a while back, and finding the ALAC files was as easy as beet ls format:flac -f '$path'. Then I can pass that whole list to beet format with the --keep-new flag, and that was that!
I really like beets, and it’s helped me keep my music library far more organised than it ever would have been otherwise, and enabled some really esoteric workflows with how scriptable it is. Please let me know if you’ve got any weird beets tricks of your own, and hopefully I can make a part 2!