為自訂網路接收器新增核心功能

本頁面包含程式碼片段,並說明自訂網頁接收器應用程式可用的功能。

  1. 代表 Web Receiver 隨附的內建播放器 UI 的 cast-media-player 元素。
  2. cast-media-player 元素的自訂 CSS 樣式,可設定各種 UI 元素 (例如 background-imagesplash-imagefont-family) 的樣式。
  3. 用於載入網頁接收器架構的指令碼元素。
  4. 用於攔截訊息和處理事件的 JavaScript 程式碼。
  5. 自動播放待播節目。
  6. 設定播放選項。
  7. 設定網頁接收器環境的選項。
  8. 設定 Web Receiver 應用程式支援的指令。
  9. 啟動 Web Receiver 應用程式的 JavaScript 呼叫。

應用程式設定和選項

設定應用程式

CastReceiverContext 是向開發人員公開的最外層類別,可管理基礎程式庫的載入作業,並處理 Web 接收器 SDK 的初始化作業。SDK 提供 API,讓應用程式開發人員透過 CastReceiverOptions 設定 SDK。系統會在每次啟動應用程式時評估這些設定,並在呼叫 start 時設定選用參數,將設定傳遞至 SDK。

以下範例說明如何覆寫預設行為,偵測傳送端連線是否仍處於連線狀態。如果 Web Receiver 在 maxInactivity 秒內無法與傳送者通訊,系統就會傳送 SENDER_DISCONNECTED 事件。下列設定會覆寫這個逾時時間。這項功能有助於偵錯問題,因為當處於 IDLE 狀態的連線傳送器數量為零時,Web Receiver 應用程式不會關閉 Chrome 遠端偵錯工具工作階段。

const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);

設定播放器

載入內容時,Web Receiver SDK 提供設定播放變數的方法,例如 DRM 資訊、重試設定和要求處理常式 (使用 cast.framework.PlaybackConfig)。這項資訊由 PlayerManager 處理,並在建立玩家時評估。每次將新負載傳遞至 Web 接收器 SDK 時,系統都會建立播放器。播放器建立後,系統會在下次載入內容時評估對 PlaybackConfig 的修改。SDK 提供下列方法來修改 PlaybackConfig

以下範例說明如何初始化 CastReceiverContext 時設定 PlaybackConfig。這項設定會覆寫取得資訊清單的外送要求。處理常式會指定應使用 Cookie 或授權標頭等憑證,發出 CORS Access-Control 要求。

const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
  requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});

以下範例說明如何使用 PlayerManager 提供的 getter 和 setter 覆寫 PlaybackConfig。這項設定會將播放器設為在載入 1 個片段後繼續播放內容。

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
            new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);

以下範例說明如何使用媒體播放資訊處理常式,覆寫特定載入要求的 PlaybackConfig。處理常式會呼叫應用程式實作的方法 getLicenseUrlForMedia,從目前項目的 contentId 取得 licenseUrl

playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
  const mediaInformation = loadRequestData.media;
  playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);

  return playbackConfig;
});

事件監聽器

Web Receiver SDK 可讓 Web Receiver 應用程式處理播放器事件。事件監聽器會採用 cast.framework.events.EventType 參數 (或這類參數的陣列),指定應觸發監聽器的事件。您可以在 cast.framework.events.category 中找到預先設定的 cast.framework.events.EventType 陣列,這些陣列有助於進行偵錯。事件參數會提供事件的其他資訊。

舉例來說,如要瞭解何時會廣播 mediaStatus 變更,可以使用下列邏輯處理事件:

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
    cast.framework.events.EventType.MEDIA_STATUS, (event) => {
      // Write your own event handling code, for example
      // using the event.mediaStatus value
});

攔截訊息

Web Receiver SDK 可讓 Web Receiver 應用程式攔截訊息,並對這些訊息執行自訂程式碼。訊息攔截器會採用 cast.framework.messages.MessageType 參數,指定要攔截的訊息類型。

攔截器應傳回修改後的請求,或以修改後的請求值解析的 Promise。傳回 null 可防止呼叫預設訊息處理常式。詳情請參閱「載入媒體」。

