建立自訂網路接收器

1. 總覽

Google Cast 標誌

本程式碼研究室將說明如何建構自訂網路接收器應用程式,以便在支援 Cast 的裝置上播放內容。

什麼是 Google Cast?

Google Cast 可讓使用者將行動裝置上的內容投放到電視。這樣一來,使用者就能將行動裝置或電腦的 Chrome 瀏覽器當做遙控器,在電視上播放媒體。

Google Cast SDK 可讓您的應用程式控制支援 Google Cast 的裝置 (例如電視或音響系統)。Cast SDK 根據 Google Cast 設計檢查清單提供必要的 UI 元件。

我們提供了 Google Cast 設計檢查清單,大幅簡化所有支援平台的 Cast 使用者體驗,並讓使用者享有簡單預測。請按這裡瞭解詳情。

我們要建構什麼?

完成本程式碼研究室後,您將取得一個 HTML5 應用程式,做為自己的自訂接收器,以便在支援 Cast 的裝置上顯示影片內容。

課程內容

  • 如何設定接收器開發作業。
  • 支援 Cast 的接收器基本概念 (以 Cast 應用程式架構為依據)。
  • 如何接收投放的影片。
  • 如何整合偵錯記錄器。
  • 如何針對智慧螢幕最佳化接收器。

軟硬體需求

體驗

  • 您必須具有網站開發背景知識。
  • 你也需要事先瞭解看電視的知識 :)

您會如何使用這個教學課程?

僅供閱讀 閱讀並完成練習

針對建立網頁應用程式的經驗,您會給予什麼評價?

新手 中級 還算容易

你對觀看電視的體驗有什麼評價?

新手 中級 還算容易

2. 取得程式碼範例

您可以將所有程式碼範例下載至電腦...

然後將下載的 ZIP 檔案解壓縮。

3. 在本機部署接收器

如要搭配投放裝置使用網路接收器,請將裝置代管在投放裝置的位置。如果您已擁有支援 https 的伺服器,請略過下列指示並記下網址,因為在下一節中會用到。

如果你沒有可用伺服器,可改用 Firebase 代管ngrok

執行伺服器

設定好您選擇的服務後,請前往「app-start」並啟動伺服器。

請記下代管接收器的網址。您將在下一節中用到它。

4. 在 Cast 開發人員控制台註冊應用程式

您必須註冊應用程式,才能在 Chromecast 裝置上執行本程式碼研究室內建的自訂接收器。註冊應用程式之後,您就會收到應用程式 ID,您的傳送者應用程式必須使用這個 ID 才能執行 API 呼叫,例如啟動接收器應用程式。

Google Cast SDK 開發人員控制台顯示「新增應用程式」的圖片醒目顯示按鈕

按一下「新增應用程式」

「新接收端應用程式」的圖片顯示「Custom Receiver」已醒目顯示選項

選取 [自訂接收端]這就是我們正在建構的元件

「新增自訂接收端」的圖片畫面顯示使用者正在輸入「接收端應用程式網址」的網址欄位

輸入新接收端的詳細資料,請務必使用您最終提供的網址

最後一個部分請記下指派給全新接收器的應用程式 ID

此外,你必須註冊 Google Cast 裝置,以便在發布前存取接收器應用程式。接收器應用程式發布後,所有的 Google Cast 裝置皆可使用該應用程式。就本程式碼研究室而言,建議您使用尚未發布的接收器應用程式。

Google Cast SDK 開發人員控制台和「新增裝置」的圖片醒目顯示按鈕

按一下「新增裝置」

「新增 Cast 接收器裝置」的圖片對話方塊

輸入印在投放裝置背面的序號,並輸入描述性名稱。在 Chrome 中存取 Google Cast SDK 開發人員控制台時,您也可以投放畫面來找出序號

接收方和裝置需要 5 到 15 分鐘的時間才能測試。等待 5 到 15 分鐘後,你必須重新啟動投放裝置。

5. 執行範例應用程式

Google Chrome 標誌

在等待新接收器應用程式可供測試期間,來看看已完成的接收器應用程式範例。我們要建立的接收器將可使用自動調整位元率串流播放媒體 (我們將使用透過 HTTP 的動態自動調整串流 (DASH) 編碼的範例內容)。

