将 Cast SDK 集成到您的 Web 发送器应用中

本开发者指南将介绍如何使用 Cast SDK 向网络发送器应用添加 Google Cast 支持。

术语

移动设备或浏览器是控制播放的发送方;Google Cast 设备是接收方,在屏幕上显示内容以供播放。

Web Sender SDK 由两部分组成:Framework API (cast.framework) 和 Base API (chrome.cast)。一般而言,您可以在更简单的较高层级 Framework API 上进行调用,然后由较低层级的 Base API 进行处理。

“发送方框架”是指框架 API、模块和相关资源,提供用于封装较低级别功能的封装容器。发送器应用Google Cast Chrome 应用是指在发送器设备上的 Chrome 浏览器中运行的网页 (HTML/JavaScript) 应用。网络接收器应用是指在 Chromecast 或 Google Cast 设备上运行的 HTML/JavaScript 应用。

发送器框架采用异步回调设计,向发送器应用通知事件,并在 Cast 应用生命周期的各种状态之间转换。

加载库

为了让您的应用实现 Google Cast 的功能,需要知道 Google Cast Web Sender SDK 的位置,如下所示。添加 loadCastFramework 网址查询参数,以便也加载 Web Sender Framework API。应用的所有页面都必须按如下方式引用该库:

<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

框架

Web Sender SDK 使用 cast.framework.* 命名空间。该命名空间表示以下内容:

  • 调用 API 操作的方法或函数
  • API 中监听器函数的事件监听器

该框架包含以下主要组件:

  • CastContext 是一个单例对象,可提供当前 Cast 状态的相关信息,并可针对 Cast 状态和 Cast 会话状态更改触发事件。
  • CastSession 对象用于管理会话,提供状态信息和触发事件,例如设备音量更改、静音状态和应用元数据更改。
  • “投射”按钮元素,这是一个简单的 HTML 自定义元素,可扩展 HTML 按钮。如果所提供的“投射”按钮不足,您可以使用“投射”状态来实现“投射”按钮。
  • RemotePlayerController 提供数据绑定来简化远程播放器的实现。

有关命名空间的完整说明,请参阅 Google Cast Web Sender API 参考文档

投放按钮

应用中的“投射”按钮组件完全由框架处理。这包括可见性管理以及点击事件处理。

<google-cast-launcher></google-cast-launcher>

或者,您也可以通过程序化方式创建该按钮:

document.createElement("google-cast-launcher");

您可以根据需要对元素应用任何其他样式,如尺寸或定位。使用 --connected-color 属性为已连接的 Web 接收器状态选择颜色,并使用 --disconnected-color 属性为断开连接状态选择颜色。

初始化

加载框架 API 后,应用会调用处理程序 window.__onGCastApiAvailable。您应确保应用先在 window 上设置此处理程序,然后再加载发送者库

在此处理程序中,您可以通过调用 CastContextsetOptions(options) 方法来初始化 Cast 交互。

例如:

<script>
window['__onGCastApiAvailable'] = function(isAvailable) {
  if (isAvailable) {
    initializeCastApi();
  }
};
</script>

然后,按如下方式初始化 API:

initializeCastApi = function() {
  cast.framework.CastContext.getInstance().setOptions({
    receiverApplicationId: applicationId,
    autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
  });
};

首先,应用会检索框架提供的 CastContext 对象的单例实例。然后,它使用 setOptions(options) 以及一个 CastOptions 对象来设置 applicationID

如果您使用的是默认媒体接收器(不需要注册),请使用 Web Sender SDK 预定义的常量(如下所示),而不是 applicationID

cast.framework.CastContext.getInstance().setOptions({
  receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
});

媒体控件

CastContext 初始化后,应用可以随时使用 getCurrentSession() 检索当前的 CastSession

var castSession = cast.framework.CastContext.getInstance().getCurrentSession();

CastSession 可用于使用 loadMedia(loadRequest) 将媒体加载到已连接的 Cast 设备。首先,使用 contentIdcontentType 以及与内容相关的所有其他信息创建一个 MediaInfo。然后,根据它创建一个 LoadRequest,为请求设置所有相关信息。最后,对 CastSession 调用 loadMedia(loadRequest)

var mediaInfo = new chrome.cast.media.MediaInfo(currentMediaURL, contentType);
var request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
  function() { console.log('Load succeed'); },
  function(errorCode) { console.log('Error code: ' + errorCode); });

loadMedia 方法将返回 Promise,可用于执行任何必要的操作来获得成功的结果。如果 Promise 被拒绝,函数参数将为 chrome.cast.ErrorCode

您可以在 RemotePlayer 中访问玩家状态变量。与 RemotePlayer 的所有互动(包括媒体事件回调和命令)都通过 RemotePlayerController 进行处理。

