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.
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.
I prefer command line open source tools. It’s a comfortable habit. You have other options, though.
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.
$ pyenv virtualenv 2.7.14 beets $ pyenv shell beets
$ brew install chromaprint $ pip install beets pyacoustid
This Google Groups thread got me started on configuration. My settings focus on safely cataloging music rather than organizing it.
The plugins add important functionality.
- Use acoustic fingerprinting to identify songs by their sound. Slower, but helps with tracks that have bad metadata.
- Edit details of your songs after importing
- Puts featured artist information in song title instead of artist.
- Try to guess missing metadata from the filename of a song.
- Use the file’s modification time to determine when you added it to your library. Useful for importing an existing library.
- Run commands for specific beet events.
Configuration is out of the way. Let’s import music.
$ beet import ~/Music/iTunes/iTunes\ Media/Music
Importing a large music library takes time, especially with acoustic
fingerprinting. My music took a full weekend, even with
giving it more leeway to automatically use the likeliest matches. But at
the end of it all, here’s what I had.
$ beet stats Tracks: 22112 Total time: 8.7 weeks Approximate total size: 107.8 GiB Artists: 2498 Albums: 2405 Album artists: 1117
$ beet ls pigeon Bert - Songs From the Street: 35 Years of Music - Doin' the Pigeon Cyndi Lauper - Hat Full of Stars - Sally's Pigeons Cyndi Lauper - Twelve Deadly Cyns... and Then Some - Sally's Pigeons Tom Lehrer - An Evening Wasted With Tom Lehrer - Poisoning Pigeons in the Park Lo Fidelity Allstars - How to Operate With a Blown Mind - Battle Flag feat. Pigeonhed RJD2 - Have Mercy - Have Mercy (Remix feat Lyrics Born and Pigeon John) RJD2 - Have Mercy - Have Mercy (Remix feat Lyrics Born and Pigeon John)
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
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.
The Beets Hook
osascript lets you run AppleScript commands and files from the command
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.
$ beet edit 'stuck in the middle'
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 sqlite> update items set year = original_year where year != original_year and original_year != 0; sqlite> update albums set year = original_year where year != original_year and original_year != 0;
beet write finalizes those changes, and updates iTunes again thanks to
Everything worked out for me this time. But remember, if you change values in the database, they happen in real life too!
That’s good enough for today. I’ll correct entries as I see them, but things are definitely better than when I started.