在瀏覽器中開啟命令與控制 (CaC) 工具

「Cast Connect &」畫面的圖片Logger 控制項命令與控制 (CaC) 工具的標籤

  1. 我們應該會顯示 CaC 工具。
  2. 使用預設的「CC1AD845」範例接收器 ID,再按一下 [設定應用程式 ID]按鈕。
  3. 按一下左上方的「投放」按鈕,然後選取你的 Google Cast 裝置。

「Cast Connect &」畫面的圖片Logger 控制項命令與控制 (CaC) 工具的分頁,表示其已連線至接收端應用程式

  1. 前往「Load Media」頂端的標籤

「Load Media」的圖片命令與控制 (CaC) 工具的標籤

  1. 按一下「載入內容」播放範例影片。
  2. 影片會在 Google Cast 裝置上開始播放,並顯示使用預設接收器的基本接收器功能。

6. 準備 start 專案

系統會在您下載的啟動應用程式中新增 Google Cast 支援功能。以下是本程式碼研究室將使用的 Google Cast 術語:

  • 寄件者應用程式是在行動裝置或筆記型電腦上執行
  • 接收器應用程式是在 Google Cast 裝置上執行。

現在,您可以使用喜愛的文字編輯器,在範例專案上進行建構:

  1. 從下載的程式碼範例中選取 「資料夾」圖示app-start 目錄。
  2. 開啟 js/receiver.jsindex.html

請注意,在執行本程式碼研究室的過程中,http-server 應擷取您的變更。如果發現沒有反應,請嘗試終止並重新啟動 http-server

應用程式設計

接收端應用程式會初始化 Cast 工作階段,並保持待命,直到傳送者抵達的 LOAD 要求 (也就是播放媒體的指令) 送達為止。

應用程式包含一個在 index.html 中定義的主要檢視畫面,以及一個稱為 js/receiver.js 的 JavaScript 檔案,該檔案包含使接收端正常運作的所有邏輯。

index.html

這個 HTML 檔案將包含接收端應用程式的 UI。目前它是空的,我們會在本程式碼研究室中全程加入。

receiver.js

這個指令碼會管理接收器應用程式的所有邏輯。目前這只是一個空白檔案,但我們要在下一節中編寫幾行程式碼,將其轉換成功能完整的 Cast 接收器。

7. 基本的 Cast 接收器

基本的 Cast 接收器會在啟動時初始化投放工作階段。必須告知所有引發接收者的連線傳送應用程式已成功。此外,新版 SDK 還預先設定為直接處理自動調整的位元率串流 (使用 DASH、HLS 和 Smooth Streaming) 和一般 MP4 檔案。我們來試試。

初始化

將下列程式碼新增至標頭中的 index.html

<head>
  ...

  <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>

在 <footer> 載入 receiver.js, 前將下列程式碼新增至 index.html <body>,為接收端 SDK 提供用來顯示預設接收器 UI 的空間,其中包含您剛新增的指令碼。

<cast-media-player></cast-media-player>

現在,我們需要在 js/receiver.js 中初始化 SDK,包括:

  • 取得 CastReceiverContext 的參照,這是整個接收端 SDK 的主要進入點
  • 儲存對 PlayerManager 的參照,這個物件會處理播放作業,並提供您插入自訂邏輯所需的所有掛鉤
  • CastReceiverContext 上呼叫 start() 來初始化 SDK

將以下內容新增至 js/receiver.js

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

context.start();

8. 正在投放「基本」影片內容

就本程式碼研究室而言,您可以使用 CaC 工具試用您全新的接收器。

將網路瀏覽器指向命令與控制 (CaC) 工具

「Cast Connect &」畫面的圖片Logger 控制項命令與控制 (CaC) 工具的標籤

請務必替換成之前在欄位中註冊的應用程式 ID,然後按一下「設定應用程式 ID」。這樣可指示工具在啟動投放工作階段時使用接收器。

正在投放媒體

