Saving and Resuming Play Position

Introduction

Your service can provide resumable content in the form of audiobooks and individual tracks, such as podcasts. Sonos will send you the position in the track or audiobook at which the user paused, so that you can resume it again. You can also send position information for Sonos to start an audiobook or track at a specific position. For example, a user could listen to an audiobook on your service and then switch to listening to it on Sonos. You can set this content as resumable and send the position information for Sonos to start the audio. Likewise, a user could pause an audiobook on Sonos and continue listening to it on your service, using the position information sent to you by the player.

The examples below talk about podcasts for individual tracks of resumable content and audiobooks for containers. After reading this introduction, see the following sections for implementation details:

Audiobooks and podcasts are resumable content

When a user selects a podcast, the Sonos app sends your service a getMetadata request for the podcast. To specify that the content is resumable, return <mediaMetadata> with an <itemType> of track and <trackMetadata> that includes <canResume> set to true.

Audiobooks are handled differently than resumable tracks because chapters are a set of tracks that we want to keep together and in order. For example, it would not make sense to let users shuffle or crossfade audiobook chapters in the queue like music tracks.

To keep audiobook chapters together, you specify an audiobook in its container. When a user selects a container of audiobooks, the Sonos app sends your service a getMetadata request for the container. To specify audiobooks in the container, return a <mediaCollection> element for each audiobook with <itemType> set to audiobook and <canResume> set to true. When a user selects an audiobook from the container, the Sonos app does not add the audiobook to the queue but instead the Sonos app passes along the audiobook ID to the Sonos player. Then, the Sonos player sends your service a getMetadata request for the audiobook, for which your service returns a set of chapters as <mediaMetadata> tracks.

For now, the only resumable content are <itemType> audiobook and track.

Manage position information

Your service needs to maintain play position information for the audiobooks and resumable tracks users listen to. This includes the following tasks:

  • Enable status reporting
  • Store position information during play
  • Handle pause and continue
  • Store position information when track play ends

You will need to enable status reporting for your service so that the Sonos player will provide position information to your service while resumable content plays. Information for resumable content includes <offsetMillis>, representing the position into the track in milliseconds.

When the Sonos player starts playing resumable content, it calls reportPlaySeconds to send play position information to your service, which you store for the resumable content and user. The Sonos player continues to call reportPlaySeconds regularly until the user decides to play something else or pause the player.

If the user explicitly selects the Sonos app's pause button while listening to resumable content, the Sonos player calls reportPlayStatus to report the play position and paused status to your service. Your service needs to store this information for the resumable content and user. Full details of what happens during pause and continue are covered in the implementation sections below.

When the playing track changes to a different track, the Sonos player calls setPlayedSeconds to report to your service the total amount of time a track played, which you store for the resumable content and user. This occurs no matter how the track changes, such as when a track completes playing, when a user chooses to skip to the next chapter of a book, or when a user starts to listen to something else. Sonos players send a final setPlayedSeconds report after 30 minutes of no playback activity to indicate that playback has stopped.

Provide resume position information

When a user returns to listen to resumable content they did not finish, your service supplies to Sonos the latest play position in a <positionInformation> element so that the Sonos player can resume playing the content where the user left off. If your service determines that the user is just beginning to listen to a particular resumable content, you simply omit position information and the Sonos player starts at the beginning.

Implementing audiobooks

While an audiobook plays, the Sonos app displays the current chapter and other audiobook information in the now-playing screen. The user can skip to the next or previous chapter but cannot view and select any specific chapter in the book. Following is the workflow for an audiobook, which highlights in green the tasks your service needs to implement. Also included below are examples of returned results your service needs to provide.

Defining audiobooks

The workflow starts by showing how the Sonos app obtains an audiobook ID and provides it to the Sonos player (workflow steps 1 through 8). A user browses the Sonos app to the container that has an audiobook, and the Sonos app sends your service a getMetadata request for the container.

