將 Cast SDK 整合至網路寄件者應用程式

本開發人員指南說明如何使用 Cast SDK 為網路傳送者應用程式新增 Google Cast 支援。

術語

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

Web send SDK 包含兩個部分:架構 API (cast.framework) 和 Base API (chrome.cast)。一般而言,您會使用較低層級的架構 API 進行呼叫,然後再透過較低層級的 Base API 處理。

「傳送者架構」是指架構 API、模組及其相關資源,為較低層級的功能提供包裝函式。寄件者應用程式Google Cast Chrome 應用程式是指在寄件者裝置上的 Chrome 瀏覽器中執行的網頁 (HTML/JavaScript)。網路接收器應用程式是指在 Chromecast 或 Google Cast 裝置上執行的 HTML/JavaScript 應用程式。

傳送者架構採用非同步回呼設計,可通知事件應用程式的傳送者,並轉換 Cast 應用程式生命週期的各個狀態。

載入程式庫

如果想讓應用程式導入 Google Cast 的功能,就必須知道 Google Cast 網路傳送者 SDK 的位置,如下所示。加入 loadCastFramework 網址查詢參數,一併載入 Web send Framework API。應用程式的所有頁面都必須參照下列程式庫:

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

架構

網站傳送者 SDK 使用 cast.framework.* 命名空間。命名空間代表下列內容:

  • 對 API 叫用作業的方法或函式
  • API 中的事件監聽器函式事件監聽器

架構包含以下主要元件:

  • CastContext 是單例模式物件,可提供目前投放狀態的相關資訊,並觸發投放狀態和投放工作階段狀態變更的事件。
  • CastSession 物件會管理工作階段,提供狀態資訊及觸發事件,例如裝置音量、靜音狀態和應用程式中繼資料等。
  • 「投放」按鈕元素,用於擴充 HTML 按鈕的簡易 HTML 自訂元素。如果提供的投放按鈕不足,您可以使用投放狀態實作投放按鈕。
  • RemotePlayerController 提供資料繫結,以簡化遠端播放器的實作。

如需命名空間的完整說明,請參閱「Google Cast Web send API 參考資料」。

投放按鈕

應用程式中的投放按鈕元件會完全由架構處理。包括瀏覽權限管理和點擊事件處理。

<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

如果您使用預設媒體接收器 (不需要註冊),請使用網路寄件者 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) 將媒體載入至已連結的投放裝置。首先,使用 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」。

  • PLAY/暫停: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;
  });

當暫停、播放、繼續或跳轉等事件發生時,應用程式就必須對事件採取行動,並在投放裝置與筆電和 Web 接收器應用程式之間同步。詳情請參閱狀態更新

工作階段管理的運作方式

Cast SDK 推出了投放工作階段的概念,這個架構結合了裝置連線步驟、啟動 (或加入) 網路接收器應用程式、連線至該應用程式,以及初始化媒體控制管道的步驟。如要進一步瞭解投放工作階段和網路接收器的生命週期,請參閱網路接收器的應用程式生命週期指南

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

如要監控工作階段狀態,請將事件監聽器新增至 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;
    }
  })

如要中斷連線,例如當使用者按一下「投放」對話方塊中的「停止投放」按鈕時,您可以在事件監聽器中為 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
    }
  });

雖然使用者可透過架構投放按鈕直接控制投放終止,但寄件者本身可以使用目前的 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.framework.SessionState.SESSION_RESUMED 事件時呼叫 CastSession#getCastDevice()

詳情請參閱在網路接收器上轉移串流一文。