建立自訂的網路接收器

1. 總覽

Google Cast 標誌

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

什麼是 Google Cast?

Google Cast 可讓使用者將內容從行動裝置投放到電視上。之後,使用者就能利用行動裝置或電腦的 Chrome 瀏覽器,以遠端控制電視播放媒體。

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

我們提供了 Google Cast 設計檢查清單,讓您在所有支援平台上都能享有簡單且可預測的投放體驗。請按這裡瞭解詳情。

我們要建構的是什麼?

完成本程式碼研究室後,您將擁有 HTML5 應用程式做為您的自訂接收器,可在支援 Cast 的裝置上顯示影片內容。

課程內容

  • 如何設定接收器的開發。
  • 以 Cast 架構為基礎的支援接收器的基本概念。
  • 如何接收投放影片。
  • 如何整合偵錯記錄工具。
  • 如何為智慧螢幕最佳化接收器。

軟硬體需求

功能

  • 您必須先具備之前的網站開發相關知識。
  • 您也需要具備先前觀看電視節目的知識 :)

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

唯讀 閱讀並完成練習

您對於建構網路應用程式的體驗如何?

新手 中級 專業知識

針對觀看電視的體驗,你會給予什麼評價?

新手 中級 專業知識

2. 取得程式碼範例

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

將下載的 ZIP 檔案解壓縮

3. 在本機部署接收器

如要透過 Cast 裝置使用網路接收器,你必須將網路託管於投放裝置可連結的地方。如果您已經有支援 https 的伺服器,請略過下列操作說明並記下網址,因為下一節將需要用到。

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

執行伺服器

選好服務之後,請前往 app-start 啟動您的伺服器。

記下代管接收器的網址。您將在下一節實作這項功能。

4. 在 Cast Developer Console 中註冊應用程式

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

Google Cast SDK Developer Console 的圖片,以方框特別標出「新增應用程式」按鈕

按一下 [新增應用程式]。

「新增接收器應用程式」畫面的圖片,醒目顯示的是「自訂接收器」選項

選取 [自訂接收器],這是我們所建構的。

「新增自訂接收器」畫面的圖片,其中包含使用者在「接收器應用程式網址」欄位中輸入的網址

輸入新收件者的詳細資料,請務必使用您最後輸入的網址

記下新申請者獲派的申請 ID

此外,您必須註冊 Google Cast 裝置,才能讓裝置存取接收器應用程式,然後再進行發布。接收器應用程式發布後,可供所有 Google Cast 裝置使用。在這個程式碼研究室中,建議您與未發布的接收器應用程式搭配使用。

Google Cast SDK Developer Console 的圖片,以方框特別標出「新增裝置」按鈕

按一下 [新增裝置]

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

輸入顯示在 Cast 裝置背面的序號,並輸入描述性名稱。在存取 Google Cast SDK Developer Console 時,您也可以在 Chrome 中投放螢幕,藉此找出您的序號

您的接收器和裝置需要 5 到 15 分鐘才能完成測試。等候 5 至 15 分鐘後,您必須重新啟動 Cast 裝置。

5. 執行範例應用程式

Google Chrome 標誌

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

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

指令與控制 (CaC) 工具的「Cast Connect 與記錄器控制項」分頁的圖片

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

指令與控制 (CaC) 工具的「Cast Connect 與記錄器控制項」分頁的圖片已連結到接收器應用程式

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

指令與控制 (CaC) 工具的「載入媒體」分頁的圖片

  1. 按一下 [按內容載入] 按鈕,即可播放範例影片。
  2. 影片隨即會在 Google Cast 裝置上開始播放,以顯示預設接收器功能的外觀。

6. 準備起始專案

我們需要針對支援下載的應用程式提供 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 檔案將包含接收端應用程式的使用者介面。目前這是空的,而且我們會在本程式碼研究室中將其加入。

接收器

這個指令碼會管理接收器應用程式的所有邏輯。目前這只是一個空白檔案,但我們會在下一節中簡單幾行程式碼,將其轉換為可正常運作的 Cast 接收器。

7. 基本的 Cast 接收器

基本 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 的參照,這是整個接收器 SDK 的主要進入點
  • 儲存 PlayerManager 的參照,此物件會處理播放作業,並提供您自訂外掛程式所需的所有掛鉤
  • 透過在 CastReceiverContext 上呼叫 start() 來初始化 SDK

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

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

context.start();

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

本程式碼研究室的目的,使用「CaC 工具」,試用新的接收器。

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

指令與控制 (CaC) 工具的「Cast Connect 與記錄器控制項」分頁的圖片