Your service returns a <getMetadataResult> that holds a list of items in the container, where each audiobook is a <mediaCollection> element that includes the following minimum settings:

  • <itemType> set to audiobook
  • <canResume> set to true
  • <title>
  • <authorId>
  • <author>
  • <narratorId>
  • <narrator>
  • <canPlay> set to true

​​The following is a sample service response to a getMetadata request for a container with two audiobooks:

<ns:getMetadataResponse>
    <ns:getMetadataResult>
        <ns:index>0</ns:index>
        <ns:count>2</ns:count>
        <ns:total>2</ns:total>
        <ns:mediaCollection>
            <ns:id>bk:1</ns:id>
            <ns:itemType>audiobook</ns:itemType>
            <ns:displayType>booksEditorial</ns:displayType>
            <ns:title>The Adventures of Sherlock Holmes</ns:title>
            <ns:summary>Robie Robot reads the mystery classics of Sir Arthur Conan Doyle. Listen
                with excitement as Mr. Holmes and Dr. Watson scamper about ye olde country solving
                crime.
            </ns:summary>
            <ns:isFavorite>false</ns:isFavorite>
            <ns:authorId>ar:30</ns:authorId>
            <ns:author>Sir Arthur Conan Doyle</ns:author>
            <ns:narratorId>ar:33</ns:narratorId>
            <ns:narrator>Microsoft Sam</ns:narrator>
            <ns:canPlay>true</ns:canPlay>
            <ns:albumArtURI>
                https://acme.example.com/assets/images/book_sherlockholmes.jpg
            </ns:albumArtURI>
            <ns:canResume>true</ns:canResume>
        </ns:mediaCollection>
        <ns:mediaCollection>
            <ns:id>bk:2</ns:id>
            <ns:itemType>audiobook</ns:itemType>
            <ns:displayType>booksEditorial</ns:displayType>
            <ns:title>The Adventures of Static HLS 1</ns:title>
            <ns:summary>PLX Narrator</ns:summary>
            <ns:isFavorite>false</ns:isFavorite>
            <ns:authorId>ar:34</ns:authorId>
            <ns:author>PLX Author</ns:author>
            <ns:narratorId>ar:35</ns:narratorId>
            <ns:narrator>PLX Narrator</ns:narrator>
            <ns:canPlay>true</ns:canPlay>
            <ns:albumArtURI>https://acme.example.com/assets/images/test.jpg
            </ns:albumArtURI>
            <ns:canResume>true</ns:canResume>
        </ns:mediaCollection>
    </ns:getMetadataResult>
</ns:getMetadataResponse>

When the user selects an audiobook from the container, the Sonos app will not put the audiobook in the queue so that the chapters remain together and in order when the book plays.

If the user selects "About this Book" from the Sonos app's Info View screen, Sonos makes a getExtendedMetadata request to your service with the audiobook ID (workflow steps 5 through 7). You can choose to display audiobook notes to the user by returning the <relatedText> element with the <type> set to BOOK_NOTES. For details on Info View, see Customized Info View.

Providing resume book position

Before the Sonos player begins to play the audiobook, it determines where to resume play by first sending your service a getMetadata request with the audiobook ID (workflow steps 9 through 13).

Your service returns to the Sonos player a <getMetadataResult> that includes <positionInformation> and <mediaMetadata> sub-elements representing the chapters. Include the <positionInformation> sub-element if your service determines this user is resuming listening. If your service determines this user is just beginning to listen, you can omit ​<positionInformation>. The data includes the following:

  • <id> The identifier of the chapter track where play is to resume.
  • <index> For future use. Set this value to "0".
  • <offsetMillis> The number of milliseconds into the chapter where playback is to resume.

Represent the audiobook chapters with a set of <mediaMetadata> elements. Each chapter includes a <trackMetadata> sub-element with the following data. Details of each are described in getMetadata:

  • <authorId>
  • <author>
  • <narratorId>
  • <narrator>
  • <bookId>
  • <book>
  • <duration>
  • <albumArtURI>
  • <canPlay> Set to true for an audiobook chapter.
  • <canAddToFavorites> Set to false for an audiobook chapter.

