建立自訂網路接收器

1. 總覽

Google Cast 標誌

本程式碼研究室將說明如何建構自訂 Web Receiver 應用程式,以便在支援投放功能的裝置上播放內容。

什麼是 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. 在本機部署接收器

如要搭配投放裝置使用網路接收器,您必須將裝置代管於支援 Cast 裝置的位置。如果您已擁有支援 https 的伺服器,請略過下列步驟,並記下網址 (下一節會用到)。

如果沒有可以使用的伺服器,可以使用 Firebase 託管ngrok

執行伺服器

設定完畢後,請前往 app-start 並啟動伺服器。

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

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

您必須註冊應用程式,才能在 Chromecast 裝置上執行自訂接收器 (如本程式碼研究室所述)。註冊應用程式後,您會收到傳送應用程式 ID 供傳送者應用程式執行 API 呼叫,例如啟動接收器應用程式。

Google Cast SDK 開發人員控制台的圖片,當中標出「Add New Application」(新增應用程式) 按鈕

按一下「新增應用程式」

「新增接收端應用程式」畫面的圖片,以方框特別標出「自訂接收端」選項

選取「自訂接收端」,這就是我們正在建構的項目。

圖片:「全新自訂接收器」畫面顯示某人在「接收端應用程式網址」欄位中輸入的網址

輸入新接收器的詳細資料,務必使用最後用來

可提供所有相關資訊記下指派給新接收端的應用程式 ID

此外,您也必須註冊 Google Cast 裝置,這樣裝置才能在您發布前存取接收器應用程式。發布接收器應用程式後,即可供所有 Google Cast 裝置使用。基於本程式碼研究室的用途,建議您使用未發布的接收器應用程式。

Google Cast SDK 開發人員控制台的圖片,當中標出「Add New Device」按鈕

按一下「新增裝置」

「新增投放接收端裝置」對話方塊的圖片

輸入印在 Google Cast 裝置背面的序號,然後設定一個描述性名稱。存取 Google Cast SDK 開發人員控制台時,在 Chrome 中投放畫面,也可以找到序號

可能需要 5 到 15 分鐘,接收者和裝置才能進行測試。等待 5 到 15 分鐘後,您必須重新啟動投放裝置。

5. 執行範例應用程式

Google Chrome 標誌

