My macOS iTunes music library includes over 21,000 songs. Some of those tracks contain the wrong information. Wrong title, wrong album, wrong artist, wrong year.
Beets
The open source Beets command line tool helps manage your music library.
The purpose of beets is to get your music collection right once and for all. It catalogs your collection, automatically improving its metadata as it goes using the MusicBrainz database. Then it provides a bouquet of tools for manipulating and accessing your music.
Plugins allow beets to perform more than media management. I won’t talk about most of them today. I don’t want to overwhelm myself. I will keep my focus on using beets from the command line to help me fix my iTunes library.
Alternatives
I prefer command line open source tools. It’s a comfortable habit. You have other options, though.
If you prefer using a mouse, try out Picard from MusicBrainz. Its manual includes an iTunes guide, so you won’t have to guess your way through the process.
TuneUp is a commercial application that integrates with iTunes. I haven’t used it, but TuneUp was the first thing that came up in most of my initial research into fixing my tracks.
Installation and Configuration
beets is written in Python. It works with both Python 2 and 3, but I had better results with my hooks when using Python 2.
I already installed pyenv and pyenv-virtualenv via Homebrew. They aren’t strictly needed, but having distinct environments simplifies things when you have several Python-related projects.
beets uses pyacoustid for acoustic fingerprinting, which helps identify tracks by their audio data. pyacoustid needs the Chromaprint library, so I install that also.
This Google Groups thread got me started on configuration. My settings focus on safely cataloging music rather than organizing it.
~/.config/beets/config.yaml
The plugins add important functionality.
- chroma
- Use acoustic fingerprinting to identify songs by their sound. Slower, but helps with tracks that have bad metadata.
- edit
- Edit details of your songs after importing
- ftintitle
- Puts featured artist information in song title instead of artist.
- fromfilename
- Try to guess missing metadata from the filename of a song.
- importadded
- Use the file’s modification time to determine when you added it to your library. Useful for importing an existing library.
- hook
- Run commands for specific beet events.
TIP
Oh in iTunes uncheck Preferences > Advanced > “Keep iTunes Media folder organized”. Otherwise you’ll end up deleting and reimporting songs that iTunes moved.
Configuration is out of the way. Let’s import music.
Importing a large music library takes time, especially with acoustic fingerprinting. My music took a full weekend, even with match
settings giving it more leeway to automatically use the likeliest matches. But at the end of it all, here’s what I had.
I won’t tell you about all the amazing query support or format strings in beets. Instead let’s just list matches for a random word.
Looks like I have some duplicates. I can worry about that another day.
Tell Beets to Tell iTunes to Refresh
Now that beets has imported everything, it’s time to write it all back out and update the iTunes library.
Write Some AppleScript
NOTE
I spent a full day trying to make JXA work for this. It didn’t. I kept crashing Script Editor with whimsical directives like
console.log(iTunes)
. If you want to try JXA, look at this blog post on JavaScript and iTunes, or the JXA Cookbook page for iTunes.
I rarely use AppleScript, so it took a combination of Web searching and guesswork to come up with this. This post from Doug’s AppleScripts for iTunes blog and this Ask Different answer got me most of the way there. The guesswork finished it off.
~/bin/iTunesRefresh.scpt
The Beets Hook
osascript
lets you run AppleScript commands and files from the command line. This after_write
hook is only called when song metadata is updated in the file itself.
Writing every track with the hook after that big import took about four hours — but I could leave it in the background while I did other stuff.
After the big import
Sometimes beets identifies tracks incorrectly. It happens. For example, Bob Dylan did not sing Stuck in the Middle With You.
I could modify that song with beets modify
, but I can also do it with the
edit plugin.
This pulls up $EDITOR
, which in my case is Vim.
After the import and update, I saw something else in iTunes that bugged me. iTunes can sort by year
, but not by original_year
— the year an album was originally released, rather than the year that particular file or CD was available.
I don’t know how to edit that with beets commands, but I can work directly with its underlying SQLite database. Maybe I’m being a little bold here, but I can always spend another weekend reimporting my music.
sqlite3 ~/.config/beets/library.db
beet write
finalizes those changes, and updates iTunes again thanks to the after_write
hook.
Everything worked out for me this time. But remember, if you change values in the database, they happen in real life too!
NOTE
Then somebody mentioned that I could skip this particular mess by setting the original date option to
yes
in my beets configuration. beets will update a song’syear
,month
, andday
fields to reflect the values inoriginal_date
. Use that setting if you would rather not poke around in the database.
What Next?
That’s good enough for today. I’ll correct entries as I see them, but things are definitely better than when I started.
To see what you can do with beets, check out the plugins.
Play with the query support and format strings. Have fun!
Backlinks
Got a comment? A question? More of a comment than a question?
Talk to me about this page on:
Added to vault 2024-01-15. Updated on 2024-02-01