整體而言,如要在投放裝置上播放媒體,必須符合下列條件:

  1. 傳送方會從 Cast SDK 建立 MediaInfo JSON 物件,為媒體項目建立模型。
  2. 傳送者會連線至投放裝置,啟動接收器應用程式。
  3. 接收器透過 LOAD 要求載入 MediaInfo 物件以播放內容。
  4. 接收端會監控並追蹤媒體狀態。
  5. 傳送方傳送播放指令給接收端,根據使用者與傳送者應用程式的互動控製播放。

第一個基本嘗試將填入 MediaInfo 填入可播放的素材資源網址 (儲存在 MediaInfo.contentUrl 中)。

真實存在的傳送者會在 MediaInfo.contentId 中使用應用程式專屬的媒體 ID。接收端會使用 contentId 做為 ID,執行適當的後端 API 呼叫來解析實際的素材資源網址,並將其設為 MediaInfo.contentUrl.。接收端也會處理各種工作,例如取得數位版權管理授權,或插入廣告插播相關資訊。

我們即將擴充您的接收器,進行下一節的這類工作。目前請先按一下「投放」圖示並選取裝置,即可開啟接收器。

「Cast Connect &」畫面的圖片Logger 控制項命令與控制 (CaC) 工具的分頁,表示其已連線至接收端應用程式

前往「Load Media」然後按一下 [依內容載入]按鈕。接收器應會開始播放範例內容。

「Load Media」的圖片命令與控制 (CaC) 工具的標籤

接收端 SDK 可立即處理的內容,如下所示:

  • 正在初始化投放工作階段
  • 處理來自包含可播放資產的傳送者傳入的 LOAD 要求
  • 提供可在大螢幕上顯示的基本播放器 UI。

歡迎先瀏覽 CaC 工具及其程式碼,再繼續進行下一個部分。接下來我們會擴充接收器,以討論簡單的範例 API 來完成寄件者傳入的 LOAD 要求。

9. 與外部 API 整合

為配合大多數開發人員在實際應用程式中與 Cast 接收器互動的方式,我們會修改接收器,以處理透過其 API 金鑰參照目標媒體內容的 LOAD 要求,而不是透過可播放的資產網址。

應用程式通常是因為:

  • 寄件者可能不知道內容網址。
  • Cast 應用程式可以直接在接收器上處理驗證、其他商業邏輯或 API 呼叫。

這項功能主要是透過 PlayerManager setMessageInterceptor() 方法實作。這可讓您依類型攔截傳入的訊息,並在訊息傳送至 SDK 的內部訊息處理常式前加以修改。在本節中,我們會處理 LOAD 要求,並會採取以下行動:

  • 讀取傳入的 LOAD 要求及其自訂 contentId
  • 向 API 發出 GET 呼叫,以透過 contentId 查詢可串流資產。
  • 使用串流網址修改 LOAD 要求。
  • 修改 MediaInformation 物件,設定串流類型參數。
  • 請將請求傳送至 SDK 進行播放,如果我們無法查詢要求的媒體,則拒絕指令。

提供的範例 API 展示了 SDK 的掛鉤,可在自訂常見接收器工作時,一併提供大部分的立即可用的體驗。

API 範例

將瀏覽器指向 https://storage.googleapis.com/cpe-sample-media/content.json,並瀏覽我們的影片目錄範例。內容包含 PNG 格式的海報圖片網址,以及 DASH 和 HTTP 即時串流串流的網址。DASH 和 HLS 串流會指向儲存在分割的 mp4 容器中的虛擬影片和音訊來源。

