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!
Post
Replies
Boosts
Views
Activity
Hi there!
I am fetching library songs using the endpoint: https://api.music.apple.com/v1/me/library/songs
Here's the code snippet -
struct Songs: Decodable {
let data: [Song]
}
public func librarySongs() async throws {
let url = URL(string: "https://api.music.apple.com/v1/me/library/songs")
guard let url = url else { return }
let dataRequest = MusicDataRequest(urlRequest: URLRequest(url: url))
do {
let dataResponse = try await dataRequest.response()
print(dataResponse.debugDescription)
let response = try JSONDecoder().decode(Songs.self, from: dataResponse.data)
} catch {
print("**ERROR**")
print(error)
print(error.localizedDescription)
}
}
Trying to decode it using a custom struct gives me the following error. -
**ERROR**
keyNotFound(CodingKeys(stringValue: "artistName", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 20", intValue: 20), CodingKeys(stringValue: "attributes", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: \"artistName\", intValue: nil) (\"artistName\").", underlyingError: nil))
The data couldn’t be read because it is missing.
On digging through the response, I found that one of the songs doesn't have an artist name because it is just a recording of my song I added to the library through GarageBand.
In this case, what should be the approach?
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?
I'm trying to get the album title from the current entry in the Queue of ApplicationMusicPlayer.
I'm using the following code for this purpose -
let queue = ApplicationMusicPlayer.shared.queue
let item = queue.currentEntry?.item
if case let .song(song) = item {
print(song.albumTitle)
}
But it is returning a nil value. If I print the debug description of the song, I get the other details.
Song(
id: "1524813873",
title: "'Til We Die",
artistName: "Slipknot",
discNumber: 1,
hasLyrics: "false",
releaseDate: "2008-08-20",
trackNumber: 15
)
If I do a request to MusicCatalogResourceRequest<Song>, and print the debug description, I get the album title as well.
let queue = ApplicationMusicPlayer.shared.queue
let item = queue.currentEntry?.item
if case let .song(song) = item {
do {
let musicRequest = MusicCatalogResourceRequest<Song>(matching: \.id, equalTo: song.id)
let response = try await musicRequest.response()
print(response.items.first.debugDescription)
} catch {
print(error)
}
}
Song(
id: "1524813873",
title: "'Til We Die",
albumTitle: "All Hope Is Gone (Deluxe Edition)",
artistName: "Slipknot",
composerName: Chris Fehn, Corey Taylor, Craig Jones, Jim Root, Joey Jordison, Mick Thomson, Paul Gray, Shawn "Clown" Crahan & Sid Wilson,
discNumber: 1,
duration: 345.693,
genreNames: [
"Metal",
"Music",
"Rock"
],
hasLyrics: "true",
isrc: "NLA320887352",
releaseDate: "2008-08-20",
trackNumber: 15
)
Is this a bug or intentional? Thanks!
Hi there!
I am curious if the MusicPlayer from MusicKit is supported on watchOS.
I have not tried it yet, and the documentation says it is only available on iOS, iPadOS, tvOS, and Catalyst.
Can you please confirm?
Is there a way to play it through the NowPlayingView?
Thank you!
Hi there!
I am working on the genres screen and realised that I can directly use MusicCatalogResourceRequest for fetching genre with a particular ID:
func getGenres() async {
do {
let genreID = MusicItemID("17")
let request = MusicCatalogResourceRequest<Genre>(matching: \.id, equalTo: genreID)
let genreResponse = try await request.response()
print(genreResponse.items)
} catch {
print(error)
}
}
Apple Music also has an API to get the top charts genres. How would I do it without using MusicDataRequest, or is it the only way?
My current approach:
typealias Genres = MusicItemCollection<Genre>
do {
let countryCode = try await MusicDataRequest.currentCountryCode
let genreURL = "https://api.music.apple.com/v1/catalog/\(countryCode)/genres"
guard let url = URL(string: genreURL) else {
throw URLError(.badURL)
}
let request = MusicDataRequest(urlRequest: URLRequest(url: url))
let response = try await request.response()
let genre = try JSONDecoder().decode(Genres.self, from: response.data)
print(genre)
} catch {
print(error)
}
Thank you!
Hi there!
I went through the Apple Music API and stumbled upon Get a Catalog Song's Relationship Directly by Name, an endpoint to fetch a song's relationship by using its identifier.
If you take a look at the example given on the page:
https://api.music.apple.com/v1/catalog/us/songs/1572278914/albums
And see the response, it has a property called audioTraits:
“audioTraits”: [
“lossy-stereo”,
“lossless”,
“atmos”,
“spatial”
]
And another one hasTimeSyncedLyrics:
“hasTimeSyncedLyrics”: true
Although, I cannot find these two properties in MusicKit's Song.
If I hit the API directly using a developer token generated, it does not have these properties as well.
I know Apple cannot disclose if these properties will be available in the future or not, but curious nonetheless.
Hi there!
How do I go about accessing the details of the curator?
For example, if I hit the following endpoint to access details about a playlist:
https://api.music.apple.com/v1/catalog/us/playlists/pl.047294ae14a24e5993d1f7ab2b127188
Then, in the response, I see the curator containing the ID under relationships:
"curator": {
"href": "/v1/catalog/us/playlists/pl.047294ae14a24e5993d1f7ab2b127188/curator",
"data": [
{
"id": "976439548",
"type": "apple-curators",
"href": "/v1/catalog/us/apple-curators/976439548"
}
]
}
Using this ID, I can get more information like the editorial notes, kind, artwork, etc.
If I use MusicKit to get details about the playlist:
let id = MusicItemID("pl.047294ae14a24e5993d1f7ab2b127188")
let request = MusicCatalogResourceRequest<Playlist>(matching: \.id, equalTo: id)
let response = try await request.response()
guard let playlist = response.items.first else { return }
print(playlist.curatorName)
It does not expose the Curator object but only the curatorName.
How can I access the ID of the curator?
Hi there!
I am trying to fetch a record label's top and latest releases. For example, for "Big Machine Label Group", I can see the top and latest releases on Apple Music.
I get the latest and top releases if I use the endpoint to get a catalog record label and query parameters to extend.
https://api.music.apple.com/v1/catalog/us/record-labels/1552967199?views=top-releases,latest-releases
However, I am getting nil for these values using MusicCatalogResourceRequest. Here's the code:
let request = MusicCatalogResourceRequest<RecordLabel>(matching: \.id, equalTo: "1552967199")
let response = try await request.response()
guard let recordLabel = response.items.first else { return }
print(recordLabel.topReleases)
print(recordLabel.latestReleases)
I cannot add properties for these either to get detailed info because I think there is no PartialMusicProperty when Root is RecordLabel.
Can you point me to what I am doing wrong?
Hi there!
I know that this is not related to MusicKit but Apple Music API, but I am curious to know where to find the activities to use this identifier?
Get a Catalog Activity endpoint:
https://api.music.apple.com/v1/catalog/{storefront}/activities/{id}
If I use the example ID given on the page, I get "Resource Not Found" error.
So, where do I get the activities ID?
Hi there!
I am trying to map the Apple Music API endpoints to MusicKit. For example, I am looking at the catalog playlist endpoints.
To get a catalog playlist by its identifier, it is:
let request = MusicCatalogResourceRequest<Playlist>(matching: \.id, equalTo: "pl.f4d106fed2bd41149aaacabb233eb5eb")
let response = try await request.response()
print(response.items)
For multiple identifiers, it is:
let request = MusicCatalogResourceRequest<Playlist>(matching: \.id, memberOf: ["pl.f4d106fed2bd41149aaacabb233eb5eb", "pl.4b364b8b182f4115acbf6deb83bd5222"])
let response = try await request.response()
print(response.items)
To get its relationship like more by curator and featured artists, I can set the properties:
var request = MusicCatalogResourceRequest<Playlist>(matching: \.id, equalTo: "pl.f4d106fed2bd41149aaacabb233eb5eb")
request.properties = [.featuredArtists, .moreByCurator, .tracks]
let response = try await request.response()
print(response.items)
My question is, how can I map the endpoint Get a Catalog Playlist's Relationship Directly by Name" to MusicKit:
https://api.music.apple.com/v1/catalog/{storefront}/playlists/{id}/{relationship}
The possible value of the relationship can be curator, library, or tracks. Where can I set these relationship values in the MusicKit request?
Thank you!
Hi there!
I was using the Apple Music app and stumbled upon Categories. For example, if you search for Apple Music Party, the first result is a Category that shows a list of playlists.
How do I access these using MusicKit? Is Categories Music exclusive only or available to third-party developers?
Hi there!
I was experimenting with the MusicCatalogChartsRequest. I have one doubt, and I do not know if it is the intended behavior.
If I have the kinds as [.cityTop] and the types as [Song.self], why does it print the city playlists and the top played playlists?
Ideally, it should print an empty array, right? As I have only Song as a type?
var request = MusicCatalogChartsRequest(kinds: [.cityTop], types: [Song.self])
request.limit = 1
let response = try await request.response()
print(response.playlistCharts)
The output is:
[MusicCatalogChart<Playlist>(
id: "city-top:cityCharts",
kind: .cityTop,
title: "City Charts",
items: [
Playlist(
id: "pl.db537759ae3341eaa600bc5482209f7c",
name: "Top 25: Mumbai",
curatorName: "Apple Music",
isChart: true,
kind: "editorial",
lastModifiedDate: "2022-06-21",
url: "https://music.apple.com/in/playlist/top-25-mumbai/pl.db537759ae3341eaa600bc5482209f7c"
)
],
hasNextBatch: true
), MusicCatalogChart<Playlist>(
id: "most-played:playlists",
kind: .mostPlayed,
title: "Top Playlists",
items: [
Playlist(
id: "pl.f4d106fed2bd41149aaacabb233eb5eb",
name: "Today’s Hits",
curatorName: "Apple Music Hits",
isChart: false,
kind: "editorial",
lastModifiedDate: "2022-06-21",
shortDescription: "Drake gets loose with “Sticky”.",
standardDescription: "Among the many surprises of Drake’s <i>Honestly, Nevermind</i>—not the least of which is the album’s very existence—is that it isn’t really a hip-hop album at all; he’s mainly singing. But “Sticky” is one of the few tracks where the project’s commitment to exploring dance music—courtesy here of production work from Australian artist RY X and Gordo (aka DJ Carnage)—meets actual rapping. Add Today’s Hits to your library to stay up on the biggest songs in pop, hip-hop, R&B and more.",
url: "https://music.apple.com/in/playlist/todays-hits/pl.f4d106fed2bd41149aaacabb233eb5eb"
)
],
hasNextBatch: true
)]
Thank you!
Hi there!
I have been trying to play the music videos we get from Apple Music API and have been unsuccessful.
Here's my code:
var video: MusicVideo
var body: some View {
VideoPlayer(player: AVPlayer(url: video.url!))
}
I know the URL from the MusicVideo is not in a music format but just the URL to the video in the Apple Music catalog.
How do I go about playing it without using something like MPMusicPlayerController.systemMusicPlayer.openToPlay(queueDescriptor) and provide an in-app experience (and not take the user to the Apple Music app)?
I am working on an app that requires to fetch all properties of a music item. Instead of adding all the items, is there a way to just say .all that adds all the properties applicable for the music item?
Example:
var request = MusicCatalogResourceRequest<Song>(matching: \.id, equalTo: song.id)
request.properties = [.all]
// Instead of
request.properties = [.audioVariants, .albums, .artists, .composers, .genres, .musicVideos, .artistURL, .station]
Thank you!