Amazon Music Device API

Playback

Basics

Tracks and Track Containers A track is the basic unit of music managed by the API. Every track belongs to a track container, an abstraction of a music collection such as a playlist, a station, or an album.

Track Container Chunks A track container specifies which tracks to play and in what order. The ordering of tracks in a track container is modelled as a chain of track container chunks, each specified by a Track­Container­Chunk­Description. A track container chunk contains a list of track instances to be played in order, and contains Track­Pointer objects that point to the previous and next chunk in the chain.

An example of two chunks

Track container chunks within a chain may overlap. For that reason, the track pointers that link track container chunks together in the chain also indicate a particular track within a chunk’s track list:

An example of two chunks with overlapping tracks

Below is a sample JSON response for a track container chunk:

"trackContainerChunkDescriptions": {
        "chunk": {
            "firstTrackPointer": {
                "chunk": "#chunk",
                "indexWithinChunk": 0
            },
            "nextTrackPointer": null,
            "prevTrackPointer": null,
            "lastTrackPointer": {
                "chunk": "#chunk",
                "indexWithinChunk": 11
            },
            "title": "Love Sux [Explicit]",
            "trackInstances": [
                "#track_inst_0",
                "#track_inst_1",
                "#track_inst_2",
                "#track_inst_3",
                "#track_inst_4",
                "#track_inst_5",
                "#track_inst_6",
                "#track_inst_7",
                "#track_inst_8",
                "#track_inst_9",
                "#track_inst_10",
                "#track_inst_11"
            ],
        }
    },

Repeat Mode

The beginning and end of a chain of track container chunks calls for special behavior that depends on whether repeat mode is active. When repeat mode is active, the chain should be treated as circular, advancing playback from the end of the chain to the beginning, and allowing the user to skip backwards from the beginning to the end. To support this feature, track container chunks contain links to the first and last track instance in the ordering.

Some containers are potentially infinite and thus have no end (e.g. stations); some are generated dynamically and do not retain enough history to always have a beginning (also e.g. stations). Client applications can determine whether or not a track container supports repeat mode by examining the first­Track­Pointer and last­Track­Pointer members of any Track­Container­Chunk­Description; repeat mode is supported if and only if both members are non-null.

Track Containers and Navigation Nodes