{
  "bbb": {
    "author": "The Blender Project",
    "description": "Grumpy Bunny is grumpy",
    "poster": "https://[...]/[...]/BigBuckBunny/images/screenshot1.png",
    "stream": {
      "dash": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.mpd",
      "hls": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.m3u8",
    "title": "Big Buck Bunny"
  },
  "fbb_ad": {
    "author": "Google Inc.",
    "description": "Introducing Chromecast. The easiest way to enjoy [...]",
    "poster": "https://[...]/[...]/ForBiggerBlazes/images/screenshot8.png",
    "stream": {
      "dash": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.mpd",
      "hls": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.m3u8",
    "title": "For Bigger Blazes"
  },

  [...]

}

在下一個步驟中,我們會使用 LOAD 要求呼叫接收器,然後將每個項目的鍵 (例如 bbb, fbb_ad) 對應至串流的網址。

攔截 LOAD 要求

在這個步驟中,我們會建立一個載入攔截器,並使用函式對代管的 JSON 檔案發出 XHR 要求。取得 JSON 檔案後,系統就會剖析內容並設定中繼資料。在以下各節中,我們會自訂 MediaInformation 參數,指定內容類型。

將下列程式碼新增至 js/receiver.js 檔案,緊接在呼叫 context.start() 之前。

function makeRequest (method, url) {
  return new Promise(function (resolve, reject) {
    let xhr = new XMLHttpRequest();
    xhr.open(method, url);
    xhr.onload = function () {
      if (this.status >= 200 && this.status < 300) {
        resolve(JSON.parse(xhr.response));
      } else {
        reject({
          status: this.status,
          statusText: xhr.statusText
        });
      }
    };
    xhr.onerror = function () {
      reject({
        status: this.status,
        statusText: xhr.statusText
      });
    };
    xhr.send();
  });
}

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
        // Fetch content repository by requested contentId
        makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json').then(function (data) {
          let item = data[request.media.contentId];
          if(!item) {
            // Content could not be found in repository
            reject();
          } else {
            // Add metadata
            let metadata = new
               cast.framework.messages.GenericMediaMetadata();
            metadata.title = item.title;
            metadata.subtitle = item.author;

            request.media.metadata = metadata;

            // Resolve request
            resolve(request);
          }
        });
      });
    });

下一節將概述如何為 DASH 內容設定載入要求的 media 屬性。

使用範例 API DASH 內容

現在,我們已備妥載入攔截器,接下來要為接收端指定內容類型。這些資訊會為接收端提供主要播放清單網址和串流 MIME 類型。將下列程式碼加入 LOAD 攔截器的 Promise() 中的 js/receiver.js 檔案:

...
playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
          ...
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.dash;
            request.media.contentType = 'application/dash+xml';
            ...
          }
        });
      });
    });

完成這個步驟後,您可以繼續進行「測試」,嘗試以 DASH 內容載入。如要測試 HTTP 即時串流內容的載入作業,請改為查看下一個步驟。

使用範例 API HTTP 即時串流內容

範例 API 包含 HLS 內容和 DASH。除了和先前步驟一樣設定 contentType,載入要求還需加入一些額外屬性,才能使用範例 API 的 HLS 網址。接收器設為播放 HTTP 即時串流串流時,預設容器類型應為傳輸串流 (TS)。因此,如果只修改 contentUrl 屬性,接收端會嘗試開啟 TS 格式的範例 MP4 串流。在載入要求中,MediaInformation 物件應使用其他屬性修改,讓接收端知道內容類型為 MP4,而非 TS。將下列程式碼加入載入攔截器中的 js/receiver.js 檔案,修改 contentUrlcontentType 屬性。此外,請加入 HlsSegmentFormatHlsVideoSegmentFormat 屬性。

...
playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
          ...
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.hls;
            request.media.contentType = 'application/x-mpegurl';
            request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
            request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
            ...
          }
        });
      });
    });

測試

再次開啟「Command and Control (CaC) 工具」,然後將您的應用程式 ID 設為接收端的應用程式 ID。使用「投放」按鈕選取你的裝置。

前往「Load Media」分頁。這次刪除「內容網址」中的文字] 欄位的按鈕,可強制應用程式傳送僅包含 contentId 媒體參照的 LOAD 要求。

「Load Media」的圖片命令與控制 (CaC) 工具的標籤

假設所有修改作業都能與接收器修改作業順利搭配運作,攔截器應將 MediaInfo 物件調整成 SDK 可以在螢幕上播放的內容。

按一下「載入內容」] 按鈕,檢查媒體是否正常播放。你可以在 content.json 檔案中將 Content ID 改為其他 ID。

10. 針對智慧螢幕進行最佳化調整

智慧螢幕是具有觸控功能的裝置,可讓接收器應用程式支援觸控手勢的控制選項。

本節說明如何在智慧螢幕上啟動接收器應用程式時最佳化,以及如何自訂播放器控制項。

存取 UI 控制項

你可以使用 cast.framework.ui.Controls.GetInstance() 存取智慧螢幕的 UI 控制項物件。在 context.start() 上方的 js/receiver.js 檔案中新增下列程式碼:

