將 Cast SDK 整合至 Web Sender 應用程式

本開發人員指南說明如何使用 Cast SDK,在 Web 傳送器應用程式中新增 Google Cast 支援。

術語

行動裝置或瀏覽器是傳送者,負責控制播放;Google Cast 裝置是接收者,負責在螢幕上顯示內容以供播放。

Web Sender SDK 包含兩個部分:Framework API (cast.framework) 和 Base API (chrome.cast)。一般來說,您會在較簡單的高階 Framework API 上發出呼叫,然後由低階 Base API 處理。

傳送者架構是指 Framework 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 物件會管理工作階段,提供狀態資訊並觸發事件,例如裝置音量、靜音狀態和應用程式中繼資料的變更。
  • Cast 按鈕元素,這是擴充 HTML 按鈕的簡單 HTML 自訂元素。如果提供的 Cast 按鈕不敷使用,您可以運用 Cast 狀態實作 Cast 按鈕。
  • RemotePlayerController 提供資料繫結,簡化遠端播放器的實作。

如需命名空間的完整說明,請參閱「Google Cast Web Sender API Reference」。

投放按鈕

應用程式中的 Cast 按鈕元件完全由架構處理。這包括可見度管理和點擊事件處理。

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

或者,您也可以透過程式建立按鈕:

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

您可以視需要將任何其他樣式 (例如大小或位置) 套用至元素。使用 --connected-color 屬性選擇已連線的網頁接收器狀態顏色,並使用 --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 物件單例模式例項。然後使用 CastOptions 物件,透過 setOptions(options) 設定 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) 將媒體載入已連線的 Google 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 完全控制已載入的媒體,包括播放、暫停、停止及搜尋。

  • 播放/暫停:playerController.playOrPause();
  • 時間到:playerController.stop();
  • SEEK: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 裝置上與 Web Receiver 應用程式同步。詳情請參閱「狀態更新」一文。

工作階段管理功能的運作方式

Cast SDK 導入了 Cast 工作階段的概念,建立工作階段時,會一併完成連線至裝置、啟動 (或加入) Web Receiver 應用程式、連線至該應用程式,以及初始化媒體控制管道等步驟。如要進一步瞭解 Google Cast 工作階段和 Web Receiver 生命週期,請參閱 Web Receiver 應用程式生命週期指南

工作階段是由類別管理 CastContext,應用程式可透過 cast.framework.CastContext.getInstance() 擷取工作階段。 個別工作階段會以 Session 類別的子類別表示。舉例來說,CastSession 代表使用 Cast 裝置的工作階段。應用程式可以透過 CastContext.getCurrentSession() 存取目前啟用的 Cast 工作階段。

如要監控工作階段狀態,請為 CastContext 新增 CastContextEventType.SESSION_STATE_CHANGED 事件類型的監聽器。

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 按鈕直接控制 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 Receiver 上轉移串流」。