Note, do not set <canResume> to true for individual chapters of an audiobook. Set this flag only at the audiobook level of the container in the <mediaCollection>. The following is an example of a <getMetadataResult> for an audiobook:

<ns:getMetadataResponse>
    <ns:getMetadataResult>
        <ns:index>0</ns:index>
        <ns:count>2</ns:count>
        <ns:total>2</ns:total>
        <ns:positionInformation>
            <ns:id>tr:473</ns:id>
            <ns:index>0</ns:index>
            <ns:offsetMillis>408191</ns:offsetMillis>
        </ns:positionInformation>
        <ns:mediaMetadata>
            <ns:id>tr:472</ns:id>
            <ns:itemType>track</ns:itemType>
            <ns:title>Chapter 1</ns:title>
            <ns:mimeType>audio/mp3</ns:mimeType>
            <ns:trackMetadata>
                <ns:authorId>ar:30</ns:authorId>
                <ns:author>Sir Arthur Conan Doyle</ns:author>
                <ns:narratorId>ar:33</ns:narratorId>
                <ns:narrator>Microsoft Sam</ns:narrator>
                <ns:bookId>bk:1</ns:bookId>
                <ns:book>The Adventures of Sherlock Holmes</ns:book>
                <ns:duration>3069</ns:duration>
                <ns:albumArtURI>
                    https://acme.example.com/assets/images/book_sherlockholmes.jpg
                </ns:albumArtURI>
                <ns:canPlay>true</ns:canPlay>
                <ns:canAddToFavorites>false</ns:canAddToFavorites>
            </ns:trackMetadata>
        </ns:mediaMetadata>
        <ns:mediaMetadata>
            <ns:id>tr:473</ns:id>
            <ns:itemType>track</ns:itemType>
            <ns:title>Chapter 2</ns:title>
            <ns:mimeType>audio/mp3</ns:mimeType>
            <ns:trackMetadata>
                <ns:authorId>ar:30</ns:authorId>
                <ns:author>Sir Arthur Conan Doyle</ns:author>
                <ns:narratorId>ar:33</ns:narratorId>
                <ns:narrator>Microsoft Sam</ns:narrator>
                <ns:bookId>bk:1</ns:bookId>
                <ns:book>The Adventures of Sherlock Holmes</ns:book>
                <ns:duration>3258</ns:duration>
                <ns:albumArtURI>
                    https://acme.example.com/assets/images/book_sherlockholmes.jpg
                </ns:albumArtURI>
                <ns:canPlay>true</ns:canPlay>
                <ns:canAddToFavorites>false</ns:canAddToFavorites>
            </ns:trackMetadata>
        </ns:mediaMetadata>
    </ns:getMetadataResult>
</ns:getMetadataResponse>

The Sonos player determines the chapter and offset from where play will resume based on the <positionInformation> your service supplied. The Sonos player then repeatedly sends your service getMediaURI requests for the chapters starting with the resume chapter, and your service returns a <getMediaURIResult> for each chapter (workflow steps 11 through 13). If the audiobook has no <positionInformation>, the requests start with the first chapter and playback will start at the beginning.

Storing audiobook position during play

When playing an audiobook, the Sonos player periodically calls reportPlaySeconds to send your service play position information, which your service needs to store for the audiobook and user (workflow steps 14 through 16). A reply is optional. By default, the player continues to call reportPlaySeconds at 60 second intervals. To set this to a different interval for your service, return <reportPlaySecondsResult> with the number of seconds in the <interval> element.

The following example sets the interval for reporting play position to 20 seconds:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
   <reportPlaySecondsResponse xmlns="http://www.sonos.com/Services/1.1">
    <reportPlaySecondsResult>
     <interval>20</interval>
    </reportPlaySecondsResult>
   </reportPlaySecondsResponse>
  </soap:Body>