A navigation node is essentially a list of items, and a track container is essentially a list of tracks. It is important to acknowledge that these two concepts are not mutually exclusive. The key difference is that the items in a navigation node are presented to the user as a list of choices, whereas tracks in a track container are simply played in order. For some Navigation Nodes (such as the root node, initiating playback may not make sense, and for that reason such navigation nodes are not also track containers. To give another example, Amazon Music Stations are track containers that do not require track selection and for that reason they are not also navigation nodes.

Playback Event Reporting

Each track instance in a response will contain a track definition with a playback event collector inside. Applications must post event JSON data to the event collector for every applicable customer action linked to a playback event. Event data is posted in the form of a PlaybackEventReport. Some examples of playback events are starting playback, pausing playback, or stopping playback due to closing the application. There are two main playback event report types, Start and Stop. Each of those events supports multiple reason codes (see below sections for a complete list of reason codes).

To the extent possible, playback events should be reported from the user’s perspective. In particular, when the user chooses to play a track and has to wait a few seconds for initial buffering, the start event should not be reported until the buffering has finished, and the delay reported in playback­Delay field of the playbackEventReport.

Let’s look at some example JSON. Suppose the API response included the following JSON for a given track:

"track_inst_91": {
 "self": "075a662c-b059-4af9-bb5f-8fe4633473c0/",
 "trackDefinition": "#track_def_91",{
 "playbackEventCollector":
"../../event/tracks/true/trackAsin/B00UMINC3W/objectId/0754af9-bb5f8fe46633473c0/duration/211000/trackContentEligibility/HAWKFIRE/"
}

then during playback, if the user instructs the app to stop playback 189,000 milliseconds into the track, the application must POST to the URI "../../event/tracks/true/trackAsin/B00UMINC3W/objectId/0754af9-bb5f-8fe46633473c0/duration/211000/trackContentEligibility/HAWKFIRE/" with a POST-BODY of:

{ 
    "trackPosition": 189000, 
    "reason": "userStop",
    "wallClockTime": "2018-06-29T9:59:43",
    "event": "stop" 
}

PlaybackEventReport fields

Field name Type Description
event string The value should be either "start" or "stop". Use "start" when the track was not previously playing, but has now started. Use "stop" when the track was previously playing, but has now stopped.
wallClockTime timestamp The actual time this event occurred. Should be reported using the time zone offset representing the local device time.
trackPosition number The distance from the beginning of the track where this event occurred, in milliseconds.
playbackDelay number The delay when starting or resuming the audio, in milliseconds. Should only be reported if it was observable by customer. Null if delay not applicable for this event.
isDirectedPlay boolean True if the start or stop event was elicited by the user’s direct action, otherwise false. Null if actual value cannot be reported. Please file an Exception Request if you are unable to report this value.
isShufflePlay boolean True if the user has a playable randomization feature enabled, otherwise false. Null if actual value cannot be reported. Please file an Exception Request if you are unable to report this value.
cacheHitStatus boolean True if client is able to immediately start playback at the requested location in the song. False if not enough of track was already downloaded/cached to begin immediate playback. Null if actual value cannot be reported. Please file an Exception Request if you are unable to report this value.
source string The source of the device’s internet connection, if available. Acceptable values: WIFI, WIRED, UNKNOWN, or the name of the cell carrier (e.g. "Verizon," "T-Mobile")
transferSpeedBPS number A best guess toward the user's connection speed in bits per second.
rebufferCount (stop only) number The number of times playback was interrupted to await further downloads or rebuffers during completion of the playable.
reason string A code indicating the reason why this event occurred (see below).

Start Event Reason Codes

userSelectTrack This track started playing as a result of the user selecting a Playable whose track­Def member matches this track’s definition.
userSelectPlayable This track started playing as a result of the user selecting a Playable whose track­Def member does not match this track’s definition or is null or absent.
autoAdvance This track started playing automatically because the previous track in the track container finished playing.
userAdvance This track started playing because of a user action that advanced from the previous track in the track container.
userAdvanceBackward This track started playing because of a user action that advanced backward from the next track in the track container.
userSeek A user action resulted in a discontinuous jump in the playback position while playing the track.
resume Playback of this track resumed after having been paused. The track­Position member should match the track­Position member of the previous stop event.
bufferUnderflow Playback resumed after stopping due to the audio stream buffer running out.

Stop Event Reason Codes

finish This track played to completion.
userAdvance This track stopped playing because of a user action that advanced to the next track, typically pressing the next button.
userAdvanceBackward This track stopped playing because of a user action that advanced backward from the current track. This should be used when user presses back and either a different track is played, or this track is restarted.
userPause A user action resulted in playback stopping in a way that allows playback to resume from the same position.
userStop A user action resulted in playback stopping in a way that does not allow playback to resume from the same position. This includes user pressing stop or explicitly selecting a different track.
userSeek A user action resulted in a discontinuous jump in the playback position while playing the track (see below.
userInactive Playback stopped mid-track due to user not interacting with the device for too long or a power-saving feature. Includes both resumable and non-resumable states.
systemPause Playback stopped for any other reason not initiated by a user action (e.g. an incoming voice call or a power management event) in a way that allows playback to resume from the same position.
systemStop Playback stopped for any other reason not initiated by a user action in a way that does not allow playback to resume from the same position.
error Playback stopped for a reason that is indicative of unexpected conditions or system errors.
bufferUnderflow Playback stopped due to the audio stream buffer running out.

Handling skip a track

The Prime experience has a skip limit feature. Every hour, a Prime user can skip a track 6 times before reaching a skip limit. To make the integration easier, there is a canSkip flag that tells if a user can skip a track. The canSkip flag is driven off of the events; whenever a user skips a track, we should receive a "Stop - userAdvance", if we do not receive the "userAdvance" event, the canSkip flag might never return false.

There are some scenarios where the user can or cannot skip backwards. The canSkipBackward flag tells if a user can or cannot skip backwards in behavior like Stations.

Below is a sample JSON partial response of a track that includes the canSkip and canSkipBackward flags:

            "autoSkipOnError": false,
            "duration": 207000,
            "isrc": "GBAYE2100379",
            "error": null,
            "trackRating": null,
            "trackTag": "B098Z4XHTT",
            "isExplicit": "false",
            "canSkip": true,
            "canSkipBackward": true,
            "album": {
                "name": "Music Of The Spheres [Explicit]",
                "indexWithinAlbum": 2,
                "uri": "../../albums/B098YT7MP1/",
                "asin": "B098YT7MP1"
            },

Errors

It is important to check for errors after sending a play event report. In some cases, there can be issues which may generate an error message. For example: the end user is playing streams on multiple devices, but their subscription tier only allows them one stream.

In such a case, the client would receive an error message from the service. In this case, the client needs to follow the error, display any messages, and possibly stop playback on one or more devices.

See the section on errors for more information on General Error Reports.

Seeking Within A Track

Whenever a user action results in a discontinuous jump in the playback position within a track, clients should report a pair of playback events: a stop event at the previous playback position and a start event at the new playback position. The user­Seek reason code should be used for both events.

Such a discontinuous jump may sometimes require rebuffering of the audio stream at the new playback position. In that case, the start event should not be reported until the buffer is ready to resume playback.

Pausing

Whenever playback becomes paused, a stop event with a proper reason code should be reported. Any events that happen while the track is in paused state should be reported as well, using the same PlaybackEventCollector.

Playback with DRM

DRM is currently required for any on device playback.

Users can not only play tracks, but in some cases they may rate them as well. Click here to learn more.