[ Music ]
[ Applause ]
Hello, everyone, and welcome.
My name is Betim Deva, and I'm an engineer on the Apple Music team, and I'm excited to share with you some updates that we have made to MusicKit.
MusicKit was announced last year, and it enabled developers like yourselves bring customized music experiences within their apps.
This year, we are announcing Apple Music on the web, which will allow you to bring the same kind of music experiences for your websites.
We have a great web player ready for you to embed, and we are introducing MusicKit for the web, which will allow you to integrate Apple Music into your websites.
We will talk more about Apple Music on the web in a little bit, but first, let's take a look at some exciting updates on MusicKit.
It's been great to see how app developers have incorporated Apple Music into their apps.
For instance, we all know and love making music videos with musical.ly.
When you find new music in this app, you can easily add it to a playlist.
Houdini makes joining Apple Music simple.
It allows you to transfer your playlists to Apple Music.
And Stationhead turns your playlists to radio stations.
It allows you to broadcast your music and your voice to the world.
And lastly, Ola is the biggest ride-hailing service in India.
We have been partnering with them to bring the Apple Music experience within their fleet of cars.
Since MusicKit was announced last year, we got a lot of feedback for providing a way to look up content using the International Standard Recording Code known as ISRC.
I am happy to report that this has been added, and it will enable you to precisely match songs and music videos in the Apple Music catalog from virtually any other source.
Another enhancement to MusicKit is the addition of iCloud Music Library APIs.
Once the user has given authorization to your app, you can now provide them with ways to interact with their music library from within your app.
These APIs enable your users to browse, search, and add content to their music library.
You can also provide a way for your user to create playlists and add songs to an existing playlist, all from within your app.
Last year, we gave you Apple Music APIs for our catalog.
This year, we added the iCloud Music Library APIs.
We think this is a great set of music APIs.
If you have been using our existing iTunes Search API, we encourage you to migrate over to Apple Music APIs now.
Now, I would like to invite my colleague DJ to the stage to talk about Apple Music on the web.
[ Applause ]
Thank you, Betim.
This year, we're excited to be announcing MusicKit on the web.
Last year, we talked all about the great ways for you to add Apple Music to your iOS apps.
This year, we're bringing all of that same great functionality to the web.
So let's talk about the components that make up MusicKit on the web.
Last year, we added access to the entire Apple Music catalog with a REST API.
This year, as Betim mentioned, we're launching new additions to that REST API that'll let you access the iCloud Music Library for the logged-in user.
We're also launching the MusicKit JS library.
Makes it really easy to use both of those REST APIs in the browser, and it gives your users the ability to play back full songs from the Apple Music catalog and from the iCloud Music Library right in their browser.
Before we dig into MusicKit JS, I want to show you the Apple Music web player.
A few weeks ago, we launched a new embeddable player.
It works great both on the desktop and on mobile browsers.
These embeddable players are a simple way for you to add full song playback from the Apple Music catalog right to your website.
We have players for a single song, an album, or a whole playlist.
You can find the embed code on the Apple Music preview pages or right within the embeddable player itself.
All you have to do is copy and paste into your own website.
These embeddable players are great for full song playback on third-party websites, and we've also enabled that functionality on the Apple Music preview pages.
So the embeds are powered by MusicKit JS, which we're also releasing so you can build your own great music experiences.
So let's talk about the functionality.
First and most importantly, you'll be able to play back full songs from Apple Music in the browser.
It works on all modern browsers without the need for any plug ins or external dependencies.
So for playback, we need to authorize the user.
We'll handle that for you to ensure that the user is an Apple Music subscriber.
Once you have that queue of songs, you'll be able to control.
You'll be able to play, pause, and skip to the previous or skip to the next track.
And we're also going to keep track of the Now Playing metadata for the song that's currently playing or currently loading so you can render your UI off of it.
So let's talk about how we would build a simple player for the web.
Then, you need to provide your developer token.
You can generate this using your private key.
We have a really great way to use declarative HTML markup.
You can add some markup to your page.
For example, buttons for sign in, sign out, or playback controls.
We'll handle wiring up those elements to the appropriate functions in MusicKit.
Then, we're going to add some play buttons.
We'll use some content IDs or some URLs from the Apple Music catalog that'll let the users start playback.
So let's take a look at the code for this.
We're going to add some buttons for signing in and signing out.
Some buttons to control playback.
Here we have a play button, a pause button, and a next track button.
We'll add some elements that we will render in metadata about what's currently playing.
Here we can get the playlist name, the title, and the artist name, for example.
And then, we have some elements that let you show the progress through the track that's currently playing the playback duration, the playback time, and the playback progress.
So I'd like to bring up Jae Hess to the stage to show you how to use the MusicKit JS to build that simple player that we just talked about.
[ Applause ]
So we're going to get started here, and I have a basic HTML template on the right side in Xcode that's already linked to the MusicKit JS library.
And on the left side, I have a Safari window open that's running a live reload server.
This way, any changes I make to my markup will be reflected directly on the left-hand side.
To get started with MusicKit JS, the first thing we need to do is configure it for our use.
And with declarative markup, we have a very simple way to do that using meta tags.
We can specify our application name as well as provide our developer token.
Next, to get the functionality we want, we're going to put a button on the page for the user to click.
And when this button is clicked, it's going to take a playlist from the Apple Music catalog, set a playback queue, and start playback in the browser.
Here I'm feeding a content URL that I got from iTunes on the desktop for a specific playlist I'd like to embed.
This playlist is the "Today at Apple Music" playlist.
[ Music ]
And so with that 1 simple line of code, we have full playback of the "Today at Apple" playlist in the browser.
While this is great and it offers a really good solution, we probably want to add more controls and more functionality for the user to use.
The first thing we want to do is allow the users of your application, which are subscribers of Apple Music, to log in and log out.
And we'll do that by adding Authorize and Unauthorize buttons to the page.
We use the Apple Music Authorize and Unauthorize attribute, and MusicKit JS manages the state of displaying those buttons for me.
I've logged in previously, so you see that the state reflects, "Sign out of Apple Music."
Next, we want to add some playback controls.
And we can specify these using the Apple Music attribute, and we can specify things like skip to previous item, pause, play, skip to next item.
We can add Now Playing information for the user to see the current playing item in the queue.
And here I've specified the playlist artwork URL, and I can specify the height and width I would like that to render.
And I also have access to any data attribute that's available on the media item.
So I can specify things like playlist name, the title of the track, as well as the artist name.
Underneath, I've specified that I would like the current playback time to be loaded into the HTML time element.
So when the page reloaded, nothing's there for Now Playing.
That's because we aren't playing anything, so let's fix that by adding buttons that would allow the user to queue up playlists.
I'm going to paste in 16 playlists.
And when the user [ Music ]
Now, using the playback controls, I can pause playback.
I can skip to the next item.
[ Music ]
I could even go back to that.
[ Applause ]
Thank you, Jae.
The declarative markup is a very straightforward way to add basic functionality.
Let's talk about some more advanced usage.
We can fetch metadata from the catalog by ID.
We can search for content within the Apple Music catalog.
We can browse the iCloud Music Library for the logged-in user, and search also works within a library scope.
We can set and control that queue of songs directly.
And we can react to playback events, and we drive our UI off of this.
So we're going to look at some code.
First, we're going to use the MusicKit getInstant method.
MusicKit is a singleton because you can only play back a single song at a time, so we're going to assign this to that music variable, and we'll use that throughout the rest of these examples.
You can look up a song by ID.
The song method takes the ID, and then you need to supply a callback.
And this is a promise.
You'll see that promise model used throughout MusicKit.
You then get a content object back, and this content object shows you the attributes of that song and any relationships for example, the artist and the album.
As Betim talked about earlier, if you don't have a content ID, you can do the exact same lookup with a query filter for the ISRC.
The objects that get returned are the same as the previous example.
We have a batch API if you want to return a array of song objects with a single network call, and this also works for albums and playlists.
We can let the user play back content from within their iCloud Music Library.
So these APIs live under the library scope.
You can get a list of songs, albums, and playlists.
These APIs are paginated, so you can fetch just a subset [inaudible] manner, and you can unload more in as the user pages through or scrolls through your application.
You could search the Apple Music catalog.
Here we're going to search for just songs, and then the second example, we'll search for both songs and albums at the same time.
You can also supply a limit to limit the number of results returned.
You can do the same query, but scope it to within the user's iCloud Music Library.
Here we're using the exact same search method with the same parameters, but we're doing it under the library scope.
Next up, we have authorization.
We're always going to handle authorization right before it's needed when playback's starting or when you're trying to access the iCloud Music Library for the current logged-in user.
You could also trigger it yourself if you'd like.
Perhaps you want to force that at the beginning when someone comes to your website.
When the user presses a button, you can start playback.
You do this using the setQueue method.
Here we're supplying the idea of an album, and MusicKit will handle fetching the metadata and then setting that queue.
If you have a content object that we saw previously, you can pass that in directly, and it will figure out what to do.
setQueue returns a promise.
When the queue is fully loaded, you can start playback.
Here we're going to start playback automatically with music.play.
Once those songs are playing, you might want to be able to control that.
You can skip to the next or previous item.
You can pause.
You can present actions in your UI that will let a user quickly add those songs, albums, or playlists they're browsing to their own iCloud Music Library.
We have an addToLibrary method here.
You can do that same, you can do those same 3 calls in batch.
Here we're adding those same 4 items as the top example, but we're going to do it in a single network call.
So let's look at events next.
MusicKit's going to fire events that you use to drive your UI from.
We do this because MusicKit needs to own the audio element in order to do that full song playback.
Here we're going to use addEventListener, which is going to be a very familiar pattern if you've done DOM scripting in the past.
We're going to dive into just a couple of the events to give you an example.
The mediaItem WillChange and the mediaItem DidChange events fire when the Now Playing item in the queue changes, when the first song you're playing transitions to the second song.
You can use this to trigger an update to your UI that shows the song that's currently playing.
When you actually begin playback, the playbackState changes events are fired.
Here we have a will and a did change event again.
For example, you can know when a song is loading, when it's playing, or when it's paused, and then you would update your UI appropriately.
This event is going to give you the old state and then the new state that it's being transitioned to.
As the song is playing, you'll get playback progress change events, and this event has the current playback progress as a percentage.
You can use this to update a progress UI.
And you're also going to listen for any media playback errors.
The mediaPlaybackError event will fire.
You can catch that and then present the appropriate error messaging to the user.
So I'd like to bring up Jae back to the stage.
[ Applause ]
As DJ mentioned, we're going to take the previous example and we're going to extend it to add playlist search.
Now, I've taken the, off stage, I've removed a lot of the stuff that we did from the previous example, but I've left some things in the page.
The major change we've done is we've added an input element for the user to search as well as 2 DOM containers that we can put those search results into.
MusicKit JS doesn't offer an opinion on a library or a framework that you would be using with your application, so for this example, our CSS has been prebuilt off screen.
We have some template helpers that we've built in a separate file as well.
And we'll notice that our markup looks a little weird on the left-hand side.
We got a couple of buttons that are magically floating, and the artwork is obviously empty.
And this is because MusicKit JS assumes that if you're configuring it with the meta tags, that you want declarative markup enabled.
We can configure MusicKit JS by listening to the MusicKit loaded event that's fired on the document.
This lets us know that MusicKit JS is ready to be used and configured and playback can happen.
We can configure our application name just like we did with the meta tags, but we now have an attribute that says declarativeMarkup that we can set to true, which lets MusicKit JS know that we're running in a mixed mode and we want those declarative markup features to be enabled.
Next, I'm going to add a search handler.
It's not specific to MusicKit JS, but I did want to walk through that when the user presses Enter on the search box is when we're going to fire our callback to do the search.
And we can implement that by using the search method off of MusicKit's API property.
This will perform the search against the Apple Music API, and we can specify any query parameters that the Apple Music API accepts with a configuration object.
So we can specify we want to search, we want to limit the search to playlists and that we want our results to be limited to 8.
We have our custom templating, but I want to highlight these 3 lines, which is where we tell our MusicKit instance to take the artwork that the user has clicked on, and we want to set the playback queue to that playlist ID.
That returns a promise where we can call music.play, which will start playback for the user.
And then, we have our custom rendering as well.
I perform a search for "a list."
We'll see 8 catalog results from the Apple Music catalog for A list playlists.
It would be nice if the same search could apply to my personal iCloud library as well.
And we can do that in almost the exact same manner, except the search method is off of the library property instead of the API property.
This lets MusicKit JS know you're looking for the cloud library.
Set playlists and set the same for 8.
And then, the code looks exactly the same with setting the queue and starting playback.
If I perform that same search, we'll see my iCloud Music Library results as well as the catalog library results.
And I can click, and we get playback of the cloud library item as well.
[ Music ]
Looking at the Now Playing screen, or the Now Playing information at the bottom makes me realize that it's missing a progress indicator to let me know how far through the current playing track we are.
And we can add something like that by simply listening for the playbackProgress DidChange event that MusicKit JS provides.
Here we add an event listener to the MusicKit instance, listen for playbackProgress DidChange, and have a custom renderer to render progress when we get that event.
So we can look for A list again.
And this time, when I play that song, we see our custom progress bar rendering.
Now, there's a lot more we could get into with MusicKit JS, but I'd like to bring DJ back up to kind of summarize what we've gone over today.
[ Applause ]
You can now bring great music experiences to your websites.
We're looking forward to seeing what you can build with it.
We have some great documentation available, and we have a lab coming up right after this session in Technology Lab 3.
Happy to answer any questions you have.
[ Applause ]