Creating a New Playlist and Adding Shazamed Songs

I went through the Shazam app and couldn’t find a way to create a new playlist in Apple Music and add the shazamed songs. (Correct me if I’m wrong) It automatically adds them to the “My Shazam Tracks” playlist.

But let’s say I’m at WWDC 2022, and I shazam some songs. I want to create a new playlist specifically for it. I wrote an article about it, Experimenting with ShazamKit - Let’s Shazam Everything, where I create an app that continuously searches for music and creates a list.

This article will extend the app to take that list of Shazamed songs and create a new playlist in Apple Music.

To give a brief introduction, we have a published property, mediaItems that contains all the recognized songs -

@Published private(set) var mediaItems: [SHMediaItem] = []

Conforming to SHSessionDelegate provides us with session(_:didFind:) method from which we can get the recognized song and add it to the mediaItems array -

// MARK:- SHSessionDelegate
extension HomeViewModel: SHSessionDelegate {
  func session(_ session: SHSession, didFind match: SHMatch) {

    guard let mediaItem = match.mediaItems.first else { return }

    Task {
      if mediaItems.contains(where: { $0.shazamID == mediaItem.shazamID }) {
        // Song already identified and in the list. Do nothing.
      } else {
        self.mediaItems.append(mediaItem)
      }
    }
  }
}

There’s a method addToMusicLibrary where we add the songs in Shazam’s library. We’ll replace it with the new implementation as follows. First, we need to import MediaPlayer to access MPMediaLibrary and create a new playlist -

import MediaPlayer

We create a unique id for our playlist -

let playlistID = UUID()

Then, we use the class MPMediaPlaylistCreationMetadata to describe our new playlist -

let creationMetadata = MPMediaPlaylistCreationMetadata(name: "My Playlist")
creationMetadata.authorDisplayName = "Rudrank Riyam"
creationMetadata.descriptionText = "This playlist contains awesome songs!"

We use the asynchronous method getPlaylist(with:creationMetadata) to create the new playlist with the playlistID and creationMetadata -

let playlist = try await MPMediaLibrary.default().getPlaylist(with: playlistID, creationMetadata: creationMetadata)

The MPMediaPlaylist class contains an instance method add(_ mediaItems: [MPMediaItem]), but it accepts an array of MPMediaItem whereas we have an array of SHMediaItem. I haven’t figured out how to convert a SHMediaItem to an MPMediaItem, so we’ll manually loop over the array and add them to the playlist by using the appleMusicID instance property of SHMediaItem -

for item in mediaItems {
  if let productID = item.appleMusicID {
    try await playlist.addItem(withProductID: productID)
  }
}

With this, we can create our own playlists! Note that this is an asynchronous task that may throw an error, so you should handle the error accordingly. Here’s the complete code -

public func addToMusicLibrary() {
  Task {
    do {
      let playlistID = UUID()
      let creationMetadata = MPMediaPlaylistCreationMetadata(name: "My Playlist")
      creationMetadata.authorDisplayName = "Rudrank Riyam"
      creationMetadata.descriptionText = "This playlist contains awesome items."

      let playlist = try await MPMediaLibrary.default().getPlaylist(with: playlistID, creationMetadata: creationMetadata)

      for item in mediaItems {
        if let productID = item.appleMusicID {
          try await playlist.addItem(withProductID: productID)
        }
      }
    } catch {
      print("*** PLAYLIST CREATION ERROR***")
      print(error)
    }
  }
}

Thanks for reading this post! If you’ve any suggestions/feedback or want me to write more about ShazamKit/MusicKit, do let me know on Twitter.