建立自訂網路接收器

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

如要透過 Cast 裝置使用網路接收器,你必須將網路接收器託管在 Cast 裝置可存取的位置。如果您已擁有支援 HTTPS 的伺服器,請略過以下操作說明,並記下網址,因為您會在下一節中使用該網址。

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

執行伺服器

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

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

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

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

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

按一下「新增應用程式」

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

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

「New Custom Receiver」畫面的圖片,顯示使用者在「Receiver Application URL」欄位中輸入的網址

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

最後一個部分記下新接收器的應用程式 ID

您也必須註冊 Google Cast 裝置,讓裝置在您發布接收器應用程式前,先存取該應用程式。接收器應用程式發布後,所有的 Google Cast 裝置皆可使用該應用程式。以本次程式碼研究室為例,建議您使用尚未發布的接收器應用程式。

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

按一下「新增裝置」

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

輸入 Cast 裝置背面所印的序號,並為裝置取個說明性名稱。你也可以在 Chrome 中投放螢幕畫面,然後存取 Google Cast SDK 開發人員控制台,藉此查看序號。

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

5. 執行範例應用程式

Google Chrome 標誌

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

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

指揮與控制 (CaC) 工具的「Cast Connect & Logger Controls」分頁圖片

  1. 畫面上應會顯示 CaC 工具。
  2. 使用預設的「CC1AD845」示範接收器 ID,然後按一下「Set App ID」(設定應用程式 ID) 按鈕。
  3. 按一下左上方的「投放」按鈕,然後選取你的 Google Cast 裝置。

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

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

指揮與控制 (CaC) 工具「Load Media」分頁的圖片

  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 接收器會在啟動時初始化 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> loading receiver.js, 之前,將下列程式碼新增至 index.html <body>,為接收器 SDK 提供空間,以便顯示預設接收器 UI,該 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 & Logger Controls」分頁圖片

請務必替換成之前在欄位中註冊的應用程式 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 授權取得或插入廣告插播資訊等工作。

在下一節中,我們將擴充接收器,讓它執行類似的操作。目前請先按一下「投放」圖示並選取裝置,即可開啟接收器。

指示已連線至接收器應用程式的「指揮與控制」(CaC) 工具「Cast Connect & Logger Controls」分頁圖片

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

指揮與控制 (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 即時串流串流的網址。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 內容載入。如果您想測試使用 HLS 內容的載入方式,請查看下一個步驟。

使用範例 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;
            ...
          }
        });
      });
    });

測試

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

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

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

假設您對接收器所做的修改一切正常,攔截器應會負責將 MediaInfo 物件轉換成 SDK 可在螢幕上播放的內容。

按一下「Load by Content」按鈕,確認媒體是否正常播放。你可以在 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 時,預設的控製版面配置如下所示:

媒體播放器控制項的圖片:進度列、「播放」按鈕、「快轉」和「倒轉」按鈕,以及啟用的「排隊上一個」和「排隊下一個」按鈕

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

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

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

媒體播放器控制項的圖片:進度列、&#39;Play&#39; 按鈕、&#39;Skip forward&#39; 和&#39;Skip backward&#39; 按鈕、&#39;Queue previous&#39; 和&#39;Queue next&#39; 按鈕,以及啟用的&#39;Closed Caption&#39; 按鈕

如要在啟動接收器內容後動態變更 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,提供媒體內容清單供瀏覽。將下列程式碼新增至 js/receiver.js 檔案的 playerDataBinder 下方和 MEDIA_CHANGED 事件監聽器中,以便設定標題為「Up Next」的瀏覽項目。

// 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 和搭配的 指令與控制 (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 接收器 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 建立自訂的網頁接收器應用程式。

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