舉例來說,如要變更載入要求資料,可以使用下列邏輯攔截並修改:

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

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_FAILED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      if (!loadRequestData.media.entity) {
        return loadRequestData;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          if (!asset) {
            throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
          }

          loadRequestData.media.contentUrl = asset.url;
          loadRequestData.media.metadata = asset.metadata;
          loadRequestData.media.tracks = asset.tracks;
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

context.start();

處理錯誤

訊息攔截器發生錯誤時,Web Receiver 應用程式應傳回適當的 cast.framework.messages.ErrorTypecast.framework.messages.ErrorReason

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_CANCELLED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      ...

      return fetchAssetAndAuth(loadRequestData.media.entity,
                               loadRequestData.credentials)
        .then(asset => {
          ...
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

訊息攔截與事件監聽器

訊息攔截和事件監聽器之間的主要差異如下:

  • 事件監聽器無法修改要求資料。
  • 事件監聽器最適合用來觸發 Analytics 或自訂函式。
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • 訊息攔截功能可讓您監聽訊息、攔截訊息,以及修改要求資料本身。
  • 訊息攔截最適合用來處理與要求資料相關的自訂邏輯。

正在載入媒體

MediaInformation 提供多項屬性,可在 cast.framework.messages.MessageType.LOAD 訊息中載入媒體,包括 entitycontentUrlcontentId

  • 建議您在傳送端和接收端應用程式的實作中,使用 entity 屬性。這個屬性是深層連結網址,可以是播放清單或媒體內容。應用程式應剖析這個網址,並填入至少一個其他兩個欄位。
  • contentUrl 是播放器用來載入內容的可播放網址。舉例來說,這個網址可以指向 DASH 資訊清單。
  • contentId 可以是可播放內容的網址 (類似於 contentUrl 屬性),也可以是載入中內容或播放清單的專屬 ID。如果使用這項屬性做為 ID,應用程式應在 contentUrl 中填入可播放的網址。

建議使用 entity 儲存實際 ID 或金鑰參數,並使用 contentUrl 做為媒體的網址。以下程式碼片段顯示相關範例,其中 entity 存在於 LOAD 要求中,且可播放的 contentUrl 已擷取:

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      ...

      if (!loadRequestData.media.entity) {
        // Copy the value from contentId for legacy reasons if needed
        loadRequestData.media.entity = loadRequestData.media.contentId;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          loadRequestData.media.contentUrl = asset.url;
          ...
          return loadRequestData;
        });
    });

裝置功能

getDeviceCapabilities 方法會提供已連線 Cast 裝置的裝置資訊,以及附加的視訊或音訊裝置。getDeviceCapabilities 方法提供 Google 助理、藍牙,以及已連線螢幕和音訊裝置的支援資訊。

這個方法會傳回物件,您可以傳遞其中一個指定的列舉,查詢該列舉的裝置功能。列舉項目定義於 cast.framework.system.DeviceCapabilities

這個範例會分別使用 IS_HDR_SUPPORTEDIS_DV_SUPPORTED 鍵,檢查 Web Receiver 裝置是否能播放 HDR 和 DolbyVision (DV)。

const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
  const deviceCapabilities = context.getDeviceCapabilities();
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
  }
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
  }
});
context.start();

處理使用者互動

使用者可以透過傳送端應用程式 (網頁、Android 和 iOS)、支援 Google 助理裝置的語音指令、智慧螢幕的觸控控制項,以及 Android TV 裝置的遙控器,與 Web Receiver 應用程式互動。Cast SDK 提供各種 API,讓 Web Receiver 應用程式處理這些互動、透過使用者動作狀態更新應用程式 UI,以及視需要傳送變更來更新任何後端服務。

支援的媒體指令

UI 控制項狀態是由 MediaStatus.supportedMediaCommands 所驅動,適用於 iOS 和 Android 傳送器擴充控制器、接收器和遙控器 應用程式 (在觸控裝置上執行),以及 Android TV 裝置上的接收器應用程式。如果屬性中啟用特定位元運算子 Command,系統就會啟用與該動作相關的按鈕。如未設定值,按鈕會停用。如要在網頁接收器上變更這些值,請採取下列做法:

  1. 使用 PlayerManager.setSupportedMediaCommands 設定特定 Commands
  2. 使用 addSupportedMediaCommands 新增指令
  3. 使用 removeSupportedMediaCommands 移除現有指令。
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

接收者準備更新的 MediaStatus 時,會將變更納入 supportedMediaCommands 屬性。狀態播送後,已連線的傳送端應用程式會相應更新 UI 中的按鈕。

