MediaSelector

MediaSelector is a BBC system used to access audio streams. It performs the following functions:

  • Confirming that client has the rights to play the content requested. Rights can vary by geography (based on GeoIP lookup), type of device and time

  • Locating the correct asset information to fulfil the request

  • Applying knowledge of the BBC’s current CDN configuration to tell clients where to access the asset

  • Issuing time-limited CDN tokens to control access to the content.

Due to the GeoIP lookup performed on each request, the request to MediaSelector must be made by the actual device on which the audio will be played, rather than by an aggregator, proxy or other intermediaries.

Clients must make an HTTP GET request using the URL provided in RadioSPI as-is. Additional or invalid query sting parameters may return an error.

See also the General Guidance page for guidance on DNS and SSL/TLS.

CDNs

The BBC uses multiple Content Delivery Networks to distribute media. This complexity is hidden from clients by MediaSelector. In general, the URLs returned by MediaSelector may:

  • Contain a time-limited access token, good for the expected usage of one client playing back the content requested

  • Point to a geographically restricted service, suitable for the GeoIP location the request is determined to originate from

  • Point to a different CDN on each request. Clients should not assume the same hostname or base path will be returned.

Redirects

The CDN location will be provided in the Location header. Any modern HTTP client should follow this as standard. The URL must be used as provided, including any query-string parameters provided. No additional query-string parameters should be appended and the URL should not be changed in any way. The URLs returned by this process may be quite long, so clients must support URLs of at least 4096 characters.

The CDN may also provide a further 1 or more redirects before returning the actual media. Clients must support at least 5 redirects in a row to be sure of coping with any CDN the BBC is likely to use.

Caching

MediaSelector responses will contain cache control headers like the following:

HTTP/1.1 302 Found
Cache-Control: private, s-maxage=300, max-age=900

In general, intermediate caching is prohibited, but the response may be cached on the client for the specified period before starting stream playback. Once the cache age expires, the URL provided may be invalid due to an embedded timestamp.

Error Handling

MediaSelector is a high-volume service, serving thousands of requests per second across all BBC products. It is imperative that clients are careful in their error-handling behaviour to avoid overwhelming the infrastructure with too many requests.

If there is a problem with the request, the error returned will be indicated by an HTTP error response code. Additional information about the error may be present in an X-MS-Error header, but will always be present in the body of the response. The contents of these are subject to change. This information would be useful in diagnosing any failures, so clients may wish to log or otherwise record the response code and the ERROR_ID, if present.

The 4xx errors are terminal. Clients must not automatically retry these, and it would be unlikely that a retry would return a different result.

The 5xx errors are non-terminal. Clients may automatically retry these, within the following constraints:

  • Clients must not automatically send the same request to the same IP address again.

  • If more than one A record was returned on the original DNS lookup, clients may try the request on an alternative IP address from the original DNS lookup, as this may resolve to a different failure zone.

  • Clients may also retry the DNS lookup and try an alternative IP address from that response, provided it differs to the original IP address used.

Except for the scenarios described above, the client must make no further attempts to contact the service until requested to do so by the user. This is to protect the BBC’s backend infrastructure in the event of a problem.

Error Responses

The general error response format will usually always take the same form. In the case of a 404, you may receive an HTML response instead. The standard error responses are:

XML:

HTTP/1.1 400 Bad Request
Date: <TIMESTAMP>
Server: nginx
Connection: close
X-MS-Disclaimer: This code and data form part of the BBC iPlayer content protection system... [...]
Content-Type: text/xml

<?xml version="1.0" encoding="UTF-8"?>
<mediaselection xmlns="http://bbc.co.uk/2011/mp/mediaselection" version="2.0">
    <error id="<ERROR_ID>"/>
</mediaselection>

JSON:

HTTP/1.1 400 Bad Request
Date: <TIMESTAMP>
Server: nginx
Connection: close
X-MS-Disclaimer: This code and data form part of the BBC iPlayer content protection system... [...]
Content-Type: application/json

{
    "disclaimer": "This code and data form part of the BBC iPlayer content protection system..."
    "result": "<ERROR_ID>"
}

The ERROR_ID reflects tha HTTP status code and is one of the following:

Status 400 (Bad Request)

  • badrequest: the request URL was invalid, e.g. media parameter missing, or malformed URL syntax.

Status 401 (Unauthorized)

  • unauthorized: the request contains no or invalid authentication credentials, e.g an invalid JWT.

Status 403 (GeoIP Restricted)

  • geolocation: the resource is not available in the geographic location from which the request originates (based on a GeoIP check).

Status 403 (Forbidden)

  • forbidden: request denied, e.g., used if a request was sent to a resource only available via a Media Distribution HTTPS gateway.

Status 403 (Unknown Origin)

  • unknownorigin: the request was made from a client whose “Origin” header does not match the list of approved origins. Returned only when /cors/1 is in the request path.

Status 404 (Not Found)

  • notavailable: the requested content is either unknown, not available yet, or already expired. In this scenario, you may receive an HTML response instead of the XML or JSON response:

HTTP/1.1 404 Not Found
Server: nginx
Date: <TIMESTAMP>
Content-Type: text/html
X-MS-Disclaimer: This code and data form part of the BBC iPlayer content protection system... [...]

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
    <head>
        <title>404 Not Found</title>
    </head>
    <body>
        <h1>Not Found</h1>
        <p>404 Not Found</p>
    </body>
</html>

Status 404 (Selection Unavailable)

  • selectionunavailable: the requested PID exists, but the requested selection is not available, e.g., not available for the requested media set, protocol, or transfer format. A client may retry the request with a different selection automatically, but must not retry requests more than twice.

Status 503 (Service Unavailable)

  • serviceunavailable: Media Selector is not able to answer the request, because of an unknown error.

Alarm Clocks

Clients that base their request on a scheduled event, such as an alarm clock, must take steps to smooth the load on the BBC’s infrastructure. A suggested route (and the one used by the BBC’s own products) is as follows:

  • Calculate a random number of milliseconds between 0 and at least 10,000 (spreading over a longer period would also be acceptable).

  • Start the request this random number of milliseconds before the scheduled start time

  • The stream starts playing at this time but is muted until the scheduled start time comes around

  • Clients must use an appropriate source of entropy as the pseudo-random number generator seed (eg time of day the application was started or device initialised), to ensure that all instances do not come up with the same, predictable random sequence.

To protect its infrastructure, the BBC reserves the right to apply rate limits to certain requests, which may result in a certain proportion of requests failing. Spreading the request load as per the above will minimise the chance of this happening.