Migrate to Web Receiver

This guide explains how to migrate a Cast Receiver v2 app to the latest Web Receiver app.

The new Cast Application Framework (CAF) SDK, also known as Web Receiver v3, is a major upgrade from the Receiver v2 SDK. The Web Receiver SDK provides an easy, streamlined SDK for developing media Web Receiver applications.

The Web Receiver provides an API that is more consistent with the new CAF sender APIs. It provides full integration of a player (MPL and Shaka) and full implementation and support for the Cast media and Google Assistant voice commands. CAF SDK also provides a default UI that can be easily styled using CSS, and a data binding service to simplify UI implementation.

Why migrate?

By migrating a Receiver v2 application to Web Receiver, a lot of code that deals with the player can be eliminated, so you can concentrate on writing application-specific business logic.

CAF seamlessly integrates MPL and Shaka players to support a wider range of content types including—HTTP Live Streaming (TS and CMAF), MPEG-DASH, Smooth Streaming and types supported by the Media Element source property (MP3, MP4, Icecast, etc...). For a complete list see Supported Media for Google Cast. Currently CAF does not support a user-provided player.

Migrating to CAF will add the support for voice control with Google Assistant. Any new Google Assistant voice command will automatically be supported when using CAF.

In addition to supporting new media commands—like "change tracks by language” and "change playback rate”—CAF also provides better queueing, built-in ads support, and better live support.

What changed?

The Web Receiver API tries to follow the conventions that were introduced by CAF senders for Android and iOS, and is quite different from v2.

The Web Receiver is using a new namespace cast.framework instead of cast.receiver namespace for all exposed APIs. Many of the data objects that were used by v2 are the same in CAF and are exposed under the cast.framework.messages namespace (they were mostly under cast.receiver.media).

The following v2 services are replaced by corresponding CAF services:

  • CastReceiverManager class is replaced by CastReceiverContext which is a singleton that manages the cast session, senders, sending custom messages, and global system events. The CastReceiverOptions can be used to provide global application options (such as queue, receiver version, playback config, etc.) to the context.
  • MediaManager class is replaced by PlayerManager which is a property of the CastReceiverContext singleton, and it manages the media session, media requests, Google Assistant voice requests (CommandAndControlManager in v2), and fires media events. Configuration for the players (cast.player.api.Host in MPL) is provided by PlaybackConfig, which can be provided globally or per load request.

The PlayerManager also exposes the new sub-manager classes:

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

// Set global options.
const options = cast.framework.CastReceiverOptions();
options.versionCode = DEVELOPERS_APP_VERSION;

context.start(options);

Receiver business logic

Receiver v2 exposed event handlers (such as CastReceiverManager.onReady or MediaManager.onLoad) to add business logic. In CAF the event handlers are replaced by event listeners (CastReceiverContext.addEventListener) and message interceptors (PlayerManager.setMessageInterceptor). Web Receiver can have multiple event listeners for an event (the listener does not affect the event), and one interceptor per message. The interceptor can update the request or handle it (return a modified request, a success message, or error message), and can be an async handler that returns a promise.

The load request interceptor is the most common place to add application-specific logic. For load requests from a sender, the load interceptor can convert the content ID to content URL. The load interceptor is also being called for preload and precache requests if no explicit interceptor was provided for preload or precache.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      // Resolve entity to content id
      if (request.media.entity && !request.media.contentId) {
        return getMediaByEntity(request.media.entity).then(
            media => {
              request.media.contentId = media.url;
              return request;
            });
      }
      return request;
    });

The v2 customized media status handler is also replaced with a message interceptor for the media status message. Web Receiver apps that do not want to expose the media URL in the media status can provide a URL resolver (PlayerManager.setMediaUrlResolver), which provides the media URL for a load request. That URL is used by CAF internally and is not provided in the media status.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.MEDIA_STATUS,
    status => {
      // Disable seek.
      status.supportedMediaCommands &=
          ~cast.framework.messages.Command.SEEK
      return status;
    });

Events

Web Receiver provides an extensive set of events both from CastReceiverContext and PlayerManager. Web Receiver apps can have multiple listeners on any event, and can also provide one listener to multiple events. (See cast.framework.events.category for some groups of events.)

The events cover any user request, playback progress, player processing, and any low-level media element event (CAF does not expose the media element itself).

The Web Receiver app can add event listeners to act upon (for example, add text tracks definition when load completes), or for analytics.

// Log all media commands
playerManager.addEventListener(
    cast.framework.events.category.REQUEST,
    event => logEvent(event.type));

Custom message bus

CAF does not expose the message bus in the API, instead it provides CastReceiverContext.addCustomMessageListener to add a message listener for a specific namespace (only one per namespace) and CastReceiverContext.sendCustomMessage to send a message on a namespace. All namespaces need to be declared before starting the Web Receiver (that is, before calling CastReceiverContext.start). The namespaces can be declared by adding a message listener to them or can be provided as a start option in CastReceiverOptions.customNamespaces.

const options = cast.framework.CastReceiverOptions();
options.customNamespaces = {
    [CUSTOM_NS]: cast.framework.system.MessageType.JSON
};
context.start(options);

context.sendCustomMessage(CUSTOM_NS, {
  type: 'status'
  message: 'Playing'
});

Default UI

CAF provides a default Web Receiver UI that displays a playback progress bar and media metadata as needed. The default UI is provided as a custom element (<cast-media-player>) that can be styled with CSS-like styling.

<style>
   cast-media-player { --splash-image: url("splash.png"); }
</style>
<cast-media-player></cast-media-player>

For more customization, a Web Receiver app can implement its own UI. The Web Receiver provides the cast.framework.ui.PlayerDataBinder class to help bind a UI object to the Web Receiver playback state.