Bring your music service to HomePod and help users enjoy your content hands-free throughout their home. Discover how to build a great integration from start to finish. We'll take you through how Media Intents work, configuring your app as a preferred music service on HomePod and integrating directly with your cloud backend, providing a personalized playback experience for individual accounts with the help of voice recognition (where available), and more.
To learn more about Media Intents, check out "Expand your SiriKit Media Intents to more platforms" from WWDC20.
Hi. I'm Jeri Mason. I'm a software engineer on the HomePod team. And I'm going to walk you through bringing your media service into the home with SiriKit Media Intents, now powered by Cloud Extensions.
Let's start with everything you need to start developing.
First, we'll cover some important prerequisites for developing a service effectively: how to configure a test home, how to set up your HomePod for testing, how to set up your iOS device for development and, finally, adopting the MediaSetup framework in your app for onboarding your service into a home.
Once you've taken these steps, you're well on your way to creating an awesome playback experience on HomePod for the people who love your content.
Let's dive into the prerequisites. To support SiriKit Media Intents on HomePod, your service must already support Media Intents in your iOS app. You'll need to apply for the program on developer.apple.com/siri. After you apply, you'll receive more details about accessing the Cloud Extension API specification, which your service must implement. Then you can register your service with us to get entitlements and profiles to begin development. And finally, before a HomePod will be able to reach out to your service via the Cloud Extension APIs, you must implement an OAuth flow and a Configuration Web Service defined in our specification.
Let's talk more about registration. To register your service, you'll need to provide your service name, a public signing key that you create to verify the service on devices, a static URL to retrieve an icon for your service from iOS devices in the home and a list of bundle IDs of apps which are using the service. This information will be used to create a development profile you can install on your test and development devices. Only devices with the profile will be able to test your service.
It should come as no surprise, since the Cloud Extension APIs use Web technology, we have adopted authentication using an OAuth 2.0 endpoint. But since your app takes the role of a trusted client, a service that implements client credentials flow is required. A unique ClientID and ClientSecret is required for each service account that is added to a home. Even though it's uncommon for this flow, the issuing of renewal tokens is recommended, so as to avoid a common reuse of these credentials provided directly to the Auth service. This is because without a renewal token flow, the ClientID and ClientSecret could be long-lived. As long as someone is using your service from a home, either a renewal token or the original authentication must be supported. Your iOS app must be able to supply these credentials by requesting them from your service and providing them to iOS media setup APIs.
With these prerequisites met, let's talk about configuring a test home.
While you're developing and testing your service, having a dedicated test home in the Apple Home app is strongly recommended. That way, you won't affect any HomeKit homes you may use personally, and you only have to manage the configuration of the devices in your test home. You'll also want to have multiple test iCloud accounts so you can test your service with different accounts in the same home. And naturally, you want to make sure that you're using the same accounts on the HomePod and your iOS test devices.
Creating a new home in the Home app is easy. First, tap Home Settings, add a home, type in the name of the home.
Now you can add people who are your other test users.
Okay. Now that you've got your test home set up, you'll need to add a HomePod to it and then set it up.
You'll usually want to install the latest tvOS Developer Beta release on your HomePod or a release Apple currently advises for development. It's important to know that you cannot use a regular tvOS release until you're ready to submit your app. Until then, you'll also need to install a development profile provided by Apple for your service in the Home app on iOS. Be sure to repeat this process for each device you plan to test in your home. When you update to a new version of tvOS, you may have to reinstall the profile.
To install a profile on a HomePod, first make sure your test home is selected in the Home app.
Open the profile on an iOS device. Select HomePod as the device type to install.
Tap Install, enter your passcode, consent to the agreements and tap Install to complete installation.
You can then choose which HomePod in your test home to install the profile to. That's it.
You'll need to set up your iOS devices for testing and development as well.
You'll need to be using a developer beta on your iOS device. Usually, you'll want the version that was released at the same time as tvOS, but check with Apple for the latest recommended version.
Like the HomePod, you'll need to install your development profile. Tap on the mobile config bundle in an e-mail or iMessage attachment, choose to install it on your iOS device and follow the typical flow for accepting and installing profiles in Settings.
It's a good idea to check that your iOS device and your HomePod devices are running the expected releases at this point.
You can repeat this setup for any test devices you may need. They can be iPhone or iPad devices.
With your devices configured, you can now adopt the MediaSetup framework in your app. This is what, ultimately, will allow people to set up your service for use in their home.
To use MediaSetup, you'll need to implement functionality in your app to retrieve or create OAuth material, choose a Configuration Resource URL appropriate for the account being onboarded, and then you'll have to add the Entitlement you received after registering your service with Apple. Otherwise, you won't be able to use the framework.
Make sure to add a prominent, discoverable onboarding presentation context in your app to trigger the account installation flow using MSSetupSession. People will be guided through the home account setup process. The setup process will use your OAuth service to retrieve API tokens and verify your Configuration Resource URL is properly signed and parsable. So all the prerequisites I mentioned earlier must be met before a successful setup will complete.
You can get more details at developer.apple.com.
Now that your development and test environments are ready, a HomePod in your test home can reach out to your service. Let's go over the system architecture of handling intents in the cloud.
On iPhones, iPads or Apple TV, when you ask Siri to play media in your iOS app, you either handle intents directly or via an extension in your app bundle. Typically, when someone asks Siri to play content from your app, Siri processes this request, identifies your app bundle as the target of the intent and loads your app extension, which implements the intent resolution. Your extension can communicate with your services, and the handling of the intent will trigger launching of your app to begin playback or just signal it to handle changes. With Cloud Extension, the process of resolving those intents moves from your extension implementation on device to an API on your service as the HomePod directly reaches out to your Cloud Extension Intent endpoints instead. The Cloud Extension API is a Web API specification designed for Intent handling. It uses OpenAPI schemas to define objects that closely follow the SiriKit Intent APIs you're already familiar with on iOS. The configuration URLs I discussed as we were getting started are also part of the specification, and their content is defined in it. Each SiriKit Media Intent type has a protocol endpoint configuration, and we can reach out to different URLs as necessary for your implementation.
The protocols supported are: play media, add media and update media affinity.
You may notice the search protocol is not provided on a HomePod because there's no context to display the results on HomePod, unlike on iOS devices. Let's look at what happens when I tell Siri to play content.
When I tell Siri, "Play 'Strange' by Celeste," this triggers the PlayMediaIntentHandling flow.
The HomePod starts resolving a PlayMediaIntent with a media search object. It's serialized in JSON and sent to your service. Once you match the media search to something appropriate in your catalog, it'll create a response object. The media item has an identifier, type and additional metadata that Siri may use to formulate dialogue to tell the user, "Now playing 'Strange' by Celeste." Additionally, this protocol has a handle method that is called after resolving other fields on the intent. If the fields on the intent are already acceptable, there's no reason to delay returning the final handle method. So include it in your response to the initial request. Not doing so causes extra round trips to your service unnecessarily and slows down the intent response time. Inside a handle response, you can include an object called UserActivity, which contains a persistentIdentifier and userInfo that will be returned to your service when the HomePod starts playing your content. Your service replies with these results and may begin to form a queue of content to play based on the request as the HomePod processes these results and starts a playback session.
Now, when media is playing from your service, let's consider what happens when I tell Siri, "Add this to my library." The AddMediaIntentHandling flow starts with resolving media items, as before, except now that Siri knows what's currently playing from your service, an identifier for the currently playing content is also part of the media search parameters. As before, your service must identify the content playing and add it to the library of the account used to make the request. You'll then create an object to represent the ResolveMediaItem and bundle together the handle method result that indicates this operation was successful.
Then you'll return that response to the HomePod, where Siri will confirm the result.
And finally, when I tell Siri, "I like this!" the UpdateMediaAffinityIntentHandling starts, again with resolving media items as before, and your service will identify the content, create a ResolveMediaItem result, register this affinity against the taste profile the account used to authenticate the request, and like the previous examples, include the handle method result. These context-specific requests will only include a content identifier if your service is the service playing on the HomePod when the request is made. Also, don't forget that listeners can just say that they want to add something that's not currently playing to their library. In this case, you'll be provided with media names and artist names to resolve. This is a less common use case though.
Let's see a basic play media request and response as it looks in the protocol as JSON.
If I ask my HomePod the most basic request, to play music on your service, every request to the intent endpoints on your service will provide a session description before the first item to resolve. Most objects in the specification include the Cloud Extension version number of the object being presented. Your service should support older versions of these objects when possible. Newer versions also should be backward compatible up to a new major version number.
The intent resolution session has an identifier, which is also carried in a header on HTTPS requests. It will remain the same during resolution of the intent interaction, and if multiple requests are made to resolve this intent, this identifier will be consistent between them.
Two time stamps are provided-- the UTC time when the request was prepared and a deadline time after which the client will time out the request. If the deadline is missed, Siri will explain the service cannot resolve the intent. Providing a timely response is important. Time-outs happen after ten seconds, so consider how you can break up the work of returning intent results and preparing content for playback so that your service can take advantage of the time between requests from the HomePod. These constraints and player context objects will be discussed in more depth later. They provide important information about what's happening on the HomePod when the request was made.
Most requests start with a resolveMediaItems method on the protocol. The most important part of this request is in the parameter and intent object. This is a PlayMediaIntent, and all PlayMediaIntent objects have a mediaSearch that defines attributes of media parsed by Siri from speech. Other parameters of the intent include information about whether I asked to play the content shuffled or repeating, or to resume playing the content, or whether I said to play something next or later instead of now. This object should appear familiar to you if you've already handled PlayMediaIntents on iOS. The response you return from this request should look familiar too, but there are a few new twists. Inside an array of results, you provide the method name, a result object, in this case a resolutionResult array with one item, the resolutionResult class appropriate for this method, which is, in this case, a success property. And as you can see, this resolvedMediaItem represents Your Favorites, a station based on my taste profile.
Here's something new for Cloud Extension. Each method you process should return a metrics object that describes how long in seconds it took for your service to provide results. Apple may use this data in aggregate to roughly determine the experience of listeners and better evaluate when delays are caused by network connectivity. You can see the next result item is peeking around the break here-- the handle method for this protocol. The result of a handle method is a response object appropriate for that intent, which has a status code and then a description of a UserActivity object. Think of user activities as a memento representing the intent result.
For playing MediaIntent results, the UserActivity is used when starting or modifying playback of your content, whereas on iOS devices, the UserActivity object is made available to your app when it's launched. On HomePod, your service defines the listening experience with another Cloud Extension API for media cube playback.
Up to this point, intent handling should have been super familiar if you've implemented SiriKit Media Intents on iOS previously. Playing media from your cloud service is the driving feature of Cloud Extension. And in this part, I'll provide you the concepts and specifics to implement media queues in the cloud.
Let's review again what happens when a person asks Siri to play media on a HomePod. The request is processed by Siri, and our Cloud Media Service extension is chosen to handle it on behalf of your service. The HomePod uses the Cloud Extension APIs implemented by your service to resolve an intent. Once we have resolved the intent, a Cloud Media Player component will contact your service's queue endpoints, and it's those queue endpoints which determine what content to play. In most services, a content distribution service often provides the actual audio files to play. You might notice that there are two HomePods depicted here. In certain situations, the HomePod that resolves the intent may not be the same HomePod that is playing your content. If a family has several HomePods, the HomePod closest to someone in the living room might respond to their request even if your service had already been playing to multiple locations in the house and that session had started in the kitchen.
Let's see how your service provides content via queues. I'm gonna walk you through some high-level concepts of media queues, including various idioms and use cases for different listening experiences. And then dive into details of managing queues and their lifetime.
And finally, I'll explain how your service defines playback controls on HomePod. Okay, let's explore what it means to provide a queue from your service.
All listening experiences supported by Cloud Extension are defined by playing a Queue of Content items. Queues are created or modified by submitting User Activity objects resulting from intent resolution to your service. Your service returns a Queue of Content items all at once or, more likely, in segments. Let's look at some use cases and how to conceptualize them as a queue. Internet radio content often starts with a promotion track, then many songs, quite often an advertisement, more songs, and then it continues indefinitely until a listener stops playback. On-demand music requests can resolve to a single album or other collection like a playlist and be constrained to a finite queue. And live streaming content will often have a single content item which forms a minimal queue response that has one piece of content referencing the live stream source.
Content items in a queue can be described with an identifier, a URL and various descriptive attributes like the name of the content, the artist and so on. Content selection can take any number of algorithmic forms in your service from a rigid album track order to a completely dynamic selection.
Queues are intended to support all these use cases. Now let's talk about the various ways you can represent your sequence of content items in a queue idiomatically.
The idioms I'll be describing are variations on using a queue broken into segments for different purposes. So here we have our content conceptually realized over time described by objects. Say these four pieces of content are the complete listening experience you want to represent as the result of an intent resolution. You can package them into a queue object which has its own identifier and a simple array of all these content items. That's a pretty basic queue object.
This is the static content idiom where a queue contains a finite, nonchanging list of content. It may fit into one queue segment or it might not, but conceptually, it is a rigid list of content items that could be played in order. Use cases for this idiom include the on-demand music request for an album or a playlist, or the live stream use case, where the queue is a simple wrapper for one piece of content that streams indefinitely.
Your service can have more complicated queues, however. Queues can be split into segments, and they internally link to the next content and previous content items via URL references. The HomePod will retrieve these segments as your service defines them, and any particular segment can be dynamically generated and return different results as the listening session moves to the new segment, either by transitioning naturally or by skipping forward or backwards through your content items. This particular example might fit a use case where a service provides an advertisement inside a set of fixed content segments. And each time the player encounters Queue segment B, a different advertisement might play. This means your service queue content is retrieved dynamically, so your service will experience more requests for each queue segment than as if it is entered.
Your service may want to have the most discrete control over content and playback options. And in the fully dynamic idiom, every queue segment contains one content item, and a new content for the queue can be retrieved dynamically as the listener proceeds through it. This is a popular idiom for Internet radio use cases because the queue is typically of indefinite size. And also because the queue content itself is a function of listening behavior. Skipping tracks and providing content affinity through Siri intents may change the taste profile associated with the account, and therefore, upcoming content items may be selected differently. Naturally, this is also the idiom that represents the most request processing on your service.
Since these idioms are different ways of using the same queue architecture, your service can provide queues using any combination of these idioms, and you can even choose alternate idioms to implement for a particular kind of request. They're useful for considering trade-offs in complexity and capability.
Enough theory. Let's talk about how your service creates and manages these queues.
When a PlayMediaIntentHandling request returns from your intent endpoint, your service should start creating your representation of a queue, because shortly afterward, a request on your queue play media endpoint will be made to retrieve the initial or complete queue segment.
Each segment can link to a next and previous segment as your service desires, providing a set of content that is potentially endless or circular. Usually, a newly retrieved queue starts playing from the first content item. To support resuming playback from a prior session, a playPointer object can be provided in the initial queue segment, and playback begins from the content item indicated at a time offset you provide. To support smooth, gap-less playback, as a listening point is near the end of the last content item in the queue segment, the next segment will be retrieved and appended at a configurable preroll interval.
Let's take a look at actual JSON objects exchanged with your service after handling a PlayMusicIntent successfully. Like all requests, we begin with the client's version. There may be a nonhomogeneous set of devices in the home, so the version supported by the device playing your content may actually be older or newer than the one that resolved the intent. The identifier for PlayMedia request inherits the identifier used in the intent resolution. If for some reason the playback has to restart though, this identifier might be a new, unique identifier. You should not rely on this for linking your intent results with a queue, where the user activity is much more appropriate, though these identifiers may be useful for debugging. A constraints object defines certain limitations for playback on the device. You may remember it's provided on the intent endpoints as well, and I'll go into more detail about these later. Finally, if your intent resolution returned a UserActivity object, that object is included to provide context for how your queue endpoint should prepare content items for this session. Your service responds to the request with a queue object. It has an identifier that will be presented later in reporting and for context and intents and typically will remain the same between different segments of the same queue. You can provide an array of content items to play through, though in this small example, only one item is provided. There are attributes describing each content item, an identifier for each item, which must be unique to this queue, if not your entire catalog, and a URL to the body of the content. Here's where the previous and next content links are described for the segment. The body of the response from these URLs is another queue segment definition much like this one. Finally, by specifying a preroll of five seconds, approximately five seconds before the end of playback of the last content item in the array, the next content URL will be retrieved to extend the queue content forward. That's all a HomePod needs to start playback of your content. Now, what if someone asks Siri to play a different track next while already listening to your queue? This is indicated in the PlayMediaIntentHandling protocol by resolving the playback queue location to next. If the HomePod is playing the second content item in this example queue, you probably don't want to provide a whole new queue result. In this case, you want to literally insert one or more content items inside this queue. You do this by providing a queue segment from your PlayMedia endpoint that has the same queue identifier as what is currently playing and an insertPointer object as to where the content carried in the segment should be inserted into the current queue segment. If no specific content identifier is provided for the insertion point, the items are also inserted after the currently playing item. This behavior lessens the impact of race conditions as the playing content in transition between resolving the intent and updating the queue. Using this technique is recommended even if your service uses the fully dynamic queue idiom. Finally, let's cover some nuances of queue management.
While it will result in the largest number of requests on your service endpoints, the fully dynamic idiom features the most flexible way of providing content for most media services and is conceptually easier to manage if your content is not completely static in nature. Despite the queue protocol being flexible enough to provide any set of content when navigating a queue, it is best to maintain consistency in your queue history if you allow listeners to navigate backwards in the queue.
To implement repeat and shuffling behavior, your service must identify these options from the intent handling and provide queue content in a shuffled order or repeat indefinitely by techniques such as a next content URL that leads to previously played items in the queue. These behaviors are impossible to perform without full knowledge of the queue extent so the HomePod does not even attempt to support them natively.
Next and previous content URLs can be templated so a small amount of context can be provided to your implementation such as the last content item in the queue segment or currently playing activity queue or content identifiers. If your service implements the queue update user activity endpoint, you can even update playing queues via reporting events. I'll talk about reporting shortly.
I hope you have a good grasp of the rich set of queue management tools your service can use to provide flexible and timely content retrieval and updates.
Finally, in this section, I'll expand on controlling playback and defining how listeners interact with your service.
Not every kind of queue is the same, and not all content in a queue can be treated the same. For example, the Internet radio use case typically supports only forward motion through the queue. Additionally, when an advertisement is playing, you may not want to support skipping that content at all. Skipping ahead in radio station queues may be limited by many variables-- premium subscriptions, freemium models, other more esoteric limitations. The fully dynamic idiom is often the only way to support these requirements.
Moving between different content in a queue may be limited arbitrarily. Let's talk about how you define this interaction. Cloud Extension queue APIs let your service define interaction with PlayMediaControl objects you provide in the queue object. Each PlayMediaControl object can choose a predefined scheme which supports several common use cases. This set of defined interactions can be specified on each content item with a control attribute.
Let's look at an example control definition which might be appropriate for an on-demand service with advertisements interspersed with songs. You include these definitions inside a controls attribute for every queue object. In this example, there are two definitions-- the required default definition, which is used when any content item does not specify a control, and an ad definition that is specified on all content items that are advertisements. All control definitions have a prototype scheme. By default, the content items in the queue are going to be onDemand scheme, and for the ad content, the advertisement scheme. The scheme modifies the Siri dialogue when a user asks to move to the next content item. Siri may then reply that skipping advertisements is not permitted. The scheme also defaults all navigation commands to be disabled, though you can selectively enable them again. An example of enabling commands is also provided here, where the dislikeTrack and likeTrack commands, normally disabled by default, are being enabled by your on-demand content. You can see how, with a small set of control definitions linked to items in your queue, you can substantially customize interactions with your content. Finally, the control definitions also allow specifying options for user activity reporting, which is how your service receives optional command events, navigation information and play status of your content. These are all topics I'm about to cover next.
So far, you've seen how a HomePod reaches out to your service to resolve intents and manage a queue of content to play. Now I'll talk about how your service is made aware of playback events and can contextualize requests over time, starting with how listening activity can be reported to your service, how playback context is provided when already playing any queue from your service and, finally, how your service must respect certain playback constraints.
So let's start with reporting. Listener activity is reported using the media queue Update Activity endpoint in the Cloud Extension API. This endpoint is technically optional, but most services implement it to get status reports from the HomePod as people listen to content.
Your service receives reports for transitions and media control events such as skips, pausing, continuing playback and scrubbing in a track. Your queue content can be affected by these reports, especially if you've implemented a partially or fully dynamic queue idiom. Your service can even return new queue segments as a response. Since update activity requests are made asynchronously from content retrieval for your queue, returning a new queue on the report of a track skip may not present your queue content cleanly and might fight the normal transition logic, some audible jump in playback would likely occur.
Use queue responses from reporting only to completely change the playback or insert new content. Use content URL templating to get more context of why a queue segment was retrieved.
Let's look at an example request made to the update activity endpoint.
In this example, I asked Siri to skip to the next track. These simple interactions are not intents but media controls. In JSON, the report looks like this. As you can see, the type of report being made is tagged as a skip_next. The full set of reporting types is defined in the specification and includes natural transitions between tracks, scrubbing within a track and when a new queue replaces the existing queue. The nowPlaying context is provided, including the activity, queue and contentIdentifiers and an offset into the content that has currently been played. For transitions, a previously playing context is also provided. It represents the identifiers associated with the last content being played and the offset inside the content when playback transitioned. You might use this to update your listener's taste profile if they skipped quickly. But in this case, I listened to a good portion of that song, as you can tell in the offsetInMillis value. So your service may assume I probably liked it, at least enough not to lower its relative rating. And like other endpoints in the queue API, the user activity object is presented in full in case the user info data is useful for your service to recover state and quickly process this information. There are more advanced capabilities your service can use as well. For example, you can request playback interval reports as content is playing to know that a certain point has been reached or each time a particular repeating interval has elapsed. You can enable and receive reporting of certain MPRemoteCommandCenter commands when iOS devices control playback on the HomePod. Note that the remote commands for likeTrack and dislikeTrack are not the same as update media affinity intent handling. They're not voice intents, but simple taps from an iOS device anywhere in the house. While I discussed returning new queues previously, you can also update User Activity objects during playback by returning an updated version of the object.
Here is an example we saw earlier of custom control schemes which include activity definitions. The default control includes a playElapsedInterval of 60 seconds, which means that a report is generated every 60 seconds as content items that have no control attribute are played. But for items with a control attribute of ad, as soon as five seconds of the content have elapsed, a report is generated, and then another report is generated every ten seconds. There are several limits on reporting intervals defined in the specification.
Reporting provides your service a lot of data, but tracking that context in your service may be expensive as millions of listeners process intents. A session context can be provided to your service to help bridge the queue playback and intent handling endpoints context.
The session context is only available if the HomePod is currently playing media from your service. When I tell Siri I like a particular piece of content, your intent service endpoint receives a playerContext object, much like how the nowPlaying object discussed in the reporting section is sent on every report. Player context includes Content, Queue and User Activity persistentIdentifier values. These encompass three levels of definition I have introduced previously-- the Activity persistentIdentifier, which defines a potentially long-lived listening session, the Queue, which defines the current listener's experience and the particular content which is now playing at the time of the intent resolution. This item is also carried in the intent media search object, and you may be familiar with using it on iOS devices already. Consider whether session context is enough information for your service to avoid the need of implementing the update activity endpoint at all and handle more complex reporting events. In this example, request for UpdateMediaAffinityIntentHandling, the HomePod was already playing a queue from your service, so a playerContext object is provided to the intent endpoint. Inside the session object, you will find playerContext or a null value if your service is not currently playing.
If your service's taste profiles are explicitly driven only by media affinity and play media requests, player context may handle all of your requirements without implementing full reporting.
But before your service uses taste profile information from these tools, it also must honor constraints on usage sent with every request. In a home, there is a different kind of contextual awareness your service must know about and honor. Each HomePod can be configured with certain options that form constraints on your service. For example, a HomePod in a child's room might have an option to exclude explicit content from results. Whenever a request is made on this HomePod, it should not return explicit content. But a request to a HomePod in a bedroom that does not have the setting enabled should be allowed to return explicit content.
Constraints are not optional. Your service must follow the implications of the constraints presented. When a guest in my home asks to play some kind of content, they can make requests on your service and they temporarily use my account, but this interaction should not affect my taste profile. Since Siri has a pretty good idea what I sound like, we detect that the request was not made by me and tell your service not to use this request to change my taste profile. The constraints values must only further constrain existing limits of your service's account settings.
If your service has account-specific controls for similar restrictions, these should be combined to provide what listeners expect from your service.
Here's one more example of an intent request that starts with a session object and constraints definitions. They are small objects, but have a significant impact to how your service interacts in the home environment.
updateUserTasteProfile is a Boolean constraint that indicates whether or not the resolving of this intent is to be used for tracking likes, dislikes, play counts and any visible listening history your service associated with my account. When it is false, your service cannot assume that the account used is that of the person controlling or initiating the playback. It can also be false because this HomePod may have been configured to never contribute to my account's taste profile, even when recognizing my voice. Imagine I had a HomePod in my family room, and I regularly ask it to play music on behalf of small children. If I did not have a way to set this option, my favorite music station may be quite more eclectic than I like. allowExplicitContent is another Boolean constraint that reflects settings per HomePod and Home app. And your service must consider it for filtering explicit content in results from intents. In fact, if a particular intent request cannot be fulfilled because of lack of any nonexplicit content that matches the search, specific error results for resolvedMediaItem methods are provided in SiriKit Media Intents.
Finally, even hardware has constraints. Queue segments can only be a finite size, and that value is dynamic per device. If your queue is larger than this value, you must implement a segmented queue idiom to adhere to this limit. The minimum size is a hundred content items per segment.
I've covered a lot today, and it may take you a while to digest it all. Once you have access, I encourage you to further explore the specification. It goes into much greater detail about all the endpoints I covered today. The specification has an open API definition for the service endpoints you need to implement, and it is complete enough to generate basic data model parsing and verification code as you develop your service. That's super useful. Cloud Extension API definitions track changes in iOS SiriKit Media APIs with each new release. With only a few exceptions, almost everything available through SiriKit Media APIs on device is available through Cloud Extension APIs. And the queue APIs provide powerful playback definition, control and reporting directly to your services. Thank you for your interest in SiriKit Media Intents, and keep up-to-date on future SiriKit Media API changes at developer.apple.com/siri.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.