Playback on Sonos

All service integrations stream audio files to Sonos. Your integration uses SMAPI to send the requested tracks and audio file locations to Sonos. But the actual process of streaming content occurs between the Sonos player and your media server, outside of SMAPI.

Sonos players make getMediaURI requests to obtain the playback URL of a track. Sonos calls this method on a secure endpoint using SSL. Your service should returns an HTTP URL for the track that is valid for a few minutes. Sonos players do not store track URLs for a long period of time, which means the actual stream URL may be different every time. You should strive to minimize the amount of time required to initialize stream playback. For example, don't force needless redirects to obtain a streaming URI.

SMAPI is codec agnostic. The format of the audio stream is determined by the content type of the data at the streaming URI. See Supported audio formats for a list of supported codecs.

The following sections describe how content playback works.

Respond to getMediaURI to provide audio for playback

The following sequence diagram illustrates the interactions when a user selects a single track and Sonos plays it. This is known as on-demand. See supported audio content for a description of the other types of audio.

The following steps occur when a user plays an on-demand track:

  1. The listener selects a track from a container such as an album or playlist, and the Sonos app tells the Sonos player to play the track by providing the track content ID.

  2. The Sonos player makes a getMediaURI request to the service to obtain the playback URL of the track based on the track's content ID.

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.sonos.com/Services/1.1">
      <soap:Header>
       ...
      </soap:Header>
      <soap:Body>
        <ns:getMediaURI>
          <ns:id>t_85787</ns:id>
        </ns:getMediaURI>
      </soap:Body>
    </soap:Envelope>
    
  3. The service responds to getMediaURI with a URI to the track's audio content.

    <soap:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.sonos.com/Services/1.1">
      <soap:Body>
        <ns:getMediaURIResponse>
          <ns:getMediaURIResult>http://acme.example.com/music/t_85787.mp3</ns:getMediaURIResult>
        </ns:getMediaURIResponse>
      </soap:Body>
    </soap:Envelope>
    
  4. The Sonos player uses repeated HTTP GET requests to obtain the encoded audio data from the media server. See playback processing, below, for details.

If your service requires using specific HTTP headers with the streaming GET requests, include the httpHeaders element in the getMediaURI response to pass to the Sonos player the headers and the expected values to use. This is a direct passthrough where the Sonos player will use the specified headers and values verbatim as headers in the GET requests to the supplied URI. More about HTTP request headers is available in the Request Header Fields section of the HTTP/1.1 Specification.

Respond to getMediaMetadata for queued items

In addition to playing audio on demand when the listener requests it, Sonos provides a queue that allows the Sonos player to play one song after another automatically. A listener adds items to the queue, usually by selecting from the Info View. We introduced the Info View with the discussion of getExtendedMetadata in content on Sonos.

When Sonos plays on demand, the Sonos app already has the title and other information to display while the song is playing. However, in order to display information about the next song in the queue, the Sonos player needs to request the information from the service. The Sonos player uses the getMediaMetadata request to retrieve from a service the track or stream metadata based on the given content ID. The following sequence diagram shows the process.

The following steps occur when a user plays an on-demand track:

  1. The listener chooses to queue a track or stream and the Sonos app adds it to the Sonos player's queue by providing the item's content ID.

  2. The Sonos player makes a getMediaMetadata request to the service and includes the content ID.

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <getMediaMetadata xmlns="http://www.sonos.com/Services/1.1">
          <id>t_85787</id>
        </getMediaMetadata>
      </soap:Body>
    </soap:Envelope>
    
  3. The service responds to getMediaMetadata with a mediaMetadata for the track or stream. The following is a sample response for a track.

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.sonos.com/Services/1.1">
      <s:Body>
        <getMediaMetadataResponse>
          <getMediaMetadataResult>
            <id>t_85787</id>
            <title>Satisfy</title>
            <itemType>track</itemType>
            <mimeType>audio/x-ms-wma</mimeType>
            <trackMetadata>
              <albumId>al_8657</albumId>
              <duration>253</duration>
              <artistId>ar_2654</artistId>
              <artist>The Rocks</artist>
              <album>The Rocks 1st Album</album>
              <albumArtURI>http://example.com/al_8657.jpg</albumArtURI>
              <canPlay>true</canPlay>
              <canSkip>true</canSkip>
              <canResume>true</canResume>
              <canSeek>true</canSeek>
              <canAddToFavorites>true</ns:canAddToFavorites>
            </trackMetadata>
          </getMediaMetadataResult>
        </getMediaMetadataResponse>
      </s:Body>
    </s:Envelope>
    
    • Required elements include the following:
      • id: This is your content ID that identifies the specific metadata item. (song)
      • title: The title is the label the Sonos app displays for the specific item. (song title)
      • itemType: Each mediaMetadata requires you specify the item type, which for songs is track.
      • mimeType: The media type for this track.
      • trackMetadata: This contains details about the specific track to play.
    • The trackMetadata element can include many options. Provide as many as appropriate so that Sonos can provide your users with the best experience possible. For example, the Sonos app uses the following to display track details to the listener:
      • albumId
      • duration
      • artistId
      • artist
      • album
      • albumArtURI
    • Use playback policies in trackMetadata sub-elements to provide information about playback behavior and about which controls the listener can use during playback. See set playback policies for details. Some examples include:
      • canPlay: When true, the user has the rights or permission so that the track can be played.
      • canSkip: When true, the user is permitted to skip forward among items in the container or queue.
      • canResume: When true, this indicates the item can be replayed or resumed where the user left off.
      • canSeek: When true, the user can seek within a track.
      • canAddToFavorites: When true, the listener can add the track to their service-specific favorites.
  4. When the listener chooses to start playing, the Sonos app tells the Sonos player to start playing from the queue.

  5. The Sonos player gets the next content ID off its queue.

  6. The Sonos player makes a getMediaURI request to the service with the content ID, and the service returns the URI for the audio.

  7. The Sonos player repeatedly makes HTTP GET requests to the current URI as the audio plays. See the next section for details of playback processing.