我們正在等待新的接收器應用程式可供測試時,來看看完成的範例接收器應用程式看起來如何。我們要建構的接收器將能透過自動調整位元率串流播放返回媒體 (我們將使用針對透過 HTTP 的 Dynamic Adaptive Streaming 編碼的範例內容 (DASH)。

在瀏覽器中開啟 Command and Control (CaC) Tool

Command and Control (CaC) 工具「投放連線及記錄器控制項」分頁的圖片

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

Command and Control (CaC) 工具的「Cast Connect & Logger Controls」分頁圖片,說明已連線至接收器應用程式

  1. 前往頂端的「Load Media」分頁。

Command and Control (CaC) 工具的「Load Media」分頁圖片

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

6. 準備 start 專案

對於你下載的啟動應用程式,我們需要新增 Google Cast 支援功能。以下是本程式碼研究室會使用的一些 Google Cast 術語:

  • 傳送者應用程式是在行動裝置或筆記型電腦上執行,
  • 接收端應用程式必須在 Google Cast 裝置上執行。

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

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

請注意,在執行本程式碼研究室時,http-server 應能擷取您所做的變更。如果未發現問題,請嘗試終止並重新啟動 http-server

應用程式設計

接收端應用程式會初始化「投放」工作階段,並會待在傳送方傳送 LOAD 要求 (也就是播放媒體片段的指令) 後才會結束。

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

index.html

此 HTML 檔案包含接收者應用程式的使用者介面。目前此內容沒有內容,我們將在整個程式碼研究室中添加。

receiver.js

這個指令碼會管理接收端應用程式的所有邏輯。現在只有空白檔案,我們會在下一節中只加入幾行程式碼,將內容轉換成功能齊全的 Cast 接收器。

7. 基本 Cast 接收器

基本的 Cast 接收器會在啟動時初始化投放工作階段。您必須這麼做,才能確定所有啟動接收端的連線應用程式都已成功。此外,新版 SDK 已預先設定,可立即處理可自動調整的位元率串流媒體 (使用 DASH、HLS 和流暢的串流) 和純 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 的參照,這是您為整個 Receiver SDK 的主要進入點
  • 儲存對 PlayerManager 的參照、物件處理播放作業,並提供插入您自訂邏輯所需的所有掛鉤
  • CastReceiverContext 上呼叫 start() 以初始化 SDK

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

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

context.start();

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

身為本程式碼研究室的學習目標,請使用 CaC 工具試用全新的接收器。

將網路瀏覽器指向 Command and Control (CaC) 工具

Command and Control (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.。接收端也會處理 DRM 授權擷取或插入廣告插播資訊等工作。

在下一節中,我們要進一步讓接收器執行類似工作。現在,按一下「投放」圖示,然後選取你的裝置即可開啟接收器。

Command and Control (CaC) 工具的「Cast Connect & Logger Controls」分頁圖片,說明已連線至接收器應用程式

瀏覽至「載入媒體」分頁,然後按一下「由內容載入」按鈕。接收端應會開始播放範例內容。

Command and Control (CaC) 工具的「Load Media」分頁圖片

接收器 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 即時串流 (HLS) 串流的網址。DASH 和 HTTP 即時串流 (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 內容。如果您想測試 HLS 內容的載入,請改為查看下一步。

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

範例 API 包含 HLS 內容和 DASH。除了和上一個步驟一樣的設定 contentType 之外,載入要求還需要一些額外屬性,才能使用範例 API 的 HLS 網址。如果接收器設定為播放 HLS 串流,預設容器類型應為傳輸串流 (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」分頁。這次會刪除「由內容載入」按鈕旁「內容網址」欄位中的文字,強制應用程式傳送只含有 Google 媒體 contentId 參照的 LOAD 要求。

Command and Control (CaC) 工具的「Load Media」分頁圖片

假設所有內容都能順利修改接收器,攔截器應將 MediaInfo 物件塑造為 SDK 可在螢幕上播放的內容。

按一下「載入內容」按鈕,看看媒體能否正常播放。您可以將 Content ID 改為 content.json 檔案中的其他 ID。

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

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

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

存取 UI 控制項

智慧螢幕的 UI Controls 物件可透過 cast.framework.ui.Controls.GetInstance() 存取。請將下列程式碼新增到 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 物件也會根據 MediaStatus.supportedMediaCommands 決定是否顯示 ControlsButton

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

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

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

媒體播放器控制項的圖片,包括進度列、「播放」按鈕、「快轉」和「倒轉」按鈕,以及已啟用「將上一個項目加入佇列」和「接著播放佇列」按鈕

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

媒體播放器控制項的圖片:已啟用的進度列、「播放」按鈕、已啟用「將上一個項目加入佇列」和「接著加入待播清單」按鈕

當有文字軌時,隱藏式輔助字幕按鈕將一律在 SLOT_1 顯示。

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

如要在啟動接收器結構定義後動態變更 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 及其屬性的範例:

顯示瀏覽內容 UI 的圖片,顯示兩張影片縮圖和三分之一的影片縮圖

  1. BrowseContent.title
  2. BrowseContent.items

顯示比例

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

BrowseItem

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

顯示瀏覽內容 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,藉此移除媒體瀏覽 UI。

12. 對接收器應用程式進行偵錯

Cast Receiver SDK 還提供另一種方式,可讓開發人員使用 CastDebugLogger API 以及隨附的 Command and Control (CaC) 工具擷取記錄,輕鬆對接收器應用程式進行偵錯。

初始化

如要整合 API,請在 index.html 檔案中加入 CastDebugLogger 來源指令碼。Cast Receiver SDK 宣告完成後,您必須在 <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>

在檔案頂端的 js/receiver.jsplayerManager 下方,新增下列程式碼,即可擷取 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 偵錯記錄器在接收端提供偵錯重疊,以在投放裝置上顯示您的自訂記錄訊息。使用 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 建立自訂網路接收器應用程式。

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