18 Replies
      Latest reply on Nov 22, 2019 12:15 PM by jr.
      dsowa Level 1 Level 1 (0 points)

        Hi,

         

        i'm playing around a little bit with the muscia kit REST Api.

        As long i'm accesing the catalog, e.g. https://api.music.apple.com/v1/catalog/de/search?term=james+brown&limit=2&types=artists,albums, the api return store ids. I then can use the store ids together with MPMusicPlayerController.

        But if i'm accessing my library, the id is something like i.addWKtl6kQE. Is there any way to translate this id in something usefull for MPMusicPlayerController? Right now i'm only able to use the store id and the persistent id together with MPMusicPlayerController.

        So from that point there is no connection between playing songs on a device and using the Music Kit API?

        • Re: Music Kit API library ID into something i can use on the device
          bluetropical Level 1 Level 1 (0 points)

          I am also having the same issue

          • Re: Music Kit API library ID into something i can use on the device
            voporak5 Level 1 Level 1 (0 points)

            If that song is a song that was added via apple music then when you look for the song in your library you want to reference the playbackStoreID https://developer.apple.com/documentation/mediaplayer/mpmediaitempropertyplaybackstoreid?language=objc

             

            However if that song was added from an album you copied over from your computer to your device then you'd have to search the api for the corresponding track id assuming you can find it and it is offered on Apple Music

            • Re: Music Kit API library ID into something i can use on the device
              whatsmusic Level 1 Level 1 (0 points)

              Hi,

               

              I'm also stuck with the same issue now. Did you ever find a solution to this s**king problem?

              • Re: Music Kit API library ID into something i can use on the device
                higginator Level 1 Level 1 (0 points)

                I have ran into the same issue. I have found that when using a song id from a user's music library, the music player plays a different song from their music library, or does not play a song at all.

                Would be great if the personal library song id vended could be the same playbackID as the search catalog, or the song id would play the correct song.

                • Re: Music Kit API library ID into something i can use on the device
                  wcrtr2121212 Level 1 Level 1 (0 points)

                  Has anyone figured this out yet?

                   

                  I'm trying to use the library id (e.g. l.NP4oWSo) to play my library content from the Apple Music API (e.g. /v1/me/library/albums). I want to be consistent in using the MusicKit APIs vs using an MPMediaItemCollection, which is what is referenced in the Adding Content to Apple Music example referenced by 3ZS above.

                   

                  The most consistent way to handle content coming from either the store catalog or the user's library is to use the Play Params returned from MusicKit, which contain metadata about the album or track, including id (l.NP4oWSo format for library items and an larger Integer for catalog items) and even an isLibrary key that is set to true for library items.

                   

                  So the playParams from MusicKit for a library album item look like:

                   

                  {
                    "id": "l.JmwYn9g",
                    "kind": "album",
                    "isLibrary": true
                  }

                   

                  So my current thinking has been to try and create an MPMusicPlayerPlayParametersQueueDescriptor using the above play param [String: Any] dictionary.

                   

                  From Apple's own documenatation on this object:

                   

                  A set of properties and methods used to modify how items are played, based on play parameters returned from MusicKit API results. Use this class to modify the player queue created by a query before the queue begins to play. You can modify when individual items start and stop playing, along with setting the first item to be played.

                   

                  So this seems like it should, work. I should be able to pass any play parameters from the Apple MusicKit api, per this documentation, and it will take those parameters and figure out how to set the queue and play the item. My code looks like:

                   

                  let playParams: [String: Any] = ... // from MusicKit api object attributes/playParams
                  
                  guard let playerPlayParams = MPMusicPlayerPlayParameters(dictionary: playParams) else {
                       // handle error if play params can't be parsed by initializer
                       return;
                  }
                  
                  let queue = MPMusicPlayerPlayParametersQueueDescriptor(playParametersQueue: [playerPlayParams])
                  
                  let musicPlayerController = MPMusicPlayerController.systemMusicPlayer
                  musicPlayerController.setQueue(with: queue)
                  (musicPlayerController as MPMediaPlayback).play()

                   

                  Alas, this doesn't work. If there's no items in the queue already, it will not play anything, and if there are existing queue items it will not modify them before playback (e.g. plays the current queue).

                   

                  I really want to work with this API, but so far the documentation has been very lacking and from this thread it seems like this library vs catalog playback issue is very confusing to anyone who is wanting to create awesome Apple Music apps.

                   

                  I hope someone has figured this out, or someone from Apple will reply to this thread with more info as I've spent a lot of time trying to figure this out and have spent a lot of time documenting the issues in this post. The current example is very lacking in doing anything other than basic playback from the device library or playback of catalog requests (e.g. recently played api queries or search api queries). For those of us wanting to provide users of our MusicKit apps a great experience that references a user's music library in addition to just the catalog, we need to figure out a real way to handle this issue.

                   

                  And just my 2 cents, as feedback the real differentiator of something like Apple Music vs Spotify, for me anyway, is the ability to have library items alongside streaming catalog items (e.g. stuff you have stored on iTunes Match) and so the inability to work with this via the api in an effective way is frustrating.

                    • Re: Music Kit API library ID into something i can use on the device
                      wcrtr2121212 Level 1 Level 1 (0 points)

                      Some additional info here that I've found in continuing to play around with this, in case it's helpful to anyone.

                       

                      The play params for an album will not work I think unless a catalogId is present, and that does not seem to be returned in the play params for albums, but it is returned for tracks.

                       

                      So for instance, a track will have the following playParams:

                       

                      {
                           "isLibrary": true,
                           "reporting": true,
                           "id": "i.eoD8YY7F69M2gA",
                           "kind": "song",
                           "catalogId": "999887109"
                      }

                       

                      which then can be used like so:

                       

                      
                      var playParamList = [MPMusicPlayerPlayParameters]()
                      
                      // an album is a object of parsed json from MusicKit, including tracks which have also been parsed from
                      // the MusicKit response
                      
                      // using for loop here vs map for code readability
                      for track in album.tracks {
                           guard let pp = MPMusicPlayerPlayParameters(dictionary: track.playParams) else {
                                continue
                           }
                                      
                           playParamList.append(pp)      
                      }
                      
                      let q = MPMusicPlayerPlayParametersQueueDescriptor(playParametersQueue: playParamList)
                      musicPlayerController.setQueue(with: q)
                      (musicPlayerController as MPMediaPlayback).play()
                      

                       

                      This actually works...

                       

                      However, again here you need the catalog id in the playParams payload. I think as far as I can tell you are SOL on any of this if you just have the id that looks like i.eoD8YY7F69M2gA so I'm not sure what the point of having this data is at all really... I'm still totally lost on how you'd play something that didn't have a catalog id but was returned from MusicKit, I just wanted to paste this code here in case someone else was trying to figure out the play params queue descriptor because there aren't any examples anywhere else on the internet.

                        • Re: Music Kit API library ID into something i can use on the device
                          klaas Level 1 Level 1 (0 points)

                          Thanks for your investigations. Currently I'm working on something else, but I'll look into this.

                          • Re: Music Kit API library ID into something i can use on the device
                            higginator Level 1 Level 1 (0 points)

                            Hey,

                             

                            About 2 weeks ago Apple updated their API output to include additional information in the playParams. Specifically, songs saved from the catalog will have a catalogId and reporting set to True. This is GREAT because you can play the song using the catalogId. I have also noticed that songs I have purchased, will have a purchasedId attribute and reporting set to False. The purchasedId did not play the correct song, similar to libraryIds. It looks like this output is experimental by Apple, and those catalogIds/purchasedIds could disappear in the future.

                             

                                {

                                        attributes =             {

                                            albumName = "Songs of Innocence";

                                            artistName = U2;

                                            artwork =                 {

                                                height = 1200;

                                                url = "https://is5-ssl.mzstatic.com/image/thumb/Features1/v4/75/26/06/75260685-4a6d-7342-9ad8-c5a56e5b8c50/mza_3295371297510140818.jpg/{w}x{h}bb.jpeg";

                                                width = 1200;

                                            };

                                            durationInMillis = 239846;

                                            name = "California (There Is No End to Love)";

                                            playParams =                 {

                                                id = "i.LVk6rMYU0zNXLD";

                                                isLibrary = 1;

                                                kind = song;

                                                purchasedId = 915794181;

                                                reporting = 0;

                                            };

                                            trackNumber = 3;

                                        };

                                        href = "/v1/me/library/songs/i.LVk6rMYU0zNXLD";

                                        id = "i.LVk6rMYU0zNXLD";

                                        type = "library-songs";

                                    },

                             

                            So, a strategy is to take the information available from a library song and perform a catalog request and compare to get a 'best match'. Then, you will have a catalogId to play a song. Lots of workarounds I'm trying...

                        • Re: Music Kit API library ID into something i can use on the device
                          trentben Level 1 Level 1 (0 points)

                          Thank you for post, I am having a simular problem with playing a library playlist. I am able to play tracks with a id "i.xxxx" by making playParams, but I can't seem to do the same with a playlist.

                           

                          playParams = [ "id": "p.4Y0Jg11I26lVaXZ",

                            "kind": "playlist",

                            "isLibrary": true,

                            "globalId": "pl.u-kv9l2aaI7B5gk48"]

                           

                          Here is a sample of what i have been trying



                          • Re: Music Kit API library ID into something i can use on the device
                            weeto Level 1 Level 1 (0 points)

                            I ended up using the following logic on song results returned from library APIs (not catalog APIs):

                            • check "playParams", if "catalogId" is there then use it:
                                        "playParams":{
                                           "id":"i.oOdKEpmsOO4rLK",
                                           "kind":"song",
                                           "isLibrary":true,
                                           "reporting":true,
                                           "catalogId":"1468910018"
                                        },
                            
                            • else check "playParams", if "purchasedId" is there then collect it:
                                        "playParams":{
                                           "id":"i.KoJezZYTddP6zZ",
                                           "kind":"song",
                                           "isLibrary":true,
                                           "reporting":false,
                                           "purchasedId":"953329401"
                                        },
                            

                             

                            After that I make a request to Get Multiple Catalog Songs by ID API (Get Multiple Catalog Songs by ID - Apple Music API | Apple Developer Documentation) with gathered "purchasedId"s (you can also include "catalogId"s to keep the logic simple):

                             

                            https://api.music.apple.com/v1/catalog/{storefront}/songs?ids=953329401,1189391897,1192687537,273798279,283213617748952
                            
                            

                            You will notice, that some "purchasedId"s are actually catalog IDs! In my request above I sent 8 purchasedIds and got 6 songs as a result. That's how I filtered stuff not in catalog (most probably synced manually from my mac).

                             

                            Hope this will help someone.

                              • Re: Music Kit API library ID into something i can use on the device
                                wcrtr2121212 Level 1 Level 1 (0 points)

                                I finally had something I thought was working for me -

                                 

                                Taking the playParams returned by the music API and passing them into the player like so:

                                 

                                guard let pp = MPMusicPlayerPlayParameters(dictionary: playItem.playParams) else {
                                   // error
                                }
                                
                                // add play params to queue

                                 

                                However, it seems like apple has AGAIN changed the way this works in the last few days. Now I have to pass a play params list with ONLY the catalogId (as id not catalogId and kind: "song"). e.g.

                                 

                                {id: {some catalogIdd), kind: "song"}

                                 

                                Has anyone else on this thread seen a behavior change? Are we going to be able to work with a stable API ever? I want to build on apple music but I'm about ready to switch to a competitive api because it actually has stable endpoints and behavior and versioning instead of pushing random changes. This is very frustrating. I have spent more time hacking my way around this API then I have putting time into the user experience. I don't know how to get clear information here but as it is now the apple music api is not a production level api.

                              • Re: Music Kit API library ID into something i can use on the device
                                jr. Apple Staff Apple Staff (0 points)

                                There is a recent "catalog" relationship available on some library content (library-songs, library-music-videos and library-playlists) that can be used for this purpose. This relationship may not always be populated as it's possible have no association with any catalog content such as some uploaded content or purchased music that is not available for streaming.

                                 

                                To get this relationship, a few approaches are available. Here's are some examples using a sample identifier from the original post:

                                 

                                GET /v1/me/library/songs/i.addWKtl6kQE?relate=catalog

                                Returns the library song resource along with an identifier to some available catalog song resource.

                                 

                                GET /v1/me/library/songs/i.addWKtl6kQE?include=catalog

                                Returns the library song resource with the available catalog song resource.

                                 

                                GET /v1/me/library/songs/i.addWKtl6kQE/catalog

                                Returns just the available catalog song resource.

                                 

                                The playParams attribute is not intended for making this association and it is possible for the values it contains to evolve over time.