如要進一步瞭解支援的媒體指令和觸控裝置,請參閱Accessing UI controls指南。

管理使用者動作狀態

使用者與 UI 互動或傳送語音指令時,可以控制內容的播放情形,以及與播放項目相關的屬性。SDK 會自動處理控制播放的要求。修改目前播放項目屬性的要求 (例如 LIKE 指令) 必須由接收器應用程式處理。SDK 提供一系列 API 來處理這類要求。如要支援這些要求,請完成下列事項:

  • 載入媒體項目時,請使用使用者的偏好設定 MediaInformation userActionStates
  • 攔截 USER_ACTION 訊息,並判斷要求的動作。
  • 更新 MediaInformation UserActionState,以更新 UI。

以下程式碼片段會攔截 LOAD 要求,並填入 LoadRequestDataMediaInformation。在本例中,使用者喜歡載入的內容。

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
      const userActionLike = new cast.framework.messages.UserActionState(
          cast.framework.messages.UserAction.LIKE);
      loadRequestData.media.userActionStates = [userActionLike];

      return loadRequestData;
    });

以下程式碼片段會攔截 USER_ACTION 訊息,並處理使用要求變更呼叫後端的作業。然後呼叫接收器上的 UserActionState 來更新。

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
  (userActionRequestData) => {
    // Obtain the media information of the current content to associate the action to.
    let mediaInfo = playerManager.getMediaInformation();

    // If there is no media info return an error and ignore the request.
    if (!mediaInfo) {
        console.error('Not playing media, user action is not supported');
        return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
    }

    // Reach out to backend services to store user action modifications. See sample below.
    return sendUserAction(userActionRequestData, mediaInfo)

    // Upon response from the backend, update the client's UserActionState.
    .then(backendResponse => updateUserActionStates(backendResponse))

    // If any errors occurred in the backend return them to the cast receiver.
    .catch((error) => {
      console.error(error);
      return error;
    });
});

下列程式碼片段會模擬呼叫後端服務。函式會檢查 UserActionRequestData,瞭解使用者要求的變更類型,且只有在後端支援該動作時,才會發出網路呼叫。

function sendUserAction(userActionRequestData, mediaInfo) {
  return new Promise((resolve, reject) => {
    switch (userActionRequestData.userAction) {
      // Handle user action changes supported by the backend.
      case cast.framework.messages.UserAction.LIKE:
      case cast.framework.messages.UserAction.DISLIKE:
      case cast.framework.messages.UserAction.FOLLOW:
      case cast.framework.messages.UserAction.UNFOLLOW:
      case cast.framework.messages.UserAction.FLAG:
      case cast.framework.messages.UserAction.SKIP_AD:
        let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
        setTimeout(() => {resolve(backendResponse)}, 1000);
        break;
      // Reject all other user action changes.
      default:
        reject(
          new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
    }
  });
}

下列程式碼片段會取得 UserActionRequestData,並從 MediaInformation 新增或移除 UserActionState。更新 UserActionStateMediaInformation 會變更與所要求動作相關聯的按鈕狀態。這項變更會反映在智慧螢幕控制項 UI、遙控器應用程式和 Android TV UI。此外,系統也會透過外送的 MediaStatus 訊息進行廣播,以便更新 iOS 和 Android 寄件者擴充控制器的 UI。

function updateUserActionStates(backendResponse) {
  // Unwrap the backend response.
  let mediaInfo = backendResponse.mediaInfo;
  let userActionRequestData = backendResponse.userActionRequestData;

  // If the current item playing has changed, don't update the UserActionState for the current item.
  if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
    return;
  }

  // Check for existing userActionStates in the MediaInformation.
  // If none, initialize a new array to populate states with.
  let userActionStates = mediaInfo.userActionStates || [];

  // Locate the index of the UserActionState that will be updated in the userActionStates array.
  let index = userActionStates.findIndex((currUserActionState) => {
    return currUserActionState.userAction == userActionRequestData.userAction;
  });

  if (userActionRequestData.clear) {
    // Remove the user action state from the array if cleared.
    if (index >= 0) {
      userActionStates.splice(index, 1);
    }
    else {
      console.warn("Could not find UserActionState to remove in MediaInformation");
    }
  } else {
    // Add the UserActionState to the array if enabled.
    userActionStates.push(
      new cast.framework.messages.UserActionState(userActionRequestData.userAction));
  }

  // Update the UserActionState array and set the new MediaInformation
  mediaInfo.userActionStates = userActionStates;
  playerManager.setMediaInformation(mediaInfo, true);
  return;
}

