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

本頁面提供自訂網頁接收器應用程式可用的功能程式碼片段和說明。

  1. cast-media-player 元素,代表 Web Receiver 提供的內建播放器 UI。
  2. cast-media-player 元素設定自訂 CSS 樣式,以便為各種 UI 元素設定樣式,例如 background-imagesplash-imagefont-family
  3. 用來載入 Web Receiver 架構的指令碼元素。
  4. 用於攔截訊息和處理事件的 JavaScript 程式碼。
  5. 自動播放的待播清單。
  6. 用於設定播放功能的選項。
  7. 設定 Web Receiver 情境的選項。
  8. 設定 Web Receiver 應用程式支援的指令選項。
  9. 用於啟動 Web Receiver 應用程式的 JavaScript 呼叫。

應用程式設定和選項

設定應用程式

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

以下範例說明如何覆寫預設行為,以便偵測是否仍與傳送端連線。如果 Web 接收器無法與傳送端通訊 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 Receiver SDK 時,系統都會建立播放器。系統會在下次內容載入時,評估播放器建立後對 PlaybackConfig 所做的修改。SDK 提供下列方法來修改 PlaybackConfig

以下範例說明如何在初始化 CastReceiverContext 時設定 PlaybackConfig。這項設定會覆寫取得資訊清單的傳出要求。這個處理程序會指定 CORS 存取控制要求應使用 Cookie 或授權標頭等憑證。

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;
        });
    });

訊息攔截與事件監聽器

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

  • 事件監聽器「不允許」您修改要求資料。
  • 事件監聽器最適合用來觸發分析或自訂函式。
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 中定義。

這個範例會檢查 Web Receiver 裝置是否能分別使用 IS_HDR_SUPPORTEDIS_DV_SUPPORTED 鍵播放 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,以及視需要傳送變更來更新任何後端服務。

支援的媒體指令

針對 iOS 和 Android 傳送端擴充控制器、在觸控裝置上執行的接收器和遙控器應用程式,以及 Android TV 裝置上的接收器應用程式,UI 控制項狀態是由 MediaStatus.supportedMediaCommands 驅動。在屬性中啟用特定位元 Command 時,系統會啟用與該動作相關的按鈕。如果未設定值,則按鈕會停用。您可以透過下列方式在 Web Receiver 上變更這些值:

  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。更新 MediaInformationUserActionState 會變更與要求動作相關聯的按鈕狀態。這項變更會反映在智慧型螢幕控制項 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;
}

語音指令

目前,Web Receiver SDK 支援下列媒體指令,適用於支援 Google 助理的裝置。這些指令的預設實作方式可在 cast.framework.PlayerManager 中找到。

指令 說明
播放 從暫停狀態播放或繼續播放。
暫停 暫停目前播放的內容。
返回 跳到媒體佇列中的上一個媒體項目。
繼續 跳至媒體佇列中的下一個媒體項目。
停止 停止播放目前的媒體。
不重複播放 待播清單中的最後一個項目播放完畢後,停用重複播放待播清單中的媒體項目。
重複單曲 無限期重複播放目前的媒體。
重複播放所有 播放待播清單中的最後一個項目後,重複播放待播清單中的所有項目。
重複播放所有項目和隨機播放 待播清單中的最後一個項目播放完畢後,請隨機播放並重複播放待播清單中的所有項目。
隨機播放 隨機播放媒體佇列中的媒體項目。
開啟 / 關閉隱藏式輔助字幕 為媒體啟用 / 停用隱藏式輔助字幕。啟用 / 停用功能也適用於語言。
Seek絕對時間 跳至指定的絕對時間。
Seek 到與目前時間相關的時間 相對於目前播放時間,向前或向後跳轉指定的時間長度。
再玩一次 重新啟動目前正在播放的媒體,或播放上次播放的媒體項目 (如果目前沒有任何媒體項目在播放的話)。
設定播放速率 變更媒體播放速率。這項作業應預設為處理。您可以使用 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 訊息傳送至 Web Receiver 應用程式。活動結束時,系統會傳送另一則含有 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 和流暢串流內容。

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

自訂訊息

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

傳送端會使用傳送端執行平台的傳送端 API (Android、iOS、網站),向網頁接收端發出訊息。傳遞至事件監聽器的事件物件 (訊息的呈現方式) 具有資料元素 (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 應用程式可使用 CastReceiverContext 上的 sendCustomMessage(namespace, senderId, message) 傳送訊息。Web Receiver 可將訊息傳送給個別傳送者,以回應收到的訊息,或因應用程式狀態變更而傳送。除了點對點訊息 (大小上限為 64kb) 之外,網頁接收器也可能會向所有已連線的傳送端廣播訊息。

投放到音訊裝置

如需僅音訊播放的支援資訊,請參閱 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 測試頁面,確認網站的受信任認證路徑是否包含標示為「extra download」的 CA 憑證,如果是的話,可能無法在 Android 平台上載入。
  • Chromecast 會在 720p 圖形平面上顯示接收器頁面,而其他 Cast 平台 (包括 Android TV) 則可能會以最高 1080p 的畫質顯示該頁面。確認接收器頁面可在不同解析度下順利縮放。