Handling audiobook pause and continue

If the user pauses playback, the Sonos player calls reportPlayStatus to send to your service the paused status and play position information, which your service stores for the audiobook and user (workflow steps 17 through 25). Your service does not reply to this call. During a pause, the player also suspends the reportPlaySeconds calls to your service. Note the following:

  • If the user selects continue within 30 minutes:
    The Sonos player continues playing at the paused position and the reportPlaySeconds calls resume to your service.
  • If 30 minutes pass during a pause:
    Sonos players send a final setPlayedSeconds report after 30 minutes of no playback activity to indicate that playback has stopped. The Sonos app leaves only the play button enabled. It also disables controls for changing the play position and does not display any current position information. The user may have decided to listen to the audiobook on a different device.
  • If the user selects continue after 30 minutes:
    ​The Sonos player sends your service a getMetadata request to get <positionInformation> from your service, and play resumes as described earlier in the workflow, but at the new position.

Storing position when chapter play ends

When the user stops listening to a chapter, the Sonos player calls setPlayedSeconds to send to your service information you save for the audiobook and user (workflow steps 26 and 27). Your service does not reply to this call. The user can stop listening to a chapter track in any number of ways, such as when the chapter is complete, when the user selects the next chapter, or if the user starts listening to something else.

User controls for audiobooks

During play, the user can select Sonos app controls to change the play position. The following controls are available:

  • Progress bar: Play moves to the newly selected position in the chapter.
  • Next button: Play moves to the next chapter.
  • Previous button: Play moves to the previous chapter.
  • Fast Forward 30 Seconds: Play moves 30 seconds ahead in the chapter. This control is only available for audiobooks.
  • Rewind 30 Seconds: Play moves 30 seconds back in the chapter. This control is only available for audiobooks.

Fast Forward 30 Seconds       Rewind 30 Seconds

Note that selecting some of these controls ends the play of the current chapter and causes a new chapter to play. If this occurs, the Sonos player will call setPlayedSeconds to send to your service information you save for the audiobook and user.

Implementing resumable tracks

Following is the workflow for selecting and playing a podcast, which is a typical resumable track. Green highlights the tasks your service needs to implement. Included below are examples of returned results your service needs to provide to implement resumable tracks.

Defining resumable tracks

The workflow shows that when a user browses the Sonos app and selects a podcast, the Sonos app sends your service a getMetadata request with the podcast's ID (workflow steps 1 through 3).

Your service needs to return to the Sonos app a <getMetadataResult> that holds a resumable track represented as a <mediaMetadata> element with the <trackMetadata> sub-element containing <canResume> set to true. The following is a sample service response to a getMetadata request for a podcast:

<ns:getMetadataResponse>
  <ns:getMetadataResult>
    <ns:index>0</ns:index>
    <ns:count>1</ns:count>
    <ns:total>1</ns:total>
    <ns:mediaMetadata>
      <ns:id>tr:480</ns:id>
      <ns:itemType>track</ns:itemType>
      <ns:title>Episode1185-SmugglingAcrossBorders</ns:title>
      <ns:isFavorite>false</ns:isFavorite>
      <ns:mimeType>audio/mp3</ns:mimeType>
      <ns:trackMetadata>
        <ns:artistId>ar:31</ns:artistId>
        <ns:artist>ESLPodcast</ns:artist>
        <ns:albumId>al:41</ns:albumId>
        <ns:album>TheESLPodcast</ns:album>
        <ns:duration>1166</ns:duration>
        <ns:albumArtURI>https://acme.example.com/assets/images/ESL_400.png</ns:albumArtURI>
        <ns:canPlay>true</ns:canPlay>
        <ns:canAddToFavorites>true</ns:canAddToFavorites>
        <ns:canResume>true</ns:canResume>
      </ns:trackMetadata>
      <ns:dynamic>
        <ns:property>
          <ns:name>LIKED</ns:name>
          <ns:value>0</ns:value>
        </ns:property>
      </ns:dynamic>
      <ns:behaviors>
        <ns:supportsQuickSkip>true</ns:supportsQuickSkip>
      </ns:behaviors>
    </ns:mediaMetadata>
  </ns:getMetadataResult>