語音指令

目前支援 Google 助理的裝置,可透過 Web Receiver SDK 使用下列媒體指令。這些指令的預設實作位於 cast.framework.PlayerManager 中。

指令 說明
播放 播放或從暫停狀態繼續播放。
暫停 暫停目前播放的內容。
返回 跳至媒體佇列中的上一個媒體項目。
繼續 跳到媒體待播清單中的下一個媒體項目。
停止 停止播放目前正在播放的媒體。
不重複播放 待播清單中的最後一個項目播放完畢後,停用重複播放功能。
重複播放單一歌曲 無限期重複播放目前播放的媒體。
重複播放所有項目 播放完待播清單中的最後一個項目後,重複播放清單中的所有項目。
重複播放所有歌曲和隨機播放 待播清單中的最後一個項目播放完畢後,隨機播放待播清單中的所有項目。
隨機播放 隨機播放媒體佇列中的媒體項目。
開啟 / 關閉隱藏式輔助字幕 為媒體啟用 / 停用隱藏式輔助字幕。你也可以依語言啟用 / 停用。
跳轉絕對時間 跳到指定的絕對時間。
跳轉相對於目前時間的時間 相對於目前的播放時間,向前或向後跳轉指定的時間長度。
再玩一次 重新啟動目前播放的媒體,或在目前未播放任何內容時,播放上次播放的媒體項目。
設定播放速率 調整媒體播放速率。系統預設會處理這項作業。您可以使用 SET_PLAYBACK_RATE 訊息攔截器,覆寫傳入的費率要求。

支援的語音媒體指令

如要避免語音指令在支援 Google 助理的裝置上觸發媒體指令,請先設定您打算支援的媒體指令。接著,您必須啟用 CastReceiverOptions.enforceSupportedCommands 屬性,強制執行這些指令。Cast SDK 傳送器和觸控裝置上的 UI 會隨之變更,如果未啟用這項旗標,系統就會執行收到的語音指令。

舉例來說,如果您允許從傳送端應用程式和支援觸控的裝置傳送 PAUSE,也必須設定接收端來反映這些設定。設定完成後,如果語音指令不在支援的指令清單中,系統就會捨棄該指令。

在下方範例中,我們會在啟動 CastReceiverContext 時提供 CastReceiverOptions。我們新增了對 PAUSE 指令的支援,並強制播放器僅支援該指令。現在,如果語音指令要求其他操作 (例如 SEEK),系統會拒絕。系統會通知使用者目前不支援該指令。

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

context.start({
  enforceSupportedCommands: true,
  supportedCommands: cast.framework.messages.Command.PAUSE
});

您可以為要限制的每個指令套用個別邏輯。移除 enforceSupportedCommands 旗標,並攔截要限制的每個指令傳入訊息。我們在此攔截 SDK 提供的要求,以免對支援 Google 助理的裝置發出 SEEK 指令時,在 Web Receiver 應用程式中觸發搜尋。

如果應用程式不支援媒體指令,請傳回適當的錯誤原因,例如 NOT_SUPPORTED

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
  seekData => {
    // Block seeking if the SEEK supported media command is disabled
    if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
      let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
      .INVALID_REQUEST);
      e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
      return e;
    }

    return seekData;
  });

從語音活動進入背景

如果 Cast 平台因 Google 助理活動 (例如聆聽使用者語音或回覆) 而將應用程式的音訊設為背景執行,系統會在活動開始時,將 NOT_IN_FOCUSFocusState 訊息傳送至網頁接收器應用程式。活動結束時,系統會再傳送一則含有 IN_FOCUS 的訊息。視應用程式和播放的媒體而定,您可能想在 FocusStateNOT_IN_FOCUS 時,透過攔截 FOCUS_STATE 訊息類型暫停媒體。

舉例來說,如果 Google 助理正在回應使用者查詢,暫停播放有聲書可提供良好的使用者體驗。

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
  focusStateRequestData => {
    // Pause content when the app is out of focus. Resume when focus is restored.
    if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
      playerManager.pause();
    } else {
      playerManager.play();
    }

    return focusStateRequestData;
  });