...

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();

context.start();

如果您不使用 <cast-media-player>元素,您必須在 CastReceiverOptions 中設定 touchScreenOptimizedApp。在本程式碼研究室中,我們將使用 <cast-media-player>元素。

context.start({ touchScreenOptimizedApp: true });

系統會根據 MetadataTypeMediaStatus.supportedMediaCommands,為每個版位指派預設控制按鈕。

影片控制選項

如果是 MetadataType.MOVIEMetadataType.TV_SHOWMetadataType.GENERIC,智慧螢幕的 UI 控制項物件將如以下範例所示。

上方疊加顯示 UI 控制項的影片播放圖片

  1. --playback-logo-image
  2. MediaMetadata.subtitle
  3. MediaMetadata.title
  4. MediaStatus.currentTime
  5. MediaInformation.duration
  6. ControlsSlot.SLOT_SECONDARY_1ControlsButton.QUEUE_PREV
  7. ControlsSlot.SLOT_PRIMARY_1ControlsButton.SEEK_BACKWARD_30
  8. PLAY/PAUSE
  9. ControlsSlot.SLOT_PRIMARY_2ControlsButton.SEEK_FORWARD_30
  10. ControlsSlot.SLOT_SECONDARY_2ControlsButton.QUEUE_NEXT

音訊控制

如果是 MetadataType.MUSIC_TRACK,智慧螢幕的 UI 控制項物件將顯示如下:

正在播放音樂的圖片,上方疊加顯示 UI 控制項

  1. --playback-logo-image
  2. MusicTrackMediaMetadata.albumName
  3. MusicTrackMediaMetadata.title
  4. MusicTrackMediaMetadata.albumArtist
  5. MusicTrackMediaMetadata.images[0]
  6. MediaStatus.currentTime
  7. MediaInformation.duration
  8. ControlsSlot.SLOT_SECONDARY_1ControlsButton.NO_BUTTON
  9. ControlsSlot.SLOT_PRIMARY_1ControlsButton.QUEUE_PREV
  10. PLAY/PAUSE
  11. ControlsSlot.SLOT_PRIMARY_2ControlsButton.QUEUE_NEXT
  12. ControlsSlot.SLOT_SECONDARY_2ControlsButton.NO_BUTTON

更新支援的媒體指令

UI Controls 物件也會決定 ControlsButton 是否根據 MediaStatus.supportedMediaCommands 顯示。

supportedMediaCommands 的值等於 ALL_BASIC_MEDIA 時,預設的控製版面配置如下所示:

媒體播放器控制項的圖片,包括進度列、「播放」按鈕,「快轉」和「倒轉」按鈕已啟用

supportedMediaCommands 的值等於 ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT 時,預設的控製版面配置如下所示:

媒體播放器控制項的圖片,包括進度列、「播放」按鈕,「快轉」和「倒轉」按鈕和「排入上一個項目」和「Queue Next」按鈕已啟用

如果 supportedMediaCommands 值等於 PAUSE | QUEUE_PREV | QUEUE_NEXT,預設的控製版面配置如下:

媒體播放器控制項的圖片,包括進度列、「播放」按鈕和「排入上一個項目」和「Queue Next」按鈕已啟用

可使用文字軌時,隱藏式輔助字幕按鈕一律會在 SLOT_1 顯示。

媒體播放器控制項的圖片,包括進度列、「播放」按鈕,「快轉」和「倒轉」按鈕,「排入上一個佇列」和「Queue Next」按鈕和「隱藏式輔助字幕」按鈕已啟用

如要在啟動接收器結構定義後動態變更 supportedMediaCommands 的值,可以呼叫 PlayerManager.setSupportedMediaCommands 來覆寫值。此外,您也可以使用 addSupportedMediaCommands 新增指令,或使用 removeSupportedMediaCommands 移除現有指令。

自訂控制按鈕

您可以使用 PlayerDataBinder 自訂控制項。將以下程式碼新增到 TouchControls 下方的 js/receiver.js 檔案,設定控制項的第一個版位:

...

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);

