I use Apple Music in large part because I’ve been rating songs there (and in iTunes before it) for over a decade. I also really dislike making playlists and Apple has a “smart playlists” feature that makes it really easy to programmatically include/remove music based on its rating and other attributes. Apple natively tracks play count, skip count, and genre, but the genre is usually one broad word the label picked, and plays and skips only mean something together: a song I’ve played 200 times and skipped 150 times isn’t a favorite, and one I’ve played 20 times and never skipped probably is. So I built PlaylistMint. PlaylistMint reads my library, classifies every track by energy, mood, genre, listening context, and language, writes the labels back into Music.app, and then builds playlists that combine those labels with my ratings and a calculated skip rate to reflect how much I enjoy the song.
How it works
- Classify. Every track gets five labels: energy (slow, moderate, high), mood (joyful, melancholic, aggressive, neutral), context (party, workout, focus, social, background, introspective), one of ~235 genres, and one of ~12 languages. Output is structured and checked against a controlled taxonomy, so the model can’t invent a genre called “vibes.”
-
Write back. The labels go into each track’s Genre and Grouping fields via AppleScript. Daft Punk’s Get Lucky becomes
high.joyful|funk|party|english. - Build playlists. 60+ playlists, organized in folders by energy, mood, context, genre, and language, with variants for All, 4 or more stars, 5 stars, and unrated for each.
Because the labels live in the Grouping field, they also work with Music.app’s own smart playlists. “Grouping contains workout” AND “Grouping contains aggressive” is a gym playlist that keeps updating as I add music.
Smart playlists can’t do math, so they can’t filter on a skip rate. PlaylistMint precomputes it and writes cumulative threshold tags (skp_le:010 means skipped on at most 10% of plays). A rule like “Grouping contains skp_le:010” gets you “songs I almost never skip” without any arithmetic in the rule. If you haven’t rated much, PlaylistMint falls back to play and skip counts: New Favorites, On Rotation, and All Time Favorites.
Writing to Music.app is annoying & slow
Classification was the easy half of this project. Getting 60+ playlists into Music.app reliably took far more work.
Music.app’s AppleScript API will happily create a playlist inside a folder inside a folder, and then refuse to find it. exists user playlist "Joyful" of folder playlist "Mood" returns false while the playlist sits in that folder on screen. Creating a playlist inside a tell folder playlist block silently drops it at the top level. Some statements intermittently fail to parse when the script is piped to osascript on stdin, but run fine when passed as -e arguments. Each of these got a workaround, and the workarounds got tests.[1]
Rewriting metadata across an entire library is also the kind of thing you do carefully. Before any write, PlaylistMint backs up the existing Genre and Grouping values. It reads every write back to verify it, skips tracks flagged for manual review instead of guessing, and can restore from the backup. Existing playlists with the same name get renamed to timestamped backups instead of deleted.
Try it
PlaylistMint is available at playlistmint.com. In Music.app, go to File → Library → Export Library…, upload the Library.xml, and close the tab. You’ll get an email when it’s done with a script that creates the playlists in Music.app with one command. Mac only, since the output is AppleScript. It’s free for the first few hundred people. If a lot more people want it than that, I may have to start charging to cover the costs.
Notes
[1] Apple’s automation surfaces seem to go like this: there are many ways to do things, and each one has gaps you have to route around. Tab2Notes had to go through a temp file and a Shortcut to reach Apple Notes for the same reason.