語音指定的字幕語言

如果使用者未明確指定字幕語言,系統會使用說出指令時的語言顯示字幕。在這些情況下,傳入訊息的 isSuggestedLanguage 參數會指出相關聯的語言是由系統建議,還是使用者明確要求。

舉例來說,如果說出「Ok Google,開啟字幕」,isSuggestedLanguage 會設為 true,因為系統會根據說出指令時使用的語言推斷語言。如果明確要求使用特定語言,例如「Ok Google,開啟英文的字幕」,isSuggestedLanguage 會設為 false

中繼資料和語音投射

語音指令預設由 Web Receiver 處理,但請務必確保內容的中繼資料完整且正確。這可確保 Google 助理能正確處理語音指令,並在 Google Home 應用程式和 Google Home Hub 等智慧螢幕等新型介面上,正確顯示中繼資料。

變更串流裝置

保留工作階段狀態是串流轉移的基礎,使用者可以透過語音指令、Google Home 應用程式或智慧螢幕,在裝置間轉移現有的音訊和視訊串流。媒體會在一部裝置 (來源) 上停止播放,並在另一部裝置 (目的地) 上繼續播放。只要韌體為最新版本,任何 Cast 裝置都能在串流轉移中做為來源或目的地。

串流轉移的事件流程如下:

  1. 在來源裝置上:
    1. 停止播放媒體。
    2. Web Receiver 應用程式會收到儲存目前媒體狀態的指令。
    3. Web Receiver 應用程式已關閉。
  2. 在目標裝置上:
    1. 載入 Web Receiver 應用程式。
    2. Web Receiver 應用程式會收到指令,還原已儲存的媒體狀態。
    3. 媒體會繼續播放。

媒體狀態的元素包括:

  • 歌曲、影片或媒體項目的特定位置或時間戳記。
  • 在較廣泛的佇列 (例如播放清單或藝人電台) 中的位置。
  • 通過驗證的使用者。
  • 播放狀態 (例如播放中或已暫停)。

啟用串流轉移

如要為 Web Receiver 導入串流轉移功能,請按照下列步驟操作:

  1. 使用 STREAM_TRANSFER 指令更新 supportedMediaCommands
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. 您可以選擇覆寫 SESSION_STATERESUME_SESSION 訊息攔截器,如「保留工作階段狀態」一文所述。只有在需要將自訂資料儲存為工作階段快照的一部分時,才需要覆寫這些資料。否則,保留工作階段狀態的預設實作方式會支援串流轉移。

保留工作階段狀態

Web Receiver SDK 提供 Web Receiver 應用程式的預設實作方式,可擷取目前的媒體狀態快照、將狀態轉換為載入要求,並使用載入要求繼續工作階段,藉此保留工作階段狀態。

如有需要,您可以在 SESSION_STATE 訊息攔截器中覆寫 Web Receiver 產生的載入要求。如要在載入要求中加入自訂資料,建議將資料放入 loadRequestData.customData

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.SESSION_STATE,
    function (sessionState) {
        // Override sessionState.loadRequestData if needed.
        const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
        sessionState.loadRequestData.credentials = newCredentials;

        // Add custom data if needed.
        sessionState.loadRequestData.customData = {
            'membership': 'PREMIUM'
        };

        return sessionState;
    });

自訂資料可從 RESUME_SESSION 訊息攔截器中的 loadRequestData.customData 擷取。

let cred_ = null;
let membership_ = null;

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.RESUME_SESSION,
    function (resumeSessionRequest) {
        let sessionState = resumeSessionRequest.sessionState;

        // Modify sessionState.loadRequestData if needed.
        cred_ = sessionState.loadRequestData.credentials;

        // Retrieve custom data.
        membership_ = sessionState.loadRequestData.customData.membership;

        return resumeSessionRequest;
    });

內容預先載入

Web Receiver 支援在佇列中目前播放的項目之後,預先載入媒體項目。

