Meet MusicKit for Swift

RSS for tag

Discuss the WWDC21 session Meet MusicKit for Swift.

Posts under wwdc21-10294 tag

54 Posts

Post

Replies

Boosts

Views

Activity

Searching for a track with MusicKit Swift Beta
I'm trying to perform a search for a song by album, artist, & title in the cases when I don't know the song's id (or if there is no isrc match) Reading the docs, it seems that I can only search for one term at a time, but against a list of MusicCatalogSearchable Types So my strategy would be to search for albums by name, then filter the results by artist and title. Two questions here, really: Is the above a good strategy, or is there a better way to do this? For the life of my I cannot figure out from the docs, what to put in place of [MusicCatalogSearchable.Album] in the below. var albumRequest = MusicCatalogSearchRequest(term: album.name, types: [MusicCatalogSearchable.Album]) Xcode doesn't like the above and gives the following error: Type 'MusicCatalogSearchable' has no member 'Album' Sadly, everything I've tried, results in an error. When I look in MusicKit, I see the below, which seems empty to me: @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public protocol MusicCatalogSearchable : MusicItem { } What am I missing?
4
0
3k
Aug ’21
How to fetch next batch of albums for an Artist?
Hello, I am fetching and displaying the .fullalbums for an Artist through the MusicKit api. The JSON response returned has a hasNextBatch: true value, but I am unsure how to fetch and display the next batch. Is this something that can be intelligently retrieved though some MusicKit functionality or does one have to perform another data request to fetch the next batch?
2
0
1.3k
Aug ’21
MusicKit Sample Code errors
In Xcode 13 beta 4, the Sample Code Using MusicKit to Integrate with Apple Music has compiler errors around the player.play() calls in handleTrackSelected and handlePlayButtonSelected. The error is "async call in a function that does not support concurrency / call can throw, but is not marked with try and the error is not handled" Would it be possible to include a fix for this error in the sample code - or could somebody share a fix here in the forums? Thanks so much!
5
0
1.4k
Aug ’21
Observing the playbackTime in MusicKit
Hi there! I'm working on an Apple Music client and stuck on creating the now playing screen. I've set up all the buttons but struggling to observe the value of playbackTime to update the current playback time label and the progress bar accordingly. Like you can observe the value of playbackRate and playbackState by making the player's state value as an @ObservedObject, how can I observe this value? Thanks in advance!
3
0
2.4k
Aug ’21
MusicKit additional properties for Songs and Albums
Hi, I know MusicKit is in beta, but after having talked to an engineer at a WWDC lab, it seems to be feature complete for now. I really enjoy the framework and it helps wrap the Apple Music API nicely. However, the types it provides are missing some properties that are relevant to any music item (song, album, music video) such as the releaseDate, contentRating, durationInMillis and url. This is the JSON response from a /tracks relationship of an album: "previews": [ { "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview115/v4/e6/84/62/e6846266-2779-4527-902b-0a3b6f73be75/mzaf_18277320986443617976.plus.aac.p.m4a" } ], "artwork": { "width": 3000, "height": 3000, "url": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/c4/7a/01/c47a01c2-2b04-a327-12bd-c726ae076c7f/886447823545.jpg/{w}x{h}bb.jpeg", "bgColor": "1c1c1c", "textColor1": "fafafa", "textColor2": "e1e1e1", "textColor3": "cdcdcd", "textColor4": "b9b9b9" }, "artistName": "Kollegah", "url": "https://music.apple.com/de/album/alpha/1477896577?i=1477896820", "discNumber": 1, "genreNames": [ "Hip-Hop/Rap", "Musik" ], "durationInMillis": 141827, "releaseDate": "2014-05-09", "name": "Alpha", "isrc": "DEDG61400001", "hasLyrics": true, "albumName": "King", "playParams": { "id": "1477896820", "kind": "song" }, "trackNumber": 1, "composerName": "Kai Engelmann, Phillip Herwig, Alexis Papadimitriou, Daniel Coros, Yunus Cimen & Sadik Kalyon", "contentRating": "explicit" } As you can see, the releaseDate, durationInMillis, url, contentRating, etc. are missing from the struct Song : MusicItem in the MusicKit. I was wondering if we can extend MusicKit as developers in a way to include the releaseDate and other types or are we making a choice between using custom models and custom requests vs. using MusicKit? Thanks
2
0
1.4k
Jul ’21
How do you do a POST to a user's playlist so as to add tracks?
Trying to do what I can do pretty easily with a standard post request in a JS app, but now with Swift, and I'm struggling. I've tried with MusicRequestItem, but that fails, so I went with this and it responds with a 400. func addTracksToAppleMusicPlaylist(targetPlaylistId: String, tracksToSave: [Song]) async throws -> Void {     let tracks = tracksToSave.compactMap{         AppleMusicPlaylistPostRequest(id: $0.id, type: "songs")     }     do {         print("Saving tracks to Apple Music Playlist: \(targetPlaylistId)")         let tokens = try await self.getAppleMusicTokens()         if let url = URL(string: "https://api.music.apple.com/v1/me/library/playlists/\(targetPlaylistId)/tracks") {             var request = URLRequest(url: url)             request.httpMethod = "POST"             request.addValue("Bearer \(tokens.devToken)", forHTTPHeaderField: "Authorization")             request.addValue("\(tokens.userToken)", forHTTPHeaderField: "Music-User-Token")             request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")             let encoder = JSONEncoder()             let data = try encoder.encode(tracks)             request.httpBody = data             let session = URLSession(configuration: .default)             let task = session.dataTask(with: request) {(data, response, error) in                 if error == nil {                     if let httpResponse = response as? HTTPURLResponse {                         print("statusCode: \(httpResponse.statusCode)")                         print("response: \(httpResponse)")                     }                 } else {                     print("Error saving tracks to playlist \(String(describing: error))")                 }             }             task.resume()         } else {             print("Bad URL!")         }     } catch {         print("Error Saving Tracks to Playlist", error)         throw error     } }
1
0
937
Jul ’21
ArtworkImage is not discoverable
Hi, I wanted to display the artwork for a playlist and was puzzled at the Artwork API. In Apple's sample code they use ArtworkImage so I checked the docs for it. ArtworkImage is not listed under structs in MusicKit. If you search for it you can find it - but you have to know it's there. It should be added to the TOC for MusicKit (I would have wrongly assumed this was done automatically) and there should be a link from Artwork to ArtworkImage with an explanation of some sort. FB9353976 Thanks, Daniel
1
0
1.1k
Jul ’21
MusicCatalogSearchRequest without AppleID/Account on iPhone
Hi, I'm currently working on a little music app PoC. I want to search the albums in the Apple Music Catalog which will done via a MusicCatalogSearchRequest: let musicAuthorizationStatus = await MusicAuthorization.request() print(musicAuthorizationStatus) // Issue a catalog search request for albums matching search term. var searchRequest = MusicCatalogSearchRequest(term: searchTerm, types: [Album.self]) searchRequest.limit = 5 let searchResponse = try? await searchRequest.response() print(searchResponse?.albums) I would expect to get a valid search response but it is nil instead. This is the console log when no AppleID is configured on my test device: 2021-06-15 23:07:19.083194+0200 ShareFi[1519:727518] [Entitlements] MSVEntitlementUtilities - Process ShareFi PID[1519] - Group: com.apple.private.tcc.allow - Entitlement: kTCCServiceMediaLibrary - Entitled: NO - Error: (null) .authorized 2021-06-15 23:07:19.130446+0200 ShareFi[1519:727542] [DataRequesting] Failed retrieving MusicKit tokens: Error Domain=ICErrorDomain Code=-8102 "Failed to fetch user token." UserInfo={NSDebugDescription=Failed to fetch user token., NSUnderlyingError=0x2825d8750 {Error Domain=ICErrorDomain Code=-7401 "No active account." UserInfo={NSDebugDescription=No active account.}}}. Throwing .userTokenRequestFailed. 2021-06-15 23:07:19.131133+0200 ShareFi[1519:727542] [DataRequesting] Failed retrieving tokens for MusicDataRequest.Context(url: https://api.music.apple.com/v1/catalog/us/search?term=Earfood&types=albums&omit%5Bresource%5D=autos&limit=5). Error = .userTokenRequestFailed. When I use a sandbox account the error is still a .userTokenRequestFailed but the message says something like: Privacy terms must be accepted first. The Apple Music API seems to require a "Developer Token" but no "User Token" for search requests?! So my questions are: Is it possible to make MusicCatalogSearchRequests without having an AppleID configured? What resources can a user without a active Apple Music subscription interact with? Best regards :) Julian
3
0
2.1k
Jul ’21
Cannot decode library playlists response
Hello, I am fetching library playlists using the endpoint: https://api.music.apple.com/v1/me/library/playlists. After that, I am trying to decode it using a custom struct that has a property named data which is array of Playlist. Here is my code: struct MyPlaylistsResponse: Decodable { let data: [Playlist] } let url = URL(string: "https://api.music.apple.com/v1/me/library/playlists")! let dataRequest = MusicDataRequest(urlRequest: URLRequest(url: url)) let dataResponse = try! await dataRequest.response() let decoder = JSONDecoder() do { let playlistsResponse = try decoder.decode(MyPlaylistsResponse.self, from: dataResponse.data) } catch let error { print("**** ERROR ****") print(error) } But the decoding isn’t working. It is giving me the following error: valueNotFound(Swift.Int, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "attributes", intValue: nil), CodingKeys(stringValue: "artwork", intValue: nil), CodingKeys(stringValue: "width", intValue: nil)], debugDescription: "Expected Int value but found null instead.", underlyingError: nil)) The response is a playlist and I am trying to decode it using a custom Decodable struct that has an array of Playlist. Decoding Genres work, as shown in session, but playlists aren't working. Am I doing something wrong? Thank you
1
0
1.3k
Jul ’21
MusicKit Album Release Data
When printing out an Album, the release date is included: Album(   id: "1566393640",   title: "Aquatic - Single",   artistName: "Nora En Pure",   genreNames: [     "Dance",     "Music"   ],   releaseDate: "2021-06-04",   isCompilation: false,   upc: "7640130765399" ) But it is not mentioned as an instance property here and I cannot identify any way to access it in my project. How can I go about getting access to this attribute via MusicKit? Thanks! :)
2
0
947
Jul ’21
Non-Apple Playlists in MusicKit
Hi, I'm sorry if this is something I should know, but if I make a music catalog search such as: let request = MusicCatalogSearchRequest(term: searchTerm,                               types: [Playlist.self]) I get the Apple Music playlists containing the searchTerm (say Rock, Rap, Jazz,...) How do I get the non Apple playlists say the ones curated by Blue Note? Thanks, Daniel
2
0
1.4k
Jul ’21
Searching for a track with MusicKit Swift Beta
I'm trying to perform a search for a song by album, artist, & title in the cases when I don't know the song's id (or if there is no isrc match) Reading the docs, it seems that I can only search for one term at a time, but against a list of MusicCatalogSearchable Types So my strategy would be to search for albums by name, then filter the results by artist and title. Two questions here, really: Is the above a good strategy, or is there a better way to do this? For the life of my I cannot figure out from the docs, what to put in place of [MusicCatalogSearchable.Album] in the below. var albumRequest = MusicCatalogSearchRequest(term: album.name, types: [MusicCatalogSearchable.Album]) Xcode doesn't like the above and gives the following error: Type 'MusicCatalogSearchable' has no member 'Album' Sadly, everything I've tried, results in an error. When I look in MusicKit, I see the below, which seems empty to me: @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) public protocol MusicCatalogSearchable : MusicItem { } What am I missing?
Replies
4
Boosts
0
Views
3k
Activity
Aug ’21
How to fetch next batch of albums for an Artist?
Hello, I am fetching and displaying the .fullalbums for an Artist through the MusicKit api. The JSON response returned has a hasNextBatch: true value, but I am unsure how to fetch and display the next batch. Is this something that can be intelligently retrieved though some MusicKit functionality or does one have to perform another data request to fetch the next batch?
Replies
2
Boosts
0
Views
1.3k
Activity
Aug ’21
MusicKit: Artist artwork?
I was listing the library artists and couldn't figure out a way to show the artist artwork. Is there a way to fetch it? Under Artist music item, I couldn't find an artwork instance property. Is it due to copyright/legal issues?
Replies
1
Boosts
0
Views
1.7k
Activity
Aug ’21
MusicKit Sample Code errors
In Xcode 13 beta 4, the Sample Code Using MusicKit to Integrate with Apple Music has compiler errors around the player.play() calls in handleTrackSelected and handlePlayButtonSelected. The error is "async call in a function that does not support concurrency / call can throw, but is not marked with try and the error is not handled" Would it be possible to include a fix for this error in the sample code - or could somebody share a fix here in the forums? Thanks so much!
Replies
5
Boosts
0
Views
1.4k
Activity
Aug ’21
Observing the playbackTime in MusicKit
Hi there! I'm working on an Apple Music client and stuck on creating the now playing screen. I've set up all the buttons but struggling to observe the value of playbackTime to update the current playback time label and the progress bar accordingly. Like you can observe the value of playbackRate and playbackState by making the player's state value as an @ObservedObject, how can I observe this value? Thanks in advance!
Replies
3
Boosts
0
Views
2.4k
Activity
Aug ’21
MusicKit additional properties for Songs and Albums
Hi, I know MusicKit is in beta, but after having talked to an engineer at a WWDC lab, it seems to be feature complete for now. I really enjoy the framework and it helps wrap the Apple Music API nicely. However, the types it provides are missing some properties that are relevant to any music item (song, album, music video) such as the releaseDate, contentRating, durationInMillis and url. This is the JSON response from a /tracks relationship of an album: "previews": [ { "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview115/v4/e6/84/62/e6846266-2779-4527-902b-0a3b6f73be75/mzaf_18277320986443617976.plus.aac.p.m4a" } ], "artwork": { "width": 3000, "height": 3000, "url": "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/c4/7a/01/c47a01c2-2b04-a327-12bd-c726ae076c7f/886447823545.jpg/{w}x{h}bb.jpeg", "bgColor": "1c1c1c", "textColor1": "fafafa", "textColor2": "e1e1e1", "textColor3": "cdcdcd", "textColor4": "b9b9b9" }, "artistName": "Kollegah", "url": "https://music.apple.com/de/album/alpha/1477896577?i=1477896820", "discNumber": 1, "genreNames": [ "Hip-Hop/Rap", "Musik" ], "durationInMillis": 141827, "releaseDate": "2014-05-09", "name": "Alpha", "isrc": "DEDG61400001", "hasLyrics": true, "albumName": "King", "playParams": { "id": "1477896820", "kind": "song" }, "trackNumber": 1, "composerName": "Kai Engelmann, Phillip Herwig, Alexis Papadimitriou, Daniel Coros, Yunus Cimen & Sadik Kalyon", "contentRating": "explicit" } As you can see, the releaseDate, durationInMillis, url, contentRating, etc. are missing from the struct Song : MusicItem in the MusicKit. I was wondering if we can extend MusicKit as developers in a way to include the releaseDate and other types or are we making a choice between using custom models and custom requests vs. using MusicKit? Thanks
Replies
2
Boosts
0
Views
1.4k
Activity
Jul ’21
Can you get an Album from a Song with MusicKit?
Is it possible to get an album from a song in MusicKit? I haven't been able to find a way to do so currently. I have tried using .with() but it appears that album is not supported. What I am looking for is properties on the Song like what is present on MPMediaItem such as albumTitle, genre, etc.
Replies
3
Boosts
0
Views
1.3k
Activity
Jul ’21
How do you do a POST to a user's playlist so as to add tracks?
Trying to do what I can do pretty easily with a standard post request in a JS app, but now with Swift, and I'm struggling. I've tried with MusicRequestItem, but that fails, so I went with this and it responds with a 400. func addTracksToAppleMusicPlaylist(targetPlaylistId: String, tracksToSave: [Song]) async throws -> Void {     let tracks = tracksToSave.compactMap{         AppleMusicPlaylistPostRequest(id: $0.id, type: "songs")     }     do {         print("Saving tracks to Apple Music Playlist: \(targetPlaylistId)")         let tokens = try await self.getAppleMusicTokens()         if let url = URL(string: "https://api.music.apple.com/v1/me/library/playlists/\(targetPlaylistId)/tracks") {             var request = URLRequest(url: url)             request.httpMethod = "POST"             request.addValue("Bearer \(tokens.devToken)", forHTTPHeaderField: "Authorization")             request.addValue("\(tokens.userToken)", forHTTPHeaderField: "Music-User-Token")             request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")             let encoder = JSONEncoder()             let data = try encoder.encode(tracks)             request.httpBody = data             let session = URLSession(configuration: .default)             let task = session.dataTask(with: request) {(data, response, error) in                 if error == nil {                     if let httpResponse = response as? HTTPURLResponse {                         print("statusCode: \(httpResponse.statusCode)")                         print("response: \(httpResponse)")                     }                 } else {                     print("Error saving tracks to playlist \(String(describing: error))")                 }             }             task.resume()         } else {             print("Bad URL!")         }     } catch {         print("Error Saving Tracks to Playlist", error)         throw error     } }
Replies
1
Boosts
0
Views
937
Activity
Jul ’21
ArtworkImage is not discoverable
Hi, I wanted to display the artwork for a playlist and was puzzled at the Artwork API. In Apple's sample code they use ArtworkImage so I checked the docs for it. ArtworkImage is not listed under structs in MusicKit. If you search for it you can find it - but you have to know it's there. It should be added to the TOC for MusicKit (I would have wrongly assumed this was done automatically) and there should be a link from Artwork to ArtworkImage with an explanation of some sort. FB9353976 Thanks, Daniel
Replies
1
Boosts
0
Views
1.1k
Activity
Jul ’21
MusicKit search for Categories and Genres
Hi, I'm enjoying working with the MusicKit APIs. I would like to be able to request a collection of the current Categories on the store so users can narrow their interests while searching. I'd like to do the same for Genres. Is there any way to do so? If not - I'd love to see support for this added. Thank you, Daniel
Replies
3
Boosts
0
Views
1.4k
Activity
Jul ’21
MusicCatalogSearchRequest without AppleID/Account on iPhone
Hi, I'm currently working on a little music app PoC. I want to search the albums in the Apple Music Catalog which will done via a MusicCatalogSearchRequest: let musicAuthorizationStatus = await MusicAuthorization.request() print(musicAuthorizationStatus) // Issue a catalog search request for albums matching search term. var searchRequest = MusicCatalogSearchRequest(term: searchTerm, types: [Album.self]) searchRequest.limit = 5 let searchResponse = try? await searchRequest.response() print(searchResponse?.albums) I would expect to get a valid search response but it is nil instead. This is the console log when no AppleID is configured on my test device: 2021-06-15 23:07:19.083194+0200 ShareFi[1519:727518] [Entitlements] MSVEntitlementUtilities - Process ShareFi PID[1519] - Group: com.apple.private.tcc.allow - Entitlement: kTCCServiceMediaLibrary - Entitled: NO - Error: (null) .authorized 2021-06-15 23:07:19.130446+0200 ShareFi[1519:727542] [DataRequesting] Failed retrieving MusicKit tokens: Error Domain=ICErrorDomain Code=-8102 "Failed to fetch user token." UserInfo={NSDebugDescription=Failed to fetch user token., NSUnderlyingError=0x2825d8750 {Error Domain=ICErrorDomain Code=-7401 "No active account." UserInfo={NSDebugDescription=No active account.}}}. Throwing .userTokenRequestFailed. 2021-06-15 23:07:19.131133+0200 ShareFi[1519:727542] [DataRequesting] Failed retrieving tokens for MusicDataRequest.Context(url: https://api.music.apple.com/v1/catalog/us/search?term=Earfood&types=albums&omit%5Bresource%5D=autos&limit=5). Error = .userTokenRequestFailed. When I use a sandbox account the error is still a .userTokenRequestFailed but the message says something like: Privacy terms must be accepted first. The Apple Music API seems to require a "Developer Token" but no "User Token" for search requests?! So my questions are: Is it possible to make MusicCatalogSearchRequests without having an AppleID configured? What resources can a user without a active Apple Music subscription interact with? Best regards :) Julian
Replies
3
Boosts
0
Views
2.1k
Activity
Jul ’21
Cannot decode library playlists response
Hello, I am fetching library playlists using the endpoint: https://api.music.apple.com/v1/me/library/playlists. After that, I am trying to decode it using a custom struct that has a property named data which is array of Playlist. Here is my code: struct MyPlaylistsResponse: Decodable { let data: [Playlist] } let url = URL(string: "https://api.music.apple.com/v1/me/library/playlists")! let dataRequest = MusicDataRequest(urlRequest: URLRequest(url: url)) let dataResponse = try! await dataRequest.response() let decoder = JSONDecoder() do { let playlistsResponse = try decoder.decode(MyPlaylistsResponse.self, from: dataResponse.data) } catch let error { print("**** ERROR ****") print(error) } But the decoding isn’t working. It is giving me the following error: valueNotFound(Swift.Int, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "attributes", intValue: nil), CodingKeys(stringValue: "artwork", intValue: nil), CodingKeys(stringValue: "width", intValue: nil)], debugDescription: "Expected Int value but found null instead.", underlyingError: nil)) The response is a playlist and I am trying to decode it using a custom Decodable struct that has an array of Playlist. Decoding Genres work, as shown in session, but playlists aren't working. Am I doing something wrong? Thank you
Replies
1
Boosts
0
Views
1.3k
Activity
Jul ’21
MusicKit Album Release Data
When printing out an Album, the release date is included: Album(   id: "1566393640",   title: "Aquatic - Single",   artistName: "Nora En Pure",   genreNames: [     "Dance",     "Music"   ],   releaseDate: "2021-06-04",   isCompilation: false,   upc: "7640130765399" ) But it is not mentioned as an instance property here and I cannot identify any way to access it in my project. How can I go about getting access to this attribute via MusicKit? Thanks! :)
Replies
2
Boosts
0
Views
947
Activity
Jul ’21
Non-Apple Playlists in MusicKit
Hi, I'm sorry if this is something I should know, but if I make a music catalog search such as: let request = MusicCatalogSearchRequest(term: searchTerm,                               types: [Playlist.self]) I get the Apple Music playlists containing the searchTerm (say Rock, Rap, Jazz,...) How do I get the non Apple playlists say the ones curated by Blue Note? Thanks, Daniel
Replies
2
Boosts
0
Views
1.4k
Activity
Jul ’21