var player = new cast.framework.RemotePlayer();
var playerController = new cast.framework.RemotePlayerController(player);

RemotePlayerController 可让应用完全控制已加载媒体的 PLAY、PAUSE、STOP 和 SEEK 等媒体。

  • 播放/暂停:playerController.playOrPause();
  • 停止:playerController.stop();
  • 搜索:playerController.seek();

RemotePlayerRemotePlayerController 可与数据绑定框架(例如 Polymer 或 Angular)搭配使用,以实现远程播放器。

以下是 Angular 的代码段:

<button id="playPauseButton" class="playerButton"
  ng-disabled="!player.canPause"
  ng-click="controller.playOrPause()">
    {{player.isPaused ? 'Play' : 'Pause'}}
</button>
<script>
var player = new cast.framework.RemotePlayer();
var controller = new cast.framework.RemotePlayerController(player);
// Listen to any player update, and trigger angular data binding
update.controller.addEventListener(
  cast.framework.RemotePlayerEventType.ANY_CHANGE,
  function(event) {
    if (!$scope.$$phase) $scope.$apply();
  });
</script>

媒体状态

在媒体播放期间,系统会发生各种事件,您可以通过在 RemotePlayerController 对象上设置各种 cast.framework.RemotePlayerEventType 事件的监听器来捕获这些事件。

如需获取媒体状态信息,请使用 cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED 事件,该事件会在播放发生变化以及 CastSession.getMediaSession().media 发生变化时触发。

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, function() {
    // Use the current session to get an up to date media status.
    let session = cast.framework.CastContext.getInstance().getCurrentSession();

    if (!session) {
        return;
    }

    // Contains information about the playing media including currentTime.
    let mediaStatus = session.getMediaSession();
    if (!mediaStatus) {
        return;
    }

    // mediaStatus also contains the mediaInfo containing metadata and other
    // information about the in progress content.
    let mediaInfo = mediaStatus.media;
  });

当发生暂停、播放、继续或跳转等事件时,应用需要对这些事件执行操作,并在自身与 Cast 设备上的网络接收器应用之间进行同步。如需了解详情,请参阅状态更新

会话管理的工作原理

Cast SDK 引入了 Cast 会话的概念,其建立过程结合了执行以下操作的步骤:连接到设备、启动(或加入)网络接收器应用、连接到该应用,以及初始化媒体控制通道。如需详细了解 Cast 会话和网络接收器生命周期,请参阅网络接收器应用生命周期指南

会话由 CastContext 类管理,您的应用可以通过 cast.framework.CastContext.getInstance() 检索该类。各个会话由 Session 类的子类表示。例如,CastSession 表示与 Cast 设备的会话。您的应用可以通过 CastContext.getCurrentSession() 访问当前处于活动状态的 Cast 会话。

如需监控会话状态,请向 CastContextEventType.SESSION_STATE_CHANGED 事件类型的 CastContext 添加监听器。

var context = cast.framework.CastContext.getInstance();
context.addEventListener(
  cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
  function(event) {
    switch (event.sessionState) {
      case cast.framework.SessionState.SESSION_STARTED:
      case cast.framework.SessionState.SESSION_RESUMED:
        break;
      case cast.framework.SessionState.SESSION_ENDED:
        console.log('CastContext: CastSession disconnected');
        // Update locally as necessary
        break;
    }
  })

对于断开连接(例如,当用户点击 Cast 对话框中的“停止投射”按钮时),您可以在监听器中为 RemotePlayerEventType.IS_CONNECTED_CHANGED 事件类型添加监听器。在监听器中,检查 RemotePlayer 是否已断开连接。如果是这样,请根据需要更新本地播放器状态。例如:

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED, function() {
    if (!player.isConnected) {
      console.log('RemotePlayerController: Player disconnected');
      // Update local player to disconnected state
    }
  });

虽然用户可以通过框架“投射”按钮直接控制 Cast 终止,但发送器本身可以使用当前的 CastSession 对象停止投射。

function stopCasting() {
  var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
  // End the session and pass 'true' to indicate
  // that Web Receiver app should be stopped.
  castSession.endSession(true);
}

流式传输

保留会话状态是数据流传输的基础,在这种情况下,用户可以使用语音指令、Google Home 应用或智能显示屏在设备之间移动现有的音频和视频串流。媒体在一台设备(来源)上停止播放,然后在另一台设备(目标)上继续播放。任何具有最新固件的 Cast 设备都可以作为流式传输传输中的来源或目的地。

如需在数据流传输期间获取新的目标设备,请在调用 cast.framework.SessionState.SESSION_RESUMED 事件时调用 CastSession#getCastDevice()

如需了解详情,请参阅在 Web 接收器上传输数据流