預先載入作業會預先下載即將推出項目的多個片段。規格是在 QueueItem 物件的 preloadTime 值中完成 (如未提供,則預設為 20 秒)。時間以秒為單位,相對於目前播放項目的結尾。只能輸入正值。舉例來說,如果值為 10 秒,系統會在先前項目完成前 10 秒預先載入這個項目。如果預先載入的時間高於 currentItem 剩餘的時間,系統就會盡快預先載入。因此,如果在 queueItem 上指定非常大的預先載入值,就能達到以下效果:播放目前項目時,系統會預先載入下一個項目。不過,我們將這項設定和選擇權留給開發人員,因為這個值可能會影響目前播放項目的頻寬和串流效能。

預先載入功能預設適用於 HLS、DASH 和 Smooth 串流內容。

MP4 影片和 MP3 等音訊檔案不會預先載入,因為 Cast 裝置只支援一個媒體元素,且現有內容項目仍在播放時,無法用於預先載入。

自訂訊息

訊息交換是 Web Receiver 應用程式的主要互動方式。

傳送端會使用傳送端 API,針對傳送端執行的平台 (Android、iOS、網站) 向 Web Receiver 發送訊息。傳遞至事件監聽器的事件物件 (即訊息的表現形式) 具有資料元素 (event.data),其中資料會採用特定事件類型的屬性。

Web Receiver 應用程式可以選擇監聽特定命名空間的訊息。因此,我們說 Web Receiver 應用程式支援該命名空間通訊協定。接著,任何想透過該命名空間通訊的已連線傳送者,都必須使用適當的通訊協定。

所有命名空間都是以字串定義,且開頭必須為「urn:x-cast:」,後面接上任何字串。例如「urn:x-cast:com.example.cast.mynamespace」。

以下是 Web Receiver 的程式碼片段,可監聽連線傳送者傳送的自訂訊息:

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

const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
  // handle customEvent.
});

context.start();

同樣地,Web Receiver 應用程式也可以將訊息傳送給已連線的傳送者,讓傳送者瞭解 Web Receiver 的狀態。Web Receiver 應用程式可以使用 sendCustomMessage(namespace, senderId, message) 傳送訊息。CastReceiverContext網頁接收器可以傳送訊息給個別傳送者,無論是為了回應收到的訊息,或是因為應用程式狀態變更。除了點對點訊息 (上限為 64 KB),網頁接收器也可以向所有連線的傳送者廣播訊息。

投放到音訊裝置

如需僅播放音訊的支援,請參閱 Google Cast 音訊裝置指南

Android TV

本節將說明 Google Web Receiver 如何將輸入內容做為播放內容,以及 Android TV 相容性。

將應用程式與遙控器整合

Android TV 裝置上執行的 Google Web Receiver 會將裝置控制項輸入 (即手持遙控器) 轉換為 urn:x-cast:com.google.cast.media 命名空間定義的媒體播放訊息,如「媒體播放訊息」一文所述。應用程式必須支援這些訊息,才能控制應用程式媒體播放,並允許透過 Android TV 的控制項輸入內容進行基本播放控制。

Android TV 相容性指南

以下提供一些建議,並列舉常見錯誤,協助您確保應用程式與 Android TV 相容:

  • 請注意,使用者代理程式字串同時包含「Android」和「CrKey」;有些網站可能會偵測到「Android」標籤,因此重新導向至僅限行動裝置的網站。請勿假設使用者代理程式字串中的「Android」一律代表行動裝置使用者。
  • Android 的媒體堆疊可能會使用透明 GZIP 擷取資料。請確認媒體資料可以回應 Accept-Encoding: gzip
  • Android TV HTML5 媒體事件的觸發時間可能與 Chromecast 不同,這可能會揭露 Chromecast 隱藏的問題。
  • 更新媒體時,請使用 <audio>/<video> 元素觸發的媒體相關事件,例如 timeupdatepausewaiting。請避免使用 progresssuspendstalled 等網路相關事件,因為這些事件通常會因平台而異。如要進一步瞭解如何在接收器中處理媒體事件,請參閱「媒體事件」。
  • 設定接收端網站的 HTTPS 憑證時,請務必加入中繼 CA 憑證。請參閱 Qualsys SSL 測試頁面,確認網站的信任認證路徑是否包含標示為「額外下載」的 CA 憑證。如果包含,網站可能無法在 Android 平台載入。
  • Chromecast 會在 720p 的圖像平面上顯示接收器頁面,而 Android TV 等其他 Cast 平台則可能會以最高 1080p 的畫質顯示該頁面。確認接收器網頁在不同解析度下都能正常縮放。