務必將先前申請的應用程式 ID 替換為先前註冊的「應用程式 ID」,然後按一下 [設定應用程式 ID]。這個指令會指示工具使用你的接收器來啟動 Cast 工作階段。

正在投放媒體

整體而言,如要在投放裝置上播放媒體,必須發生以下情況:

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

在第一次基本嘗合中,我後為為 MediaInfo 填充可播放的素材 URL(存儲在 MediaInfo.contentUrl)。

真實寄件者會在 MediaInfo.contentId 中使用應用程式專屬的媒體 ID。接收器會使用 contentId 做為 ID 發出適當的後端 API 呼叫,以解析實際資產網址並設為 MediaInfo.contentUrl.。接收器也會處理 DRM 授權擷取或插入廣告插播等工作。

我們將在下一節擴充您的接收器,以便執行類似的動作。此時,請按一下「投放」圖示,然後選取裝置以開啟接收器。

指令與控制 (CaC) 工具的「Cast Connect 與記錄器控制項」分頁的圖片已連結到接收器應用程式

前往 [載入媒體] 分頁,然後按一下 [按內容載入] 按鈕。您的接收器應會開始播放試聽內容。

指令與控制 (CaC) 工具的「載入媒體」分頁的圖片

因此,接收端 SDK 可立即處理:

  • 正在初始化 Cast 工作階段
  • 處理來自可播放資產的寄件者提出的 LOAD 要求
  • 提供基本的播放器 UI,可顯示在大螢幕上。

在前往下一個部分之前,建議您先探索「CaC 工具」及其程式碼,而我們將擴充接收器與簡單的範例 API 通訊,以處理來自寄件者的 LOAD 要求。

9. 與外部 API 整合

為因應多數開發人員在實際應用程式中與 Cast Receiver 互動的方式,我們將修改接收器,以處理透過其 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 和 HLS 串流。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 HLS 內容

範例 API 包含 HLS 內容和 DASH。contentType因此,如果只修改 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;
            ...
          }
        });
      });
    });

測試

再次開啟指令與控制 (CaC) 工具,然後將應用程式 ID 設為接收端的應用程式 ID。使用投放按鈕選取你的裝置。

前往「Load Media」分頁。這次請刪除 [Load by Content] (內容載入) 按鈕旁邊的 [Content URL] (內容網址) 欄位文字,強制應用程式只傳送包含 contentId 參照的 LOAD 要求至我們的媒體。

指令與控制 (CaC) 工具的「載入媒體」分頁的圖片

假設對接收器的修改作業均能正常運作,攔截器應負責將 MediaInfo 物件形狀成 SDK 可在螢幕上播放的內容。

按一下 [按內容載入] 按鈕,查看您的媒體是否能正確播放。請記得將 content.json 檔案中的內容 ID 變更為其他 ID。

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

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

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

存取 UI 控制項

可以使用 cast.framework.ui.Controls.GetInstance() 存取智慧螢幕的 UI Control 物件。將下列程式碼新增到 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 Control 物件將如下列範例所示。

影片播放中重疊顯示 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 控制項物件也會根據 MediaStatus.supportedMediaCommands 判斷是否要顯示 ControlsButton

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

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

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

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

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

媒體播放器控制項的圖片:已啟用進度列、「播放」按鈕,以及「將佇列排入佇列」按鈕和「接下來請播」按鈕

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

媒體播放器控制項的圖片:已啟用進度列、「播放」按鈕、「向前略過」和「向後略過」按鈕、「將上一個項目排入佇列」按鈕和「隱藏式輔助字幕」按鈕,而且已啟用「隱藏式輔助字幕」按鈕

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

自訂控制按鈕

您可以使用 PlayerDataBinder 自訂控制選項。請將以下程式碼加到 TouchControl 下方的 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 UI 及其屬性的範例:

瀏覽內容使用者介面圖片,顯示兩張影片縮圖,其中有三分之一

  1. BrowseContent.title
  2. BrowseContent.items

長寬比

使用 targetAspectRatio property 為圖片素材資源選取最佳長寬比。CAF 接收器的 SDK 支援三種長寬比:SQUARE_1_TO_1PORTRAIT_2_TO_3LANDSCAPE_16_TO_9

瀏覽項目

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

瀏覽內容使用者介面圖片,顯示兩張影片縮圖,其中有三分之一

  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.js 以及 playerManager 的下方,新增下列程式碼以擷取 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 Receiver 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,
};

偵錯重疊廣告

投放偵錯記錄程式會在接收器上提供偵錯重疊元素,以便在投放裝置上顯示自訂記錄訊息。使用 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 建立自訂網頁接收器應用程式。

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