playerDataBinder.addEventListener(
  cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
  (e) => {
    if (!e.value) return;

    // Clear default buttons and re-assign
    touchControls.clearDefaultSlotAssignments();
    touchControls.assignButton(
      cast.framework.ui.ControlsSlot.SLOT_PRIMARY_1,
      cast.framework.ui.ControlsButton.SEEK_BACKWARD_30
    );
  });

context.start();

11. 在智慧螢幕上實作媒體瀏覽

媒體瀏覽是一項 CAF 接收器功能,可讓使用者在觸控裝置上探索其他內容。為實作這項功能,您將使用 PlayerDataBinder 設定 BrowseContent UI。然後根據要顯示的內容,填入 BrowseItems

BrowseContent

以下是 BrowseContent UI 及其屬性的範例:

圖片:BrowseContent UI 顯示兩部影片縮圖,三張三分之一

  1. BrowseContent.title
  2. BrowseContent.items

顯示比例

請使用 targetAspectRatio property 選取最適合圖片素材資源的顯示比例。CAF 接收器 SDK 支援三種顯示比例:SQUARE_1_TO_1PORTRAIT_2_TO_3LANDSCAPE_16_TO_9

BrowseItem

使用 BrowseItem 顯示每個項目的標題、副標題、時間長度和圖片:

圖片:BrowseContent UI 顯示兩部影片縮圖,三張三分之一

  1. BrowseItem.image
  2. BrowseItem.duration
  3. BrowseItem.title
  4. BrowseItem.subtitle

設定媒體瀏覽資料

您可以呼叫 setBrowseContent 提供要瀏覽的媒體內容清單。將下列程式碼新增到 playerDataBinder 下方的 js/receiver.js 檔案,以及 MEDIA_CHANGED 事件監聽器中,以設定標題為「即將播放」的瀏覽項目。

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);

...

let browseItems = getBrowseItems();

function getBrowseItems() {
  let browseItems = [];
  makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
  .then(function (data) {
    for (let key in data) {
      let item = new cast.framework.ui.BrowseItem();
      item.entity = key;
      item.title = data[key].title;
      item.subtitle = data[key].description;
      item.image = new cast.framework.messages.Image(data[key].poster);
      item.imageType = cast.framework.ui.BrowseImageType.MOVIE;
      browseItems.push(item);
    }
  });
  return browseItems;
}

let browseContent = new cast.framework.ui.BrowseContent();
browseContent.title = 'Up Next';
browseContent.items = browseItems;
browseContent.targetAspectRatio = cast.framework.ui.BrowseImageAspectRatio.LANDSCAPE_16_TO_9;

playerDataBinder.addEventListener(
  cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
  (e) => {
    if (!e.value) return;

    ....

    // Media browse
    touchControls.setBrowseContent(browseContent);
  });

點按媒體瀏覽項目會觸發 LOAD 攔截器。將下列程式碼加入 LOAD 攔截器中,將 request.media.contentId 從媒體瀏覽項目對應至 request.media.entity

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

      // Map contentId to entity
      if (request.media && request.media.entity) {
        request.media.contentId = request.media.entity;
      }

      return new Promise((resolve, reject) => {
            ...
        });
    });

您也可以將 BrowseContent 物件設為 null,以移除 MediaBrowse UI。

12. 偵錯接收器應用程式

Cast Receiver SDK 提供另一個選項,可讓開發人員使用 CastDebugLogger API 和隨附的指令與控制 (CaC) 工具擷取記錄,輕鬆對接收器應用程式進行偵錯。

初始化

如要整合 API,請在 index.html 檔案中加入 CastDebugLogger 來源指令碼。來源應在 <head> 中宣告標記後方。

<head>
  ...
  <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
  <!-- Cast Debug Logger -->
  <script src="//www.gstatic.com/cast/sdk/libs/devtools/debug_layer/caf_receiver_logger.js"></script>
</head>

在檔案頂端和 playerManager 下方的 js/receiver.js 中,新增下列程式碼以擷取 CastDebugLogger 例項並啟用記錄器:

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

// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MyAPP.LOG';

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      castDebugLogger.setEnabled(true);
  }
});

啟用偵錯記錄器後,接收器會顯示顯示 DEBUG MODE 的重疊元素。

影片播放時使用「偵錯模式」的圖片訊息顯示在外框左上角的紅色背景上

