MusicKit

RSS for tag

Let users play Apple Music and their local music library from your app using MusicKit.

Posts under MusicKit tag

93 Posts

Post

Replies

Boosts

Views

Activity

Thoughts on MusicLibraryRequest as a replacement for MPMediaQuery
I'm very excited about the new MusicLibrary API, but after a couple of days of playing around with it, I have to say that I find the implementation of filtering MusicLibraryRequests a little confusing. MPMediaQuery has a fairly extensive list of predicates that can be applied, including string and persistentID comparisons for artist, album artist genre, and more. It also lets you filter on an item’s title. MusicLibraryRequests let you filter on the item’s ID, or on its MusicKit Artist and Genre relationships. To me, this seems like it adds an extra step.  With an MPMediaQuery, if I wanted to fetch every album by a given artist, I’d apply an MPMediaPropertyPredicate looking at MPMediaItemPropertyAlbumArtist and compare the string. It was also easy to change the MPMediaPredicateComparison to .contains to match more widely. If I wanted to surface albums by “Aesop Rock” or “Aesop Rock & Blockhead,” I could use that. In the MusicLibraryRequest implementation, it looks like I need to perform a MusicLibraryRequest<Artist> first in order to get the Artist objects. There’s no filter for the name property, so if I don’t have their IDs, I’ve got to use filter(text:). From there, I can take the results of that request and apply them to my MusicLibraryRequest<Album> using the filter(matching:memberOf) function.  I could use filter(text:) on the MusicLibraryRequest<Album>, but that filters across multiple properties (title and artistName?) and is less precise than defining the actual property I want to match against. I think my ideal version of the MusicLibraryRequest API would offer something like filter(matching:equalTo:) or filter(matching:contains:) that worked off of KeyPaths rather than relationships. That seems more intuitive to me. I’m not saying we need every property from every filterable MPMediaItemProperty key, but I’d love to be able to do it on title, artistName, and other common metadata. That might look something like: filter(matching: \.title, contains: “Abbey Road”) filter(matching: \.artistName, equalTo: “Between The Buried And Me”) I noticed that filter(text:) is case insensitive, which is awesome, and something I’ve wanted for a long time in MPMediaPropertyPredicate. As a bonus, it would be great if a KeyPath based filter API supported a case sensitivity flag. This is less of a problem when dealing with Apple Music catalog content, but users’ libraries are a harsh environment, and you might have an artist “Between The Buried And Me” and one called “Between the Buried and Me.” It would be great to get albums from both with something like: filter(matching: \.artistName, equalTo: “Between The Buried And Me”, caseSensitive: false)  I've submitted the above as FB10185685. I also submitted another feedback this morning regarding filter(text:) and repeating text as FB10184823. My last wishlist item for this API (for the time being!) is exposing the MPMediaItemPropertyAlbumPersistentID as an available filter attribute. I know, I know… hear me out. If you take a look at the other thread I made today, you’ll see that due to missing metadata in MusicKit, I still have some use cases where I need to be able to reference an MPMediaItem and might need to fetch its containing MPMediaItemCollection to get at other tracks on the album. It would be nice to seamlessly be able to fetch the MPMediaItemCollection or the library Album using a shared identifier, especially when it comes to being able to play the album in MusicKit’s player rather than Media Player’s.  I've submitted that list bit as FB10185789 Thanks for bearing with my walls of text today. Keep up the great work!
11
1
3.8k
Nov ’24
MusicKit / macOS : Song.Artwork not nil when there is no Artwork
I'm using iCloud Music Library. I’m using macOS 14.1 (23B74) and iOS 17.1. i’m using MusicKit to find songs that do not have artwork. On iOS, Song.artwork will be nil for items I know do not have artwork. On macOS, Song.artwork is not nil. However when the songs are shown in Music.app, they do not have Artwork. Is this expected? Alternately, is there a more correct way to determine that a Song has no Artwork? I have also filed FB13315721. Thank you for any tips!
1
0
749
Nov ’24
Clear ApplicationMusicPlayer queue after station queued
After an Album, Playlist, or collection of songs have been added to the ApplicationMusicPlayer queue, clearing the queue can be easily accomplished with: ApplicationMusicPlayer.shared.queue.entries = [] This transitions the player to a paused state with an empty queue. After queueing a Station, the same code cannot be used to clear the queue. Instead, it causes the queue to be refilled with a current and next MusicItem from the Station. What's the correct way to detect that the ApplicationMusicPlayer is in the state where it's being refilled by a Station and clear it? I've tried the following approaches with no luck: # Reinitialize queue ApplicationMusicPlayer.shared.queue = ApplicationMusicPlayer.Queue() # Create empty Queue let songs: [Song] = [] let emptyQueue = ApplicationMusicPlayer.Queue(for: songs) ApplicationMusicPlayer.shared.queue = emptyQueue
1
0
557
Nov ’24
MusicKit and sorted artist and album names?
I have an app that gets data from Music.app with both the iTunesLibrary and MusicKit. iTunesLibrary has ITLibArtist.sortName and ITLibAlbum.sortTitle and ITLibAlbum.sortAlbumArtist. I can’t seem to find an equivalent in MusicKit. How are those properties obtained using MusicKit? Thanks. FYI I have filed FB15554956 on this. You also may see my code at https://github.com/bolsinga/itunes_json
1
1
503
Nov ’24
Generate recomendation QUEUE after selection a song in MusicKit
Hi, I'm developing a musicKit integration in my iOS App, and I want to select songs from recently played (done it), the problem is that the queue is not auto-generated and the user have to select other song if they want to go forward. There is any method to ask for similar songs, or recommended songs, from a song that the user has already selected? It will be really great :) Also if you know it... There is any publisher for the music duration or I need to do a timer?? Thanks. David.
1
1
393
Nov ’24
MusicKit: How do we search by title or name only?
I can't find any way to search for a song by title only. You can search for songs, but any term you provide appears to be applied to any metadata associated with the song. Look at the largely nonsensical results when I search for a song with the letters "de": In many cases, that string doesn't appear anywhere. I used MusicCatalogSearchRequest(term: searchTerm, types: [Song.self]) Likewise it stands to reason that people want to search for artist and album names using text strings. How do we do that?
0
0
423
Nov ’24
Unable to add MusicKit capability
I have an existing Xcode project that I am trying to add MusicKit to, but for some reason I am unable to. I have logged into my developer account, and ticked off the MusicKit checkbox under the Services tab of my app in the Certificates, Identifiers & Profiles section. In Xcode I have Automatically manage signing set to true. But MusicKit does not show up as a Capability, neither in the list of capabilities in my app, nor when trying to add it with the +Capability button. I have done this successfully before with Game Center, so I really do not understand why this does not work with MusicKit. Any ideas as to how this can be solved?
2
0
856
Dec ’24
Batching CatalogSearchRequests for Spotify Playlist conversion
Hi! Im attempting to make a spotify to apple playlist converter and to do so am using the Catalog search functionality of the api. My question is, is there anyway to convert these songs to apple music urls (or ids) that does not spam api calls. I know you can batch catalog searches if you have apple music song ids, but I obviously dont have that since the song was shared from spotify. Any ideas/help is appreciated!
0
0
442
Dec ’24
MusicKit lastPlayedDate always nil
I am having trouble accessing the lastPlayedData for any given album or track using MusicKit. The value is always nil, both on numerous albums and tracks I tested. Afaik this is not a property that has to be fetched separately like tracks for example. I am running this on my physical iPhone 12 18.1.1 with Xcode 16.1. The albums and tracks have definitely been played multiple times before. The app has permission to the library using MusicAuthorization.request() This post mentions the same problem but offers no solution. Thanks for any help
0
0
450
Dec ’24
MusicKit swift start / end times
Hello! I am having trouble setting start times for songs when using the ApplicationMusicPlayer. When I initialize a new MusicPlayer.Queue.Entry using the following constructor, I am seeing strange results: init( _ playableMusicItem: PlayableMusicItem, startTime: TimeInterval? = nil, endTime: TimeInterval? = nil ) It appears that any value I provide for startTime is also applied to the endTime. For example: MusicPlayer.Queue.Entry(playable, startTime: TimeInterval(30), endTime: TimeInterval(183)) provides the following console output: MusicPlayer.Queue.Entry(id: "3D6A3DA3-595E-4657-8DBA-DDD245BBB7EF", transientItem: PlayableMusicItem, startTime: 30.0, endTime: 30.0) I have also tried setting the endTime to nil with the same result. Does anyone have any experience setting start times for songs using the MusicKit ApplicationMusicPlayer? Any feedback is greatly appreciated!
6
2
1.9k
Dec ’24
Apple music web kit play issues (MusicKit JS)
Hello, I am trying to follow the getting started guide. I have produced a developer token via the music kit embedding approach and can confirm I'm successfully authorized. When I try to do play music, I'm unable to hear anything. Thought it could be some auto-play problems with the browser, but it doesn't appear to be related, as I can trigger play from a button with no further success. const music = MusicKit.getInstance() try { await music.authorize() // successful const result = await music.api.music(`/v1/catalog/gb/search`, { term: 'Sound Travels', types: 'albums', }) await music.play() } catch (error) { console.error('play error', error) // ! No error triggered } I have searched the forum, have found similar queries but apparently none using V3 of the API. Other potentially helpful information: OS: macos 15.1 (24B83) API version: V3 On localhost Browser: Arc (chromium based), also tried on Safari, The only difference between the two browsers is that safari appears to exit the breakpoint, whereas Arc will continue (without throwing any errors) authorizationStatus: 3 Side note, any reason this is still in beta so many years later?
1
0
663
Dec ’24
Trouble with getting extended Album info from user library
Hello! I have a problem with getting album extended info from users library. Note that app authorised to use Apple Music according documentation. I get albums from users library with this code: func getLibraryAlbums() async throws -> MusicItemCollection<Album> { let request = MusicLibraryRequest<Album>() let response = try await request.response() return response.items } This is an example of Albums request respones: { "data" : [ { "meta" : { "musicKit_identifierSet" : { "isLibrary" : true, "id" : "1945382328890400383", "dataSources" : [ "localLibrary", "legacyModel" ], "type" : "Album", "deviceLocalID" : { "databaseID" : "37336CB19CF51727", "value" : "1945382328890400383" }, "catalogID" : { "kind" : "adamID", "value" : "1173535954" } } }, "id" : "1945382328890400383", "type" : "library-albums", "attributes" : { "artwork" : { "url" : "musicKit:\/\/artwork\/transient\/{w}x{h}?id=4A2F444C%2D336D%2D49EA%2D90C8%2D13C547A5B95B", "width" : 0, "height" : 0 }, "genreNames" : [ "Pop" ], "trackCount" : 1, "artistName" : "Сара Окс", "isAppleDigitalMaster" : false, "audioVariants" : [ "lossless" ], "playParams" : { "catalogId" : "1173535954", "id" : "1945382328890400383", "musicKit_persistentID" : "1945382328890400383", "kind" : "album", "musicKit_databaseID" : "37336CB19CF51727", "isLibrary" : true }, "name" : "Нимфомания - Single", "isCompilation" : false } }, { "meta" : { "musicKit_identifierSet" : { "isLibrary" : true, "id" : "-8570883332059662437", "dataSources" : [ "localLibrary", "legacyModel" ], "type" : "Album", "deviceLocalID" : { "value" : "-8570883332059662437", "databaseID" : "37336CB19CF51727" }, "catalogID" : { "kind" : "adamID", "value" : "1618488499" } } }, "id" : "-8570883332059662437", "type" : "library-albums", "attributes" : { "isCompilation" : false, "genreNames" : [ "Pop" ], "trackCount" : 1, "artistName" : "TIMOFEEW & KURYANOVA", "isAppleDigitalMaster" : false, "audioVariants" : [ "lossless" ], "playParams" : { "catalogId" : "1618488499", "musicKit_persistentID" : "-8570883332059662437", "kind" : "album", "id" : "-8570883332059662437", "musicKit_databaseID" : "37336CB19CF51727", "isLibrary" : true }, "artwork" : { "url" : "musicKit:\/\/artwork\/transient\/{w}x{h}?id=BEA6DBD3%2D8E14%2D4A10%2D97BE%2D8908C7C5FC2C", "width" : 0, "height" : 0 }, "name" : "Не звони - Single" } }, ... ] } In AlbumView using task: view modifier I request extended information about the album with this code: func loadExtendedInfo(_ album: Album) async throws -> Album { let response = try await album.with([.tracks, .audioVariants, .recordLabels], preferredSource: .library) return response } but in the response some of the fields are always nil, for example recordLabels, releaseDate, url, editorialNotes, copyright. Please tell me what I'm doing wrong?
0
0
435
Dec ’24
MusicKit Artwork url
Hi, I'm trying out the beta for music kit. In the current version of my app, my widget can show multiple albums. I preload the images of the album covers. In the beta's the url that is returned for the artwork starts with: "musickit://", which does not work with URLSession. How can I preload the data using the new url scheme? Current code:     func fetchArtworkFor (musicID: MusicItemID, url : URL?) async throws -> UIImage? {         guard let url = url else {             return nil         }         let urlRequest = URLRequest (url: url)         let data = try await URLSession.shared.data(for: urlRequest)         let image = UIImage(data: data.0)         return image     } // Some other function         for album in albumsToShow {             if let url = album.artwork?.url(width: context.family.imageHeight, height: context.family.imageHeight), let image = try? await fetchArtworkFor(musicID: album.id, url:url) {                 images[album] = image             }         }
3
1
2.2k
Dec ’24
Playlist IDs from MusicKit not working with Apple Music API
I am building an app for MacOS and I am trying to implement the code to add songs to a library playlist (which is added below). The issue I am having is that if I use Music Kit to load a users library playlists, the ID for the playlist (which is just a string of numbers) does not work with the Add tracks to a Library Playlist endpoint of Apple Music API. If I retrieve the playlists from the Apple Music API and use that playlist ID (which is different than the id I get from MusicKit) my code works fine and adds the song to the playlist. The problem is that when getting a users library playlists from Apple Music API is that it does not give me all of the library playlists that I get when using Music Kit and it also does not give me Artwork for playlists that have the collage of album covers, so I would prefer to use Music Kit to get the playlists. I have also tested trying to retrieve a single playlist using the Apple Music API with the playlist Id from Music Kit and it does not work. I get the error that the resource cannot be found. Since this is a macOs app I cannot use MusicKit to add songs to library playlists. Does anyone know a way to resolve this? Or a possible workaround? Ideally I want to use MusicKit to get the library playlists and have some way to use the playlist Id and add songs to that playlist. Below is my code for adding a song to a playlist using the Apple Music API, which works correctly only if I originally get the library playlist's id value from a playlist retrieved from the Apple Music API. Also, does anyone know why the playlist Id's are not universal and are different when using Music Kit and Apple Music API? For songs and tracks it does not seem to matter if I use music kit or Apple Music API, the Id's are in the correct format for Apple Music API to use and work with my code. Thanks everyone for any and all help! func addToPlaylist(songs: [Track], playlist: Playlist, alert: Binding<AlertItem?>) async { let tracks = AppleMusicPlaylistPostRequestBody(data: songs.compactMap { AppleMusicPlaylistPostRequestItem(id: $0.id.rawValue, type: "songs") // or "library-songs" }) let playlistID = playlist.id // Build the request URL for adding a song to a playlist guard let url = URL(string: "https://api.music.apple.com/v1/me/library/playlists/\(playlistID)/tracks") else { alert.wrappedValue = AlertItem(title: "Error", message: "Invalid URL for the playlist.") return } // Authorization Header guard let musicUserToken = try? await MusicUserTokenProvider().getUserMusicToken() else { alert.wrappedValue = AlertItem(title: "Error", message: "Unable to retrieve Music User Token.") return } do { var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Bearer \(musicUserToken)", forHTTPHeaderField: "Authorization") request.setValue("application/json", forHTTPHeaderField: "Content-Type") let encoder = JSONEncoder() let data = try encoder.encode(tracks) request.httpBody = data let musicRequest = MusicDataRequest(urlRequest: request) let musicRequestResponse = try await musicRequest.response() // Check if the request was successful (status 201) if musicRequestResponse.urlResponse.statusCode == 201 { alert.wrappedValue = AlertItem(title: "Success", message: "Song successfully added to the playlist.") } else { print("Status Code: \(musicRequestResponse.urlResponse.statusCode)") print("Response Data: \(String(data: musicRequestResponse.data, encoding: .utf8) ?? "No Data")") // Attempt to decode the error response into the AppleMusicErrorResponse model if let appleMusicError = try? JSONDecoder().decode(AppleMusicErrorResponse.self, from: musicRequestResponse.data) { let errorMessage = appleMusicError.errors.first?.detail ?? "Unknown error occurred." alert.wrappedValue = AlertItem(title: "Error", message: errorMessage) } else { alert.wrappedValue = AlertItem(title: "Error", message: "Failed to add song to the playlist.") } } } catch { alert.wrappedValue = AlertItem(title: "Error", message: "Network error: \(error.localizedDescription)") } }
1
1
770
Dec ’24
Music Kit initialisation, Uncaught TypeError: Cannot read properties of undefined (reading 'node')
I'm trying to load Music Kit on the server with solid js. I can confirm that my implementation has been sufficient to return authentication tokens and for MusicKit.isAuthorized to return true. My issue is that if I reload the page, it only succeeds intermittently (perhaps 25% of the time?). My question is - what is wrong with my implementation? Removing the async keyword ensures it loads every time but playing and queuing music no longer works. I'm currently assuming this is an SSR issue but the docs haven't explicitly specified this isn't possible. I have the following boilerplate: export default createHandler( () => ( <StartServer document={({ assets, children, scripts }) => { return ( <html lang="en"> <head> <meta name="apple-music-developer-token" content={authResult.token} /> <meta name="apple-music-app-name" content="app name" /> <meta name="apple-music-app-build" content="1978.4.1" /> {assets} <script src="https://js-cdn.music.apple.com/musickit/v3/musickit.js" async /> </head> <body> <div id="app">{children}</div> {scripts} </body> </html> ) }} /> )) When I first load my app, I'll encounter: musickit.js:13 Uncaught TypeError: Cannot read properties of undefined (reading 'node') at musickit.js:13:10194 at musickit.js:13:140 at musickit.js:13:209 The intermittence signals an issue relating to the async keyword. An expansion on this issue can be found here.
0
0
532
Dec ’24
[Request] Support for Spotify-like Audio Analysis API for Apple Music.
Hi, I have been working on a project that enables users to listen to their favorite music using a streaming service, which so far was Spotify. The app had a programmable 3D/2D interface with the ability to connect to devices in your home and have them react to music. As of September 2024, Spotify decomissioned their Audio Analysis API. I have seen other posts mention playing Apple Music through AVFoundation, which would break DRM and so it’s not supported. However, the Spotify Audio Analysis API does not allow for a full frequency reconstruction. It is entirely temporal data on beats, kicks, loudness, and timbre changes, which themselves are operators on the spectral data from the FFT. It would be very useful for the developer community if we get the ability to do this and it will probably Apple Music among developers and those who use their apps a lot more. Would love to hear your thoughts about this and Happy New Year!
0
2
601
Dec ’24
ApplicationMusicPlayer stops with error after skipping quickly over playlist entries
ApplicationMusicPlayer with queue created from playlist crashes with random occurrence shortly after skipping back or forth using controls embedded in the notification, with the error on console log: applicationController: xpc service connection interrupted. I've noticed that the issue occurs more frequently the shorter is time between skipping entries. Since ApplicationMusicPlayer is run on a remote process, the main app does not crash, but the music stops playing without any exception, and the playback control turns uninitiated. Here is how I'm initiating the queue: let entries = playlist .with(.entries).entries! .map { ApplicationMusicPlayer.Queue.Entry($0) } ApplicationMusicPlayer.shared.queue = .init( entries, startingAt: entries.last ) Please give me some tips on how to solve this. EDIT: The issue does not occur when navigating quickly through the station.
1
0
494
Jan ’25
SystemMusicPlayer.item nil when state = .playing
I've been working with MusicKit without enrolling for a developer account and I haven't run into any issues until I noticed nil on the SysteyMusicPlayer item for some songs and I don't understand why. Are some songs blocked from the framework? Or is it somehow a limitation to not having registered MusicKit to the bundle ID? I am planning on using MusicKit properly in prod and this is just a test app for a package I'm working on. These are the nil songs which I got from the Discovery Station: https://music.apple.com/ca/album/okay/950816298?i=950816304 https://music.apple.com/ca/album/youre-so-cool/1670485433?i=1670485446
0
0
403
Jan ’25