Stream radio with non-HLS M3U playlists

Your service can stream radio by providing Sonos with a non-HLS M3U playlist. Sonos players will stream from an M3U playlist in order, switching to the next stream when a stream fails. When a player switches streams, it will not know in advance if the new stream is a lower or higher bitrate or a different codec.

For details about streaming with HLS, see HTTP Live Streaming (HLS).

Playback processing

After a Sonos player gets the URI for a track from a getMediaURI response, it uses a fairly standard process to retrieve the audio from your service involving HTTP GET requests. Sonos does not cache the entire file before starting playback, but instead buffers and processes as needed until the entire file has played. One or more GET requests will be sent to the URI for each audio file. For most file formats, playback from the beginning of the file will result in one GET request.

The number of seconds of audio a Sonos player can buffer varies depending on encoding and bitrate. Certain encodings, such as WAV or FLAC, have a high bitrate; requiring many more bytes to generate a second of audio. This results in some files having more audio buffered than others. For more information about encodings and other audio details, see Supported audio formats and FLAC best practices.

The following provides a specific example to illustrate the playback process. This example includes some listener pause and resume actions, which are not included in the diagram above:

  1. After receiving the URI from a getMediaURI response, the Sonos player makes repeated GET requests.

    1. Sonos sends a GET request such as the following to the music service:

      GET
      http://acme.example.com/music/t_85787.mp3
      Referer:sonos-mymusicservice.example.com
      
      • Referer header: The request includes the HTTP header Referer set to sonos-mymusicservice.example.com to indicate to the service that the request comes from Sonos.
    2. The service should typically return the entire file in the response along with the HTTP success status code 200 and HTTP headers:

      HTTP/1.1 200 Success  
      Content-Type: application/mp3  
      Accept-Ranges: bytes  
      Content-Length: 4570936
      
      • Content-Type header: This identifies the audio media content type.
      • Accept-Ranges header: You may include this to indicate your service accepts byte-range requests.
      • Content-Length header: In addition to returning the requested audio, your service must return an accurate Content-Length HTTP header in the response. Sonos requires this to support seeking to any point in the file for formats where the time position doesn't map linearly to byte positions.
  2. Suppose the listener pauses the file at byte 3480314, and then a few minutes later the listener resumes play.

    1. The Sonos player then sends the service a request for the rest of the file:

      GET
      http://acme.example.com/music/t_85787.mp3
      Referer:sonos-mymusicservice.example.com
      Range:3480315-
      
      • Range header: In some cases, the Sonos player may need to send multiple requests during buffering, such as for some encodings like MP3 and MP4. In other situations, the data flow might start in the middle of the file such as when resuming from pause or seeking within a track. For these situations, Sonos sends a GET request using a Range header asking for the rest of the track starting from the resumption point.
    2. The service should return the section of the file starting with byte 3480315 until the end of the file. For a successful response include the HTTP partial content status code 206 and the following HTTP headers:

      HTTP/1.1 206 Partial Content  
      Content-Type: application/mp3  
      Accept-Ranges: bytes  
      Content-Range: bytes 3480315-/4570936  
      Content-Length: 1090621
      
      • Content-Range header: The music service must understand a range request and either send the requested partial file segment along with HTTP status code 206 or the error status code 416 if the requested byte range is invalid in some way and you cannot respond with a matching file segment.
  3. Suppose the listener pauses their music again and happens to hit the very last byte of the file.

    1. When the listener resumes, the Sonos player makes the following request:

      GET  
      <http://acme.example.com/music/t_85787.mp3>  
      Referer:sonos-mymusicservice.example.com  
      Range:4570937-
      
    2. The service should then return an HTTP error status code 416 indicating that the requested range is invalid:

      HTTP/1.1 416 Requested Range Cannot be Provided.

  4. After a Sonos player finishes buffering a track, it will continue playing the track while it gets the URI for the next song in the queue via another getMediaURI request/response. The Sonos player will begin buffering the new track even before it has finished playing the current track. If the queue is empty, the Sonos player will complete playback by finishing the current track.