記錄播放器事件

使用 CastDebugLogger 可讓您輕鬆記錄由 CAF 接收器 SDK 觸發的玩家事件,並使用不同的記錄器層級記錄事件資料。loggerLevelByEvents 設定使用 cast.framework.events.EventTypecast.framework.events.category 指定要記錄哪些事件。

請在 castDebugLogger 宣告下方加入以下程式碼,以便在系統觸發玩家 CORE 事件或 mediaStatus 變更時進行記錄:

// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      castDebugLogger.setEnabled(true);
  }
});

// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
  'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
  'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}

記錄訊息和自訂標記

CastDebugLogger API 可讓您建立記錄訊息,並以不同顏色顯示在接收器偵錯疊加上。可使用以下記錄方法,按優先順序由高到低依序列出:

  • castDebugLogger.error(custom_tag, message);
  • castDebugLogger.warn(custom_tag, message);
  • castDebugLogger.info(custom_tag, message);
  • castDebugLogger.debug(custom_tag, message);

每一個記錄方法的第一個參數都是自訂標記。可以是任何您認為有意義的識別字串。CastDebugLogger 會使用標記篩選記錄。下文將詳細說明標記的用法。第二個參數是記錄訊息

如要顯示記錄的實際運作情形,請將記錄新增至 LOAD 攔截器。

playerManager.setMessageInterceptor(
  cast.framework.messages.MessageType.LOAD,
  request => {
    castDebugLogger.info(LOG_TAG, 'Intercepting LOAD request');

    // Map contentId to entity
    if (request.media && request.media.entity) {
      request.media.contentId = request.media.entity;
    }

    return new Promise((resolve, reject) => {
      // Fetch content repository by requested contentId
      makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
        .then(function (data) {
          let item = data[request.media.contentId];
          if(!item) {
            // Content could not be found in repository
            castDebugLogger.error(LOG_TAG, 'Content not found');
            reject();
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.dash;
            request.media.contentType = 'application/dash+xml';
            castDebugLogger.warn(LOG_TAG, 'Playable URL:', request.media.contentUrl);

            // Add metadata
            let metadata = new cast.framework.messages.MovieMediaMetadata();
            metadata.metadataType = cast.framework.messages.MetadataType.MOVIE;
            metadata.title = item.title;
            metadata.subtitle = item.author;

            request.media.metadata = metadata;

            // Resolve request
            resolve(request);
          }
      });
    });
  });

只要在 loggerLevelByTags 中設定每個自訂標記的記錄層級,即可控制要顯示在偵錯疊加畫面的訊息。舉例來說,啟用記錄層級 cast.framework.LoggerLevel.DEBUG 的自訂標記時,會顯示所有加入的訊息,以及錯誤、警告、資訊和偵錯記錄訊息。啟用含有 WARNING 層級的自訂標記時,只會顯示錯誤和警告記錄訊息。

loggerLevelByTags 設定為選用項目。如果沒有針對記錄器層級設定自訂標記,偵錯疊加畫面將顯示所有記錄訊息。

CORE 事件記錄器下方新增下列程式碼:

// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
  'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
  'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}

// Set verbosity level for custom tags.
castDebugLogger.loggerLevelByTags = {
    [LOG_TAG]: cast.framework.LoggerLevel.DEBUG,
};

偵錯重疊

Cast Debug Logger 會在接收器上提供偵錯疊加層,以便在投放裝置上顯示您的自訂記錄訊息。使用 showDebugLogs 切換偵錯疊加層,並使用 clearDebugLogs 清除疊加上的記錄訊息。

加入下列程式碼即可在接收器上預覽偵錯重疊畫面。

context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      // Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
      castDebugLogger.setEnabled(true);

      // Show debug overlay
      castDebugLogger.showDebugLogs(true);

      // Clear log messages on debug overlay
      castDebugLogger.clearDebugLogs();
  }
});

顯示偵錯重疊圖片的圖片,這是一個半透明背景的偵錯記錄訊息清單,位於影片影格上方

13. 恭喜

您已瞭解如何使用 Cast Web Receiver SDK 建立自訂的網頁接收器應用程式。

詳情請參閱網路接收端開發人員指南。