</ns:getMetadataResponse>

 

Providing resume track position

Before the Sonos player begins to play the podcast, it determines where to resume play by first sending your service a getMediaURI request for the track ID (workflow steps 5 through 8).

Your service returns to the Sonos player a <getMediaURIResult> that includes <positionInformation> along with the podcast's URI. Include <positionInformation> if your service determines this user is resuming listening. If your service determines this user is just beginning to listen, you can omit ​<positionInformation>. The data includes the following:

  • <id> The current track ID which is the same as the requested ID.
  • <index> For future use. Set this value to "0".
  • <offsetMillis> The number of milliseconds into the track where playback is to resume.

The following is an example of a service response to getMediaURI for a resumable track that includes position information:

<getMediaURIResponse xmlns="http://www.sonos.com/Services/1.1">
    <getMediaURIResult>
     http://example.com/12345.mp3
  </getMediaURIResult>
    <positionInformation>
        <id>tr:480</id>
        <index>0</index>
        <offsetMillis>54690</offsetMillis>
    </positionInformation>
</getMediaURIResponse>

Storing track position during play

When playing a resumable track, the Sonos player periodically calls reportPlaySeconds to send your service play position information, which your service needs to store for the track and user (workflow steps 9 through 11). A reply is optional. By default, the player continues to call reportPlaySeconds at 60 second intervals. To set this to a different interval for your service, return <reportPlaySecondsResult> with the number of seconds in the <interval> element.

The following example sets the interval for reporting play position to 20 seconds:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
   <reportPlaySecondsResponse xmlns="http://www.sonos.com/Services/1.1">
    <reportPlaySecondsResult>
     <interval>20</interval>
    </reportPlaySecondsResult>
   </reportPlaySecondsResponse>
  </soap:Body>

Handling tRACK pause and continue

If the user selects the pause control, the Sonos player calls reportPlayStatus to send to your service the paused status and play position information, which your service stores for the track and user (workflow steps 12 through 20). Your service does not reply to this call. During a pause, the player also suspends the reportPlaySeconds calls to your service. Note the following:

  • If the user selects continue within 30 minutes:
    The Sonos player continues playing at the paused position and the reportPlaySeconds calls resume to your service.
  • If 30 minutes pass during a pause:
    Sonos players send a final setPlayedSeconds report after 30 minutes of no playback activity to indicate that playback has stopped. The Sonos app leaves only the play button enabled. It also disables controls for changing the play position and does not display any current position information. The user may have decided to listen to the track on a different device.
  • If the user selects continue after 30 minutes:
    ​The Sonos player sends your service a getMediaURI request to get <positionInformation> from your service, and play resumes as described earlier in the workflow, but at the new position.

Storing position when track play ends

When the user stops listening to a resumable track, the Sonos player calls setPlayedSeconds to send to your service information you save for the resumable track and user (workflow steps 21 and 22). Your service does not reply to this call. The user can stop listening to a track in any number of ways, such as when the track is complete, when the user selects the next track in the queue, or if the user starts listening to something else.

Enabling status reporting

In order for the Sonos player to provide your service play position information for resumable content, you need to enable Status Reporting for the API reportPlaySeconds, reportPlayStatus, and setPlayedSeconds. When the Sonos player plays resumable content and reporting is enabled, these calls will include <offsetMillis> as part of the position information.

Use the Version Manager to enable the following capabilities when submitting your service to Sonos:

  • "Playback duration logging at track end"
  • "Playback event logging during track play"
  • "Add play context to reporting"

See B: TECHNICAL CONFIGURATION & TEST SETUP and Add your service with customSD for details.