MusicKit

RSS for tag

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

Posts under MusicKit tag

134 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

MusicKit subscription page crashes
Hi there, It seems I'm getting crashes in the Apple Music subscription view sometimes. Couldn't figure out why. crash_info_entry_0 _MusicKit_SwiftUI/MusicSubscriptionOffer.swift:73: Fatal error: Unexpectedly changed musicSubscriptionOffer's isPresented binding to true while internal presentation state is loading(MusicSubscriptionOffer.Options(messageIdentifier: .join, itemID: 331661274, affiliateToken: ....)). It's important to note I am displaying it from UIKit ObjC and so I had to go through some hoops in order to get this to working. Here's the relevant code: // // MusicSubscriptionOfferView.swift // import Foundation import MusicKit import Combine import SwiftUI struct MusicSubscriptionOfferView: View { @StateObject var viewModel = MusicSubscriptionOfferViewModel() var body: some View { EmptyView() .musicSubscriptionOffer( isPresented: $viewModel.isShowingOffer, options: viewModel.offerOptions ) } } class MusicSubscriptionOfferViewModel: NSObject, ObservableObject { @Published var isShowingOffer = false static var musicItemID: MusicItemID? var canBecomeSubscriber = false var offerOptions: MusicSubscriptionOffer.Options { get { var options = MusicSubscriptionOffer.Options() options.affiliateToken = "..." options.itemID = MusicSubscriptionOfferViewModel.musicItemID return options } } var subscriptions = Set<AnyCancellable>() override init() { super.init() Task { for await subscription in MusicSubscription.subscriptionUpdates { MyApp.sharedInstance().canBecomeSubscriber = subscription.canBecomeSubscriber } } NotificationCenter.default .publisher(for: NSNotification.Name(K_SHOW_APPLE_MUSIC_SUBSCRIPTION)) .sink { [weak self] _ in self!.isShowingOffer = true } .store(in: &subscriptions) } } MusicSubscriptionOfferViewModel is initiated on launch, so MyApp.sharedInstance().canBecomeSubscriber receives a value upon launch. and: @objcMembers final class MusicOfferProxyViewController: UIHostingController<MusicSubscriptionOfferView> { required init() { super.init(rootView: MusicSubscriptionOfferView()) } @objc required dynamic init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } From the UIKit view controller: MusicKitInterop* musicKitObject = [[MusicKitInterop alloc] init]; [self.view addSubview:musicKitObject.musicOfferProxyViewController.view]; [self addChildViewController:musicKitObject.musicOfferProxyViewController]; self.musicKitInterop = musicKitObject; class MusicKitInterop: NSObject { var musicOfferVC: MusicOfferProxyViewController override init() { musicOfferVC = MusicOfferProxyViewController() } @objc func musicOfferProxyViewController() -> UIViewController { return musicOfferVC } @objc func canBecomeSubscriber() -> Bool { return MyApp.sharedInstance().canBecomeSubscriber } }
1
0
435
Sep ’23
MusicKit: Artist MusicItemID is not the same between Library and Catalog. Is there a way to map them?
So I understand that MusicItemID is a unique object identifier so for one specific artist; they have a different MusicItemID from Library than from Catalog. But if I'm trying to implement a feature that allows users to add UNIQUE Artists to a list, whether it be from Library or Catalog; how am I supposed to differentiate between the Library Artist and Catalog Artist? In this scenario, there is no way for me to identify that an Artist from Library is the same Artist from Catalog because the MusicItemID is not the same; so it's not possible for me to omit duplicates from the list as I cannot identify if they are representing the same Artist. This is an extremely big blocker as I want users to have the option to access from library and catalog. I've looked over the documentation but can't find anything that would allow me to do this sort of mapping to match Artists between Library and Catalog. Using name comparison also is not a valid option as Artist names are not unique. Any advice or workarounds would be appreciated, thank you.
0
0
349
Sep ’23
MusicLibraryRequest for podcasts
Hi. I am transitioning my app from using MPMediaQuery to using MusicLibraryRequest from MusicKit. This is working fine for playlists in the user's library. I also allow my app users to play their podcasts. I currently use MPMediaQuery.podcasts(). Does anyone know if there is an equivalent using MusicLibraryRequest? Cheers, Ian
0
0
379
Sep ’23
MusicLibraryRequests are much slower on macOS/Mac Catalyst than on iOS
I'm experiencing this issue on Sonoma beta 7 and Xcode 15 beta 8: FB13094612 -- MusicLibraryRequests are way slower on macOS than iOS The following code has massive speed differences on macOS than iOS, with macOS taking 3-7 seconds for each request and iOS taking 0.1 seconds or less. let start = Date() var artistAlbumRequest = MusicLibraryRequest<Album>.init() artistAlbumRequest.filter(matching: \.artistName, equalTo: "Ratboys") print("Searching artist Ratboys") let artistAlbums = try! await artistAlbumRequest.response() let name = artistAlbums.items.first!.title let id = artistAlbums.items.first!.id let end = Date() print("It took \(end.timeIntervalSince1970 - start.timeIntervalSince1970) to complete the artist request. \(artistAlbums.items.count) returned") print(artistAlbums.items) let start2 = Date() print("Searching by title: \(name)") var albumNameRequest = MusicLibraryRequest<Album>.init() albumNameRequest.filter(matching: \.title, equalTo: name) let nameAlbum = try! await albumNameRequest.response() let end2 = Date() print("It took \(end2.timeIntervalSince1970 - start2.timeIntervalSince1970) to complete this request") print(nameAlbum.items) print("Searching by ID") let start3 = Date() var albumIDRequest = MusicLibraryRequest<Album>.init() albumIDRequest.filter(matching: \.id, equalTo: id) let idalbum = try! await albumIDRequest.response() let end3 = Date() print("It took \(end3.timeIntervalSince1970 - start3.timeIntervalSince1970) to complete this request") print(idalbum.items) Awaiting the three requests takes 0.085, 0.019, and 0.102 seconds respectively on iOS. However, they take 7.10, 0.1, and 3.3 seconds on macOS. The second one only returns so quickly because of a bug where matching on title returns no results (see FB13094588) This makes it very difficult to provide a good experience when starting music playback, because it takes several seconds between the user selecting an album and it starting.
0
0
465
Aug ’23
A couple of MusicLibraryRequest<Album> issues on Sonoma
Thanks to the MusicKit team for addressing FB12301908 and FB12301718, but I'm afraid I've discovered even more issues that make MusicLibraryRequest<Album> difficult/impossible to use on macOS. Each of these issues is occurring on Sonoma seed 7 and Xcode 15 beta 8. FB13094022 - MusicLibraryRequest crashes when no filters are applied with error about MPModelGenre The following code crashes the app when run against my library (consisting of Apple Music catalog and self-added music) on macOS or Mac Catalyst: var libraryRequest = MusicLibraryRequest<Album>.init() let albums = try! await libraryRequest.response() The error is as follows: <NSXPCConnection: 0x6000023bc460> connection to service with pid 4331 named com.apple.amp.library.framework: Exception caught during invocation of reply block to message 'performLibraryRequest:withReply:'. Exception: No identifiers for model class: MPModelGenre from source: (null) ( 0 CoreFoundation 0x000000018ebb08c0 __exceptionPreprocess + 176 1 libobjc.A.dylib 0x000000018e6a9eb4 objc_exception_throw + 60 2 Foundation 0x000000018fcf718c -[NSCalendarDate initWithCoder:] + 0 3 MediaPlayer 0x00000001be7f3e20 -[MPBaseEntityTranslator _objectForPropertySet:source:context:] + 392 4 MediaPlayer 0x00000001be7f41f8 -[MPBaseEntityTranslator _objectForRelationshipKey:propertySet:source:context:] + 296 5 MediaPlayer 0x00000001be7f4088 __63-[MPBaseEntityTranslator _objectForPropertySet:source:context:]_block_invoke_2 + 76 6 CoreFoundation 0x000000018eafe6f4 __NSDICTIONARY_IS_CALLING_OUT_TO_A_BLOCK__ + 24 7 CoreFoundation 0x000000018eafe5bc -[__NSDictionaryI enumerateKeysAndObjectsWithOptions:usingBlock:] + 268 8 MediaPlayer 0x00000001be7f3fdc __63-[MPBaseEntityTranslator _objectForPropertySet:source:context:]_block_invoke + 436 9 MediaPlayer 0x00000001be82c5c4 -[MPModelObject initWithIdentifiers:block:] + 184 10 MediaPlayer 0x00000001be7f3d80 -[MPBaseEntityTranslator _objectForPropertySet:source:context:] + 232 11 MediaPlayer 0x00000001be7f30e0 -[MPBaseEntityTranslator objectForPropertySet:source:context:] + 32 12 MediaPlayer 0x00000001be8becbc __47-[MPModeliTunesLibraryRequestOperation execute]_block_invoke + 1032 13 iTunesLibrary 0x00000001c2de3584 iTunesLibrary + 83332 14 CoreFoundation 0x000000018eb1c144 __invoking___ + 148 15 CoreFoundation 0x000000018eb1bfbc -[NSInvocation invoke] + 428 16 Foundation 0x000000018fc06698 __NSXPCCONNECTION_IS_CALLING_OUT_TO_REPLY_BLOCK__ + 16 17 Foundation 0x000000018fc04d18 -[NSXPCConnection _decodeAndInvokeReplyBlockWithEvent:sequence:replyInfo:] + 520 18 Foundation 0x000000018fc04674 __88-[NSXPCConnection _sendInvocation:orArguments:count:methodSignature:selector:withProxy:]_block_invoke_3 + 188 19 libxpc.dylib 0x000000018e788034 _xpc_connection_reply_callout + 116 20 libxpc.dylib 0x000000018e787f2c _xpc_connection_call_reply_async + 80 21 libdispatch.dylib 0x000000010534ebcc _dispatch_client_callout3 + 20 22 libdispatch.dylib 0x0000000105373e0c _dispatch_mach_msg_async_reply_invoke + 400 23 libdispatch.dylib 0x0000000105357ae8 _dispatch_lane_serial_drain + 368 24 libdispatch.dylib 0x0000000105358e00 _dispatch_lane_invoke + 468 25 libdispatch.dylib 0x000000010536877c _dispatch_root_queue_drain_deferred_wlh + 652 26 libdispatch.dylib 0x0000000105367a54 _dispatch_workloop_worker_thread + 444 27 libsystem_pthread.dylib 0x00000001050abd9c _pthread_wqthread + 288 28 libsystem_pthread.dylib 0x00000001050b3ab4 start_wqthread + 8 ) FB13094588 - MusicLibraryRequest filtered by .title, equalTo returns blank The following code returns no results on macOS and MacCatalyst but successfully returns albums on iOS: var albumNameRequest = MusicLibraryRequest<Album>.init() albumNameRequest.filter(matching: \.title, equalTo: "The Window") let nameAlbums = try! await albumNameRequest.response() It returns no results whether I'm providing a string myself, or using the .title property of an Album I've already fetched
5
0
633
Aug ’23
iOS 17 beta (and iOS 16) Music Gapless Playback Broken ... Again
Am I the only one having this problem? The Music app on iOS 17 beta does not cleanly seque between songs that are intended to have no gap between them. When gapless songs are played (e.g., Pink Floyd's "Dark Side of the Moon", The Beatles' "Abbey Road"), a noticeable gap is heard between songs. These are songs in my music library that I sync from my computer, not Apple Music streams. It should be noted that this bug also exists in iOS 16.6, and I've verified that the problem does not occur on a older phone running iOS 15.7.8. More importantly, when I put the device in Airplane mode, the songs seque correctly, without any gaps. I suspect that the Music app is phoning home to Apple (a bad practice in and of itself) and something is interrupting playback queuing. Even when I have Cellular access turned off for the Music app, and am not connected to Wi-Fi, the problem persists. The only way to make gapless playback work is to turn off all of the device radios via Airplane mode. Understand that this is NOT a cross-fade issue. It is a gapless issue. And it's not an Apple Music streaming issue. The problem seems to be more prevalent for songs encoded as 128 kbps AAC. In comparison, the Music app on macOS (Ventura, 13.5) operates correctly. It's only iOS that no longer performs gapless playback. I've filed bug reports (FB12992049 and FB13019931), but have not heard anything from Apple. Like I asked at the beginning, am I the only one having this problem? It's extremely maddening that Apple can't get this right. I can't play my Pink Floyd, Alan Parsons, and my other AOR playlists, including my late 60's Beatles. Steve Jobs would be rolling in his grave.
6
3
1.8k
Sep ’23
MusicDataRequest responding with an Internal Service Error when creating a playlist folder
I am trying to create a new playlist folder in Apple Music using MusicKit on iOS 16. However, I am receiving an Internal Service Error when sending the request. This is the code: let urlString = "https://api.music.apple.com/v1/me/library/playlist-folders" let url = URL(string: urlString)! let body = LibraryPlaylistFolderCreationRequest( attributes: .init( name: "test-playlist-folder"), relationships: .init( parent: .init( data: [.init(id: "playlistsroot", type: "library-playlist-folders")]))) var urlRequest = URLRequest(url: url) urlRequest.httpMethod = "POST" urlRequest.httpBody = try JSONEncoder().encode(body) let request = MusicDataRequest(urlRequest: urlRequest) let response = try await request.response() let responseString = String(data: response.data, encoding: .utf8) print(responseString) When I print the request body using the following code snippet, I get the output as seen below: let jsonBody = try JSONEncoder().encode(body) print(String(data: jsonBody, encoding: .utf8)) Output of the above snippet: Optional("{\"attributes\":{\"name\":\"test-playlist-folder\"},\"relationships\":{\"parent\":{\"data\":[{\"id\":\"playlistsroot\",\"type\":\"library-playlist-folders\"}]}}}") Which should conform to the JSON scheme provided in the docs: https://developer.apple.com/documentation/applemusicapi/libraryplaylistfoldercreationrequest And this is the error output: [DataRequesting] Failed to perform MusicDataRequest.Context( url: "https://api.music.apple.com/v1/me/library/playlist-folders", currentRetryCounts: [.other: 1] ) with MusicDataRequest.Error( status: 500, code: 50000, title: "Internal Service Error", detailText: "", id: "VK23VIZ6AAM5IVP4GIFQ6VXPLU", originalResponse: MusicDataResponse( data: 111 bytes, urlResponse: <NSHTTPURLResponse: 0x000000028042b0c0> ) ). After a lot of trial and error, I don't think I know what the underlying issue is. Is MusicDataRequest not designed to issue POST requests? Is it something else? Kind regards!
1
0
559
Sep ’23
MusicKit: URL to a song in user's Music Library in macOS?
I am looking for a way to get a URL to a MusicItemID/Song that is in the users music library after finding the song using MusicKit search. I would like the linked song to open the system music player. MusicCatalogSearchRequest has a link to the song, but MusicLibrarySearchRequest songs don't include a url. var searchRequest = MusicLibrarySearchRequest(term: searchTerm, types: [Song.self]) let s = try await searchRequest.response() resultSongURL = s.songs[0].song.url **alas, empty url** macOS also lacks access to SystemMusicPlayer when not using Catalyst. Thanks!
0
0
399
Aug ’23
Timer Pauses When Playing Apple Music, AvAudioPlayer and Synthesizer
In my workout app, I play workout music locally using AvAudioPlayer. There's a one-second timer firing to update a countdown clock and progress circle. I also play text through the Synthesizer and sound effects through AvAudioPlayer. It all works smoothly. There's no hesitation at any time in the UI to update the countdown clock or progress circle. I added the ability to play music through Apple Music. Not everything works smoothly. Switching the audio session to duckothers mode to turn down the volume on Apple Music while the synth plays causes problems. You can't switch sessions while something is playing in AvAudioPlayer, which happens while I'm playing sound effects. It's a timing mess, but solvable. What I can't figure out is that in the periods when Apple Music is playing, the AvAudioPlayer is playing, and the synth is speaking, the UI visibly freezes for a second or so and then resumes. If I don't play sound effects through AvAudioPlayer, the UI does not freeze. I tried various "DispatchQueue.global(qos: options", but I think it all just goes into the OS subsystem anyway, so it's not really running in the calling thread context. So, after this torturous setup, is there a way to condition priorities, threads, or some other mechanism in swiftui to make sure the timer gets enough priority to operate smoothly at all times? thanks
0
0
432
Aug ’23
Queuing Bug in MPMusicPlayerController's append(_ :) & prepend(_:) on iOS 17 Beta
There’s an unexpected behaviour when using the append(_:) & prepend(_:) methods on iOS 17 Beta 6 and Public Beta 4. Observed Behaviour When queuing using the mentioned methods on recent iOS 17 Betas, the supplied music isn‘t queued up and the now playing music pauses. When using applicationQueuePlayer, it even ends up crashing the app. FB13010449 Sample Project
2
0
524
Aug ’23
MusicKit: Recent Items -- 30 item limit?
Using the MusicKit API to query the recent items seems to have a limit of 30 records. var searchRequest = MusicRecentlyPlayedRequest<Song>() Is this the true limit or is there another way? Using the Web Service API seems to have this limit too and is kind enough to document that. https://developer.apple.com/documentation/applemusicapi/get_recently_played_tracks I am interested in searching all history for certain tracks. The music library is good for checking songs played, but does not maintain tracks not in the library. Thank you for the assistance!
0
0
410
Aug ’23
setPlaybackRate changes are ignored in the background on iOS 17
Starting some time during the iOS 17 beta period, I've been seeing unusual playback rate behavior. I have an app that configures a queue of tracks to play and then sets the playback rate at the start of each new track, getting notified of each new track by observing MPMusicPlayerControllerNowPlayingItemDidChange. In iOS 17, I've noticed that setting the playback rate while an app is in the background will not actually change the playback rate. It appears to, and MusicPlayer.state.playbackRate returns the playback rate that has been requested, but the actual playback rate remains at whatever value it was previously. This is not the case when the app is in the foreground, setting the playback rate works as you would expect, updating the actual rate of playback as well as the value returned from the MusicPlayer. In iOS 16, these playback rate changes would occur normally, regardless of the state of the app in the foreground or background. Given the incorrect rate information coming back from the MusicPlayer state, this would appear to be an unexpected change. I've looked in the SDK diffs for any intentional changes for how playbackRate works and I haven't seen anything new or any new tech notes on the subject. Has anyone seen anything like this in their own implementations?
0
0
350
Aug ’23
Change the Volume for ApplicationMusicPlayer to hear the voice synthesizer?
My app uses the voice synthesizer, and I'm trying to integrate apple music into my app using MusicKit to play a playlist during a workout. I want to lower the volume of the music while the synthesizer is speaking so the user can hear it. When I play music locally using AVAudioPlayer this is possible. I'm using the ApplicationMusicPlayer to play the tracks of the playlist. I don't see a way to lower the volume ApplicationMusicPlayer programmatically. Is there a way to programmatically change the volume of the ApplicationMusicPlayer? Or is there a better way to accomplish what I'm trying to do? thanks
1
0
497
Aug ’23
Fetch with time in Apple music API
I'm trying to pull library songs, playlist and artist from authorized user. The API gives me data in alphabetical order and there's no timestamp in the response, is it possible to fetch data with the most recent ones first? It is very difficult to pull all the data and filter ourselves, is it possible to fetch only the first 30-60 most recent ones?
0
0
514
Aug ’23
Crossfade with MPMusicPlayerController.applicationQueuePlayer
Hi. In iOS 17 Apple introduced crossfading for the Music app. In my app I am using MPMusicPlayerController.applicationQueuePlayer and also want to support crossfading. In an early beta of iOS 17 my app crossfaded automatically with the same setting as for the Music app which maybe was a bug. However, I did not find any way to enable crossfade for my app. Does anybody know how to do that? Thanks, Dirk
1
0
737
Nov ’23
MusicKit JS Not Resolving/Authorizing User
For some reason when I go through the same process as shown here: https://developer.apple.com/documentation/musickitjs/ using MusicKit JS to authorize a user, the popup opens a user logs in and then on the access request screen you click allow nothing happens. You can see in the network tab when inspecting that the usertoken is being generated but the popup isn't closing and no matter what I try I cannot extract the usertoken, any thoughts?
0
0
629
Jul ’23
MusicKit MusicCatalogSearchRequest.response() starting failing with 401 userTokenRequestFailed for users without subscription
Hello, I have an app published on AppStore which relies on MusicKit's functionality to retrieve results of MusicCatalogSearchRequest even when a user doesn't have an Apple Music subscription. (As per other sources and this thread, this is expected to work normally for users without the subscription.) The app used to work fine for months, yet today all the devices I tested on failed to execute the request (both AppStore and dev versions), resulting in the following log: 2023-07-27 23:45:16.036271+0200 Lisyn[6288:3156868] [DataRequesting] Updated user token cache with new error. 2023-07-27 23:45:16.043294+0200 Lisyn[6288:3156868] [DataRequesting] Failed retrieving user token: Error Domain=ICError Code=-8101 "Failed to fetch music user token with Unauthorized (401) status code. Account does not have an active Apple Music Subscription." UserInfo={NSDebugDescription=Failed to fetch music user token with Unauthorized (401) status code. Account does not have an active Apple Music Subscription.}. Throwing .userTokenRequestFailed. 2023-07-27 23:45:16.043413+0200 Lisyn[6288:3156868] [DataRequesting] Failed refreshing user token for MusicDataRequest.Context( url: "https://api.music.apple.com/v1/catalog/it/search?term=B&l=en-GB&types=songs&limit=25&omit%5Bresource%5D=autos", currentRetryCounts: [.userTokenInvalid: 1], activeRetryContext: RetryContext( reason: .userTokenInvalid, previousTokens: .personalizedTokens( developerToken: "some token", userToken: "some other token" ) ) ). Error = .userTokenRequestFailed. I am using automatic token generation and make requests via MusicKit: func searchMusic(searchText: String) async throws -> [PlaybackStoreID] { return try await throttler.schedule { var request = MusicCatalogSearchRequest(term: searchText, types: [Song.self]) request.limit = 25 return try await request.response().songs.map(\.id.rawValue) } } None of the certificate/identifier settings, nor the code related to the issue has been touched between when it was working and now. Also, live versions stopped working as well, so I am sure this isn't related. Is this a temporary issue? Should I roll out a fix using non-automatic token generation? Thank you!
1
0
605
Jul ’23