Xây dựng trình thu nhận web tuỳ chỉnh

1. Tổng quan

Biểu trưng Google Cast

Lớp học lập trình này sẽ hướng dẫn bạn cách tạo một ứng dụng Custom Web Receiver để phát nội dung trên các thiết bị hỗ trợ Cast.

Google Cast là gì?

Google Cast cho phép người dùng truyền nội dung từ thiết bị di động lên TV. Sau đó, người dùng có thể sử dụng thiết bị di động hoặc Trình duyệt Chrome trên máy tính làm điều khiển từ xa để phát nội dung nghe nhìn trên TV.

Google Cast SDK cho phép ứng dụng của bạn điều khiển các thiết bị hỗ trợ Google Cast (ví dụ: TV hoặc hệ thống âm thanh). Cast SDK cung cấp cho bạn các thành phần giao diện người dùng cần thiết dựa trên Danh sách kiểm tra thiết kế của Google Cast.

Danh sách kiểm tra thiết kế Google Cast được cung cấp để giúp trải nghiệm người dùng Cast trở nên đơn giản và dễ đoán trên tất cả các nền tảng được hỗ trợ. Xem thêm tại đây.

Chúng ta sẽ xây dựng những gì?

Khi hoàn tất lớp học lập trình này, bạn sẽ có một ứng dụng HTML5 đóng vai trò là receiver tuỳ chỉnh của riêng bạn, có khả năng hiển thị nội dung video trên các thiết bị hỗ trợ Cast.

Kiến thức bạn sẽ học được

  • Cách thiết lập để phát triển receiver.
  • Thông tin cơ bản về một bộ nhận hỗ trợ Cast dựa trên Cast Application Framework.
  • Cách nhận video truyền.
  • Cách tích hợp Trình ghi nhật ký gỡ lỗi.
  • Cách tối ưu hoá receiver cho màn hình thông minh.

Bạn cần có

  • Trình duyệt Google Chrome mới nhất.
  • Dịch vụ lưu trữ HTTPS, chẳng hạn như Lưu trữ Firebase hoặc ngrok.
  • Một thiết bị Google Cast, chẳng hạn như Chromecast hoặc Android TV được thiết lập để có quyền truy cập vào Internet.
  • TV hoặc màn hình có cổng đầu vào HDMI.

Trải nghiệm

  • Bạn cần có kiến thức về phát triển web.
  • Bạn cũng cần có kiến thức về cách xem TV :)

Bạn sẽ sử dụng hướng dẫn này như thế nào?

Chỉ đọc Đọc và hoàn thành bài tập

Bạn đánh giá thế nào về trải nghiệm xây dựng ứng dụng web?

Người mới bắt đầu Trung cấp Thành thạo

Bạn đánh giá thế nào về trải nghiệm xem truyền hình?

Người mới bắt đầu Trung cấp Thành thạo

2. Nhận mã mẫu

Bạn có thể tải tất cả mã mẫu xuống máy tính...

và giải nén tệp zip đã tải xuống.

3. Triển khai bộ nhận tại địa phương

Để có thể sử dụng trình nhận web với một thiết bị truyền, bạn cần lưu trữ trình nhận web ở một nơi mà thiết bị truyền có thể truy cập. Nếu bạn đã có một máy chủ hỗ trợ https, hãy bỏ qua các hướng dẫn sau và ghi lại URL vì bạn sẽ cần URL đó trong phần tiếp theo.

Nếu không có máy chủ để sử dụng, bạn có thể dùng Lưu trữ Firebase hoặc ngrok.

Chạy máy chủ

Sau khi thiết lập dịch vụ bạn chọn, hãy chuyển đến app-start rồi khởi động máy chủ.

Ghi lại URL cho máy thu được lưu trữ. Bạn sẽ sử dụng đối tượng này trong phần tiếp theo.

4. Đăng ký một ứng dụng trong Cast Developer Console

Bạn phải đăng ký ứng dụng để có thể chạy một trình nhận tuỳ chỉnh (như được tạo trong lớp học lập trình này) trên các thiết bị Chromecast. Sau khi đăng ký ứng dụng, bạn sẽ nhận được một mã ứng dụng mà ứng dụng người gửi phải dùng để thực hiện các lệnh gọi API, chẳng hạn như để chạy một ứng dụng nhận.

Hình ảnh về Bảng điều khiển dành cho nhà phát triển SDK của Google Cast, trong đó nút "Thêm ứng dụng mới" được đánh dấu

Nhấp vào "Thêm ứng dụng mới"

Hình ảnh màn hình "Ứng dụng nhận mới" có lựa chọn "Trình nhận tuỳ chỉnh" được làm nổi bật

Chọn "Custom Receiver" (Trình nhận tuỳ chỉnh), đây là thành phần mà chúng ta sẽ tạo.

Hình ảnh màn hình "New Custom Receiver" (Trình nhận tuỳ chỉnh mới) cho thấy một URL mà người dùng đang nhập vào trường "Receiver Application URL" (URL ứng dụng nhận)

Nhập thông tin chi tiết về thiết bị nhận mới, nhớ sử dụng URL mà bạn đã nhận được

trong phần cuối. Ghi lại Mã ứng dụng được chỉ định cho bộ nhận hoàn toàn mới của bạn.

Bạn cũng phải đăng ký thiết bị truyền Google Cast để thiết bị đó có thể truy cập vào ứng dụng nhận trước khi bạn xuất bản ứng dụng. Sau khi bạn phát hành ứng dụng nhận, ứng dụng đó sẽ có trên tất cả các thiết bị Google Cast. Để phục vụ cho mục đích của lớp học lập trình này, bạn nên làm việc với một ứng dụng nhận chưa được xuất bản.

Hình ảnh Bảng điều khiển dành cho nhà phát triển SDK của Google Cast, trong đó nút "Thêm thiết bị mới" được làm nổi bật

Nhấp vào "Thêm thiết bị mới"

Hình ảnh hộp thoại "Thêm thiết bị nhận nội dung truyền"

Nhập số sê-ri in ở mặt sau của thiết bị truyền và đặt tên mô tả cho thiết bị đó. Bạn cũng có thể tìm thấy số sê-ri bằng cách truyền màn hình trong Chrome khi truy cập vào Bảng điều khiển dành cho nhà phát triển SDK của Google Cast

Quá trình này sẽ mất từ 5 đến 15 phút trước khi thiết bị và bộ nhận của bạn sẵn sàng kiểm thử. Sau khi đợi 5 đến 15 phút, bạn phải khởi động lại thiết bị truyền.

5. Chạy ứng dụng mẫu

Biểu trưng Google Chrome

Trong khi chờ ứng dụng nhận mới sẵn sàng để kiểm thử, hãy xem ứng dụng nhận mẫu đã hoàn tất trông như thế nào. Trình nhận mà chúng ta sẽ tạo có khả năng phát nội dung nghe nhìn bằng tính năng truyền phát trực tiếp tốc độ bit thích ứng (chúng ta sẽ sử dụng nội dung mẫu được mã hoá cho tính năng Truyền phát thích ứng động qua HTTP (DASH)).

Trong trình duyệt, hãy mở Công cụ chỉ huy và kiểm soát (CaC).

Hình ảnh thẻ "Cast Connect & Logger Controls" (Cast Connect và các chế độ điều khiển trình ghi nhật ký) của Công cụ Command and Control (CaC)

  1. Bạn sẽ thấy Công cụ CaC của chúng tôi.
  2. Sử dụng mã nhận dạng mẫu mặc định "CC1AD845" và nhấp vào nút "Set App ID" (Đặt mã ứng dụng).
  3. Nhấp vào nút Truyền ở trên cùng bên trái rồi chọn thiết bị truyền của bạn.

Hình ảnh thẻ "Cast Connect & Logger Controls" (Cast Connect và các chế độ điều khiển trình ghi nhật ký) của Công cụ Command and Control (CaC) cho biết thẻ này được kết nối với một Ứng dụng nhận

  1. Chuyển đến thẻ "Tải nội dung nghe nhìn" ở trên cùng.

Hình ảnh thẻ "Load Media" (Tải nội dung nghe nhìn) của Công cụ chỉ huy và kiểm soát (CaC)

  1. Nhấp vào nút "Load by Content" (Tải theo nội dung) để phát một video mẫu.
  2. Video sẽ bắt đầu phát trên thiết bị truyền Google Cast để cho thấy chức năng cơ bản của bộ nhận trông như thế nào khi dùng Bộ nhận mặc định.

6. Chuẩn bị dự án khởi đầu

Bạn cần thêm tính năng hỗ trợ Google Cast vào ứng dụng khởi động mà bạn đã tải xuống. Sau đây là một số thuật ngữ về Google Cast mà chúng ta sẽ sử dụng trong lớp học lập trình này:

  • ứng dụng người gửi chạy trên thiết bị di động hoặc máy tính xách tay,
  • ứng dụng receiver chạy trên thiết bị truyền Google Cast.

Giờ đây, bạn đã sẵn sàng xây dựng dựa trên dự án khởi đầu bằng trình chỉnh sửa văn bản mà bạn yêu thích:

  1. Chọn thư mục biểu tượng thư mụcapp-start trong tệp tải mã mẫu xuống.
  2. Mở js/receiver.jsindex.html

Lưu ý rằng khi bạn thực hiện lớp học lập trình này, http-server sẽ nhận biết được những thay đổi mà bạn thực hiện. Nếu bạn nhận thấy http-server không hoạt động, hãy thử tắt rồi khởi động lại ứng dụng này.

Thiết kế ứng dụng

Ứng dụng nhận khởi tạo phiên truyền và sẽ ở chế độ chờ cho đến khi nhận được yêu cầu LOAD (nói cách khác là lệnh phát một nội dung nghe nhìn) từ một ứng dụng gửi.

Ứng dụng này bao gồm một khung hiển thị chính (được xác định trong index.html) và một tệp JavaScript có tên là js/receiver.js chứa tất cả logic để giúp bộ nhận hoạt động.

index.html

Tệp HTML này sẽ chứa giao diện người dùng cho ứng dụng nhận. Hiện tại, tệp này đang trống và chúng ta sẽ thêm nội dung vào tệp này trong suốt lớp học lập trình.

receiver.js

Tập lệnh này sẽ quản lý tất cả logic cho ứng dụng nhận. Hiện tại, đây chỉ là một tệp trống, nhưng chúng ta sẽ biến tệp này thành một ứng dụng nhận Cast hoạt động đầy đủ chỉ với một vài dòng mã trong phần tiếp theo.

7. Thiết bị nhận Cast cơ bản

Một thiết bị nhận cơ bản của Cast sẽ khởi chạy phiên Cast khi khởi động. Điều này là cần thiết để thông báo cho tất cả các ứng dụng gửi đã kết nối rằng việc hiển thị ứng dụng nhận đã thành công. Ngoài ra, SDK mới được định cấu hình sẵn để xử lý nội dung nghe nhìn phát trực tuyến có tốc độ bit thích ứng (sử dụng DASH, HLS và Smooth Streaming) cũng như các tệp MP4 thông thường. Hãy thử xem.

Khởi chạy

Thêm mã sau vào index.html trong tiêu đề:

<head>
  ...

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

Thêm mã sau vào index.html <body> trước <footer> loading receiver.js, để cung cấp cho SDK bộ nhận không gian để hiển thị giao diện người dùng bộ nhận mặc định đi kèm với tập lệnh mà bạn vừa thêm.

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

Bây giờ, chúng ta cần khởi chạy SDK trong js/receiver.js, bao gồm:

  • thu thập thông tin tham chiếu đến CastReceiverContext, điểm truy cập chính của bạn vào toàn bộ Receiver SDK
  • lưu trữ một tham chiếu đến PlayerManager, đối tượng xử lý hoạt động phát và cung cấp cho bạn tất cả các hook cần thiết để kết nối logic tuỳ chỉnh của riêng bạn
  • khởi chạy SDK bằng cách gọi start() trên CastReceiverContext

Thêm nội dung sau vào js/receiver.js.

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

context.start();

8. Truyền nội dung video "cơ bản"

Trong phạm vi của Lớp học lập trình này, hãy sử dụng Công cụ CaC để dùng thử bộ nhận hoàn toàn mới của bạn.

Chuyển trình duyệt web của bạn đến Công cụ chỉ huy và kiểm soát (CaC).

Hình ảnh thẻ &quot;Cast Connect & Logger Controls&quot; (Cast Connect và các chế độ điều khiển trình ghi nhật ký) của Công cụ Command and Control (CaC)

Nhớ thay thế Mã ứng dụng của riêng bạn đã đăng ký trước đó trong trường này rồi nhấp vào "Đặt mã ứng dụng". Thao tác này hướng dẫn công cụ sử dụng bộ nhận khi bắt đầu phiên truyền.

Truyền nội dung nghe nhìn

Nhìn chung, để phát nội dung nghe nhìn trên một thiết bị truyền, bạn cần thực hiện những việc sau:

  1. Người gửi tạo một đối tượng MediaInfo JSON từ Cast SDK mô hình hoá một mục nội dung nghe nhìn.
  2. Người gửi kết nối với thiết bị truyền để chạy ứng dụng nhận.
  3. Trình nhận tải đối tượng MediaInfo thông qua yêu cầu LOAD để phát nội dung.
  4. Trình nhận giám sát và theo dõi trạng thái của nội dung nghe nhìn.
  5. Người gửi gửi các lệnh phát đến bộ nhận để kiểm soát chế độ phát dựa trên hoạt động tương tác của người dùng với ứng dụng người gửi.

Trong lần thử cơ bản đầu tiên này, chúng ta sẽ điền sẵn MediaInfo bằng một URL tài sản có thể phát (được lưu trữ trong MediaInfo.contentUrl).

Người gửi thực tế sử dụng mã nhận dạng nội dung nghe nhìn dành riêng cho ứng dụng trong MediaInfo.contentId. Trình nhận dùng contentId làm giá trị nhận dạng để thực hiện các lệnh gọi API phụ trợ thích hợp nhằm phân giải URL thực tế của tài sản và đặt URL đó thành MediaInfo.contentUrl.. Trình nhận cũng sẽ xử lý các tác vụ như lấy giấy phép DRM hoặc chèn thông tin về các điểm chèn quảng cáo.

Trong phần tiếp theo, chúng ta sẽ mở rộng receiver để làm điều tương tự. Hiện tại, hãy nhấp vào biểu tượng Truyền rồi chọn thiết bị để mở bộ nhận.

Hình ảnh thẻ &quot;Cast Connect & Logger Controls&quot; (Cast Connect và các chế độ điều khiển trình ghi nhật ký) của Công cụ Command and Control (CaC) cho biết thẻ này được kết nối với một Ứng dụng nhận

Chuyển đến thẻ "Load Media" (Tải nội dung nghe nhìn) rồi nhấp vào nút "Load by Content" (Tải theo nội dung). Thiết bị nhận sẽ bắt đầu phát nội dung mẫu.

Hình ảnh thẻ &quot;Load Media&quot; (Tải nội dung nghe nhìn) của Công cụ chỉ huy và kiểm soát (CaC)

Vì vậy, Receiver SDK có sẵn sẽ xử lý:

  • Đang khởi tạo phiên truyền
  • Xử lý các yêu cầu LOAD đến từ những người gửi có chứa tài sản có thể phát
  • Cung cấp một giao diện người dùng cơ bản của trình phát, sẵn sàng hiển thị trên màn hình lớn.

Bạn có thể khám phá Công cụ CaC và mã của công cụ này trước khi chuyển sang phần tiếp theo. Trong phần này, chúng ta sẽ mở rộng receiver để giao tiếp với một API mẫu đơn giản nhằm thực hiện các yêu cầu LOAD đến từ người gửi.

9. Tích hợp với một API bên ngoài

Theo cách mà hầu hết nhà phát triển tương tác với Cast Receiver trong các ứng dụng thực tế, chúng tôi sẽ sửa đổi receiver để xử lý các yêu cầu LOAD tham chiếu đến nội dung nghe nhìn dự kiến bằng khoá API thay vì gửi URL tài sản có thể phát.

Các ứng dụng thường làm như vậy vì:

  • Người gửi có thể không biết URL nội dung.
  • Ứng dụng Cast được thiết kế để xử lý việc xác thực, logic nghiệp vụ khác hoặc các lệnh gọi API ngay trên thiết bị nhận.

Chức năng này chủ yếu được triển khai trong phương thức PlayerManager setMessageInterceptor(). Điều này cho phép bạn chặn các thông báo đến theo loại và sửa đổi chúng trước khi chúng đến trình xử lý thông báo nội bộ của SDK. Trong phần này, chúng ta sẽ xử lý các yêu cầu LOAD, trong đó chúng ta sẽ làm những việc sau:

  • Đọc yêu cầu LOAD đến và contentId tuỳ chỉnh của yêu cầu đó.
  • Gọi GET đến API của chúng tôi để tra cứu tài sản có thể phát trực tuyến theo contentId.
  • Sửa đổi yêu cầu LOAD bằng URL của luồng phát.
  • Sửa đổi đối tượng MediaInformation để đặt các tham số loại luồng phát.
  • Truyền yêu cầu đến SDK để phát hoặc từ chối lệnh nếu chúng tôi không thể tra cứu nội dung nghe nhìn được yêu cầu.

API mẫu được cung cấp minh hoạ các lệnh gọi của SDK để tuỳ chỉnh các tác vụ phổ biến của receiver, trong khi vẫn dựa vào trải nghiệm hầu như có sẵn.

API mẫu

Truy cập https://storage.googleapis.com/cpe-sample-media/content.json trong trình duyệt để xem danh mục video mẫu của chúng tôi. Nội dung này bao gồm URL cho hình ảnh áp phích ở định dạng png cũng như cả luồng DASH và HLS. Luồng DASH và HLS trỏ đến các nguồn video và âm thanh đã tách kênh được lưu trữ trong các vùng chứa mp4 phân đoạn.

{
  "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"
  },

  [...]

}

Ở bước tiếp theo, chúng ta sẽ liên kết khoá của từng mục nhập (ví dụ: bbb, fbb_ad) với URL của luồng sau khi bộ nhận được gọi bằng một yêu cầu LOAD.

Chặn yêu cầu LOAD

Ở bước này, chúng ta sẽ tạo một trình chặn tải có chức năng đưa ra yêu cầu XHR đối với tệp JSON được lưu trữ. Sau khi nhận được tệp JSON, chúng tôi sẽ phân tích cú pháp nội dung và đặt siêu dữ liệu. Trong các phần sau, chúng ta sẽ tuỳ chỉnh các tham số MediaInformation để chỉ định loại nội dung.

Thêm mã sau đây vào tệp js/receiver.js, ngay trước lệnh gọi đến 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);
          }
        });
      });
    });

Phần tiếp theo sẽ trình bày cách định cấu hình thuộc tính media của yêu cầu tải cho nội dung DASH.

Sử dụng nội dung DASH mẫu của API

Giờ đây, sau khi chuẩn bị trình chặn tải, chúng ta sẽ chỉ định loại nội dung cho receiver. Thông tin này sẽ cung cấp cho thiết bị nhận URL danh sách phát chính và loại MIME của luồng phát. Thêm mã sau vào tệp js/receiver.js trong Promise() của trình chặn LOAD:

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

Sau khi hoàn tất bước này, bạn có thể chuyển sang phần Thử nghiệm để thử tải nội dung bằng DASH. Nếu bạn muốn kiểm thử việc tải bằng nội dung HLS, hãy xem bước tiếp theo.

Sử dụng nội dung HLS mẫu của API

API mẫu này bao gồm cả nội dung HLS và DASH. Ngoài việc đặt contentType như chúng ta đã làm ở bước trước, yêu cầu tải sẽ cần một số thuộc tính bổ sung để sử dụng các URL HLS của API mẫu. Khi được định cấu hình để phát các luồng HLS, loại vùng chứa mặc định dự kiến là luồng truyền tải (TS). Do đó, nếu chỉ sửa đổi thuộc tính contentUrl, thì receiver sẽ cố gắng mở các luồng MP4 mẫu ở định dạng TS. Trong yêu cầu tải, đối tượng MediaInformation phải được sửa đổi bằng các thuộc tính bổ sung để máy nhận biết rằng nội dung thuộc loại MP4 chứ không phải TS. Thêm mã sau vào tệp js/receiver.js trong trình chặn tải để sửa đổi các thuộc tính contentUrlcontentType. Ngoài ra, hãy thêm các thuộc tính 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;
            ...
          }
        });
      });
    });

Thử nghiệm

Một lần nữa, hãy mở Công cụ Lệnh và kiểm soát (CaC) rồi đặt App ID thành App ID của bộ nhận. Chọn thiết bị bằng nút Truyền.

Chuyển đến thẻ "Tải nội dung nghe nhìn". Lần này, hãy xoá văn bản trong trường "URL nội dung" bên cạnh nút "Tải theo nội dung". Thao tác này sẽ buộc ứng dụng của chúng tôi gửi một yêu cầu LOAD chỉ chứa tham chiếu contentId đến nội dung nghe nhìn của chúng tôi.

Hình ảnh thẻ &quot;Load Media&quot; (Tải nội dung nghe nhìn) của Công cụ chỉ huy và kiểm soát (CaC)

Giả sử mọi thứ đều hoạt động bình thường với các nội dung sửa đổi của bạn đối với receiver, interceptor sẽ đảm nhận việc định hình đối tượng MediaInfo thành một đối tượng mà SDK có thể phát trên màn hình.

Nhấp vào nút "Load by Content" (Tải theo nội dung) để xem nội dung nghe nhìn của bạn có phát đúng cách hay không. Bạn có thể thay đổi Content ID thành một ID khác trong tệp content.json.

10. Tối ưu hoá cho màn hình thông minh

Màn hình thông minh là những thiết bị có chức năng cảm ứng, cho phép các ứng dụng nhận hỗ trợ các chế độ điều khiển cảm ứng.

Phần này giải thích cách tối ưu hoá ứng dụng nhận khi khởi chạy trên màn hình thông minh và cách tuỳ chỉnh các nút điều khiển trình phát.

Truy cập vào các thành phần điều khiển trên giao diện người dùng

Bạn có thể truy cập vào đối tượng UI Controls (Các chế độ kiểm soát giao diện người dùng) cho Màn hình thông minh bằng cách sử dụng cast.framework.ui.Controls.GetInstance(). Thêm đoạn mã sau vào tệp js/receiver.js ở phía trên context.start():

...

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

context.start();

Nếu không sử dụng phần tử <cast-media-player>, bạn sẽ cần đặt touchScreenOptimizedApp trong CastReceiverOptions. Trong lớp học lập trình này, chúng ta sẽ sử dụng phần tử <cast-media-player>.

context.start({ touchScreenOptimizedApp: true });

Các nút điều khiển mặc định được chỉ định cho từng khe dựa trên MetadataTypeMediaStatus.supportedMediaCommands.

Các nút điều khiển video

Đối với MetadataType.MOVIE, MetadataType.TV_SHOWMetadataType.GENERIC, đối tượng UI Controls (Các chế độ kiểm soát giao diện người dùng) cho Màn hình thông minh sẽ xuất hiện như trong ví dụ bên dưới.

Hình ảnh video đang phát có các nút điều khiển giao diện người dùng phủ lên trên

  1. --playback-logo-image
  2. MediaMetadata.subtitle
  3. MediaMetadata.title
  4. MediaStatus.currentTime
  5. MediaInformation.duration
  6. ControlsSlot.SLOT_SECONDARY_1: ControlsButton.QUEUE_PREV
  7. ControlsSlot.SLOT_PRIMARY_1: ControlsButton.SEEK_BACKWARD_30
  8. PLAY/PAUSE
  9. ControlsSlot.SLOT_PRIMARY_2: ControlsButton.SEEK_FORWARD_30
  10. ControlsSlot.SLOT_SECONDARY_2: ControlsButton.QUEUE_NEXT

Điều khiển âm thanh

Đối với MetadataType.MUSIC_TRACK, đối tượng UI Controls (Các thành phần điều khiển trên giao diện người dùng) cho Màn hình thông minh sẽ xuất hiện như sau:

Hình ảnh nhạc đang phát với các chế độ điều khiển trên giao diện người dùng được đặt ở trên cùng

  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_1: ControlsButton.NO_BUTTON
  9. ControlsSlot.SLOT_PRIMARY_1: ControlsButton.QUEUE_PREV
  10. PLAY/PAUSE
  11. ControlsSlot.SLOT_PRIMARY_2: ControlsButton.QUEUE_NEXT
  12. ControlsSlot.SLOT_SECONDARY_2: ControlsButton.NO_BUTTON

Cập nhật các lệnh về nội dung nghe nhìn được hỗ trợ

Đối tượng UI Controls cũng xác định xem ControlsButton có xuất hiện hay không dựa trên MediaStatus.supportedMediaCommands.

Khi giá trị của supportedMediaCommands bằng ALL_BASIC_MEDIA, bố cục điều khiển mặc định sẽ hiển thị như sau:

Hình ảnh các nút điều khiển trình phát nội dung nghe nhìn: thanh tiến trình, nút &quot;Phát&quot;, nút &quot;Bỏ qua tiến&quot; và nút &quot;Bỏ qua lùi&quot; được bật

Khi giá trị của supportedMediaCommands bằng ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT, bố cục điều khiển mặc định sẽ hiển thị như sau:

Hình ảnh về các nút điều khiển trình phát: thanh tiến trình, nút &quot;Phát&quot;, nút &quot;Tua đi&quot; và &quot;Tua lại&quot;, cũng như nút &quot;Hàng đợi trước&quot; và &quot;Hàng đợi tiếp theo&quot; được bật

Khi giá trị của supportedMediaCommands bằng PAUSE | QUEUE_PREV | QUEUE_NEXT, bố cục điều khiển mặc định sẽ hiển thị như sau:

Hình ảnh về các nút điều khiển trình phát: thanh tiến trình, nút &quot;Phát&quot; và nút &quot;Thêm vào hàng đợi trước đó&quot; và &quot;Thêm vào hàng đợi tiếp theo&quot; được bật

Khi có tệp phụ đề, nút phụ đề sẽ luôn xuất hiện tại biểu tượng SLOT_1.

Hình ảnh các nút điều khiển trình phát nội dung nghe nhìn: thanh tiến trình, nút &quot;Phát&quot;, nút &quot;Tua đi&quot; và &quot;Tua lại&quot;, nút &quot;Hàng đợi trước đó&quot; và &quot;Hàng đợi tiếp theo&quot;, cũng như nút &quot;Phụ đề&quot; đã bật

Để thay đổi giá trị của supportedMediaCommands một cách linh động sau khi bắt đầu một ngữ cảnh của bộ nhận, bạn có thể gọi PlayerManager.setSupportedMediaCommands để ghi đè giá trị. Ngoài ra, bạn có thể thêm lệnh mới bằng cách sử dụng addSupportedMediaCommands hoặc xoá lệnh hiện có bằng cách sử dụng removeSupportedMediaCommands.

Tuỳ chỉnh các nút điều khiển

Bạn có thể tuỳ chỉnh các chế độ kiểm soát bằng cách sử dụng PlayerDataBinder. Thêm đoạn mã sau vào tệp js/receiver.js bên dưới touchControls để đặt khe cắm đầu tiên cho các chế độ điều khiển:

...

// 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. Triển khai tính năng duyệt xem nội dung nghe nhìn trên màn hình thông minh

Media Browse là một tính năng của CAF Receiver, cho phép người dùng khám phá nội dung bổ sung trên các thiết bị cảm ứng. Để triển khai việc này, bạn sẽ dùng PlayerDataBinder để đặt giao diện người dùng BrowseContent. Sau đó, bạn có thể điền BrowseItems vào đó dựa trên nội dung bạn muốn hiển thị.

BrowseContent

Dưới đây là ví dụ về giao diện người dùng BrowseContent và các thuộc tính của giao diện này:

Hình ảnh về giao diện người dùng BrowseContent cho thấy 2 hình thu nhỏ của video và một phần của hình thu nhỏ thứ ba

  1. BrowseContent.title
  2. BrowseContent.items

Tỷ lệ khung hình

Sử dụng biểu tượng targetAspectRatio property để chọn tỷ lệ khung hình phù hợp nhất cho thành phần hình ảnh. CAF Receiver SDK hỗ trợ 3 tỷ lệ khung hình: SQUARE_1_TO_1, PORTRAIT_2_TO_3, LANDSCAPE_16_TO_9.

BrowseItem

Sử dụng BrowseItem để hiển thị tiêu đề, phụ đề, thời lượng và hình ảnh cho từng mục:

Hình ảnh về giao diện người dùng BrowseContent cho thấy 2 hình thu nhỏ của video và một phần của hình thu nhỏ thứ ba

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

Đặt dữ liệu Duyệt qua nội dung nghe nhìn

Bạn có thể cung cấp danh sách nội dung nghe nhìn để duyệt xem bằng cách gọi setBrowseContent. Thêm mã sau vào tệp js/receiver.js bên dưới playerDataBinder và trong trình nghe sự kiện MEDIA_CHANGED để đặt các mục duyệt xem có tiêu đề "Tiếp theo".

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

Khi bạn nhấp vào một mục duyệt xem nội dung nghe nhìn, trình chặn LOAD sẽ được kích hoạt. Thêm mã sau vào trình chặn LOAD để liên kết request.media.contentId với request.media.entity từ mục duyệt qua nội dung nghe nhìn:

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) => {
            ...
        });
    });

Bạn cũng có thể đặt đối tượng BrowseContent thành null để xoá Giao diện người dùng Duyệt xem nội dung nghe nhìn.

12. Gỡ lỗi ứng dụng nhận

Cast Receiver SDK cung cấp một lựa chọn khác để nhà phát triển dễ dàng gỡ lỗi ứng dụng nhận bằng cách sử dụng CastDebugLogger APICông cụ điều khiển và kiểm soát (CaC) đi kèm để ghi lại nhật ký.

Khởi chạy

Để kết hợp API, hãy thêm tập lệnh nguồn CastDebugLogger vào tệp index.html. Nguồn phải được khai báo trong thẻ <head> sau khi khai báo Cast Receiver SDK.

<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>

Trong js/receiver.js ở đầu tệp và bên dưới playerManager, hãy thêm mã sau để truy xuất thực thể CastDebugLogger và bật trình ghi nhật ký:

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

Khi bạn bật trình ghi nhật ký gỡ lỗi, một lớp phủ hiển thị DEBUG MODE sẽ xuất hiện trên thiết bị nhận.

Hình ảnh một video đang phát với thông báo &quot;CHẾ ĐỘ GỠ LỖI&quot; xuất hiện trên nền đỏ ở góc trên bên trái của khung hình

Ghi nhật ký sự kiện của trình phát

Khi sử dụng CastDebugLogger, bạn có thể dễ dàng ghi lại các sự kiện của trình phát do CAF Receiver SDK kích hoạt và sử dụng các cấp trình ghi nhật ký khác nhau để ghi lại dữ liệu sự kiện. Cấu hình loggerLevelByEvents sử dụng cast.framework.events.EventTypecast.framework.events.category để chỉ định những sự kiện sẽ được ghi lại.

Thêm mã sau bên dưới khai báo castDebugLogger để ghi nhật ký khi sự kiện CORE của trình phát được kích hoạt hoặc thay đổi mediaStatus được phát:

// 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
}

Thông điệp nhật ký và thẻ tuỳ chỉnh

CastDebugLogger API cho phép bạn tạo các thông báo nhật ký xuất hiện trên lớp gỡ lỗi của bộ nhận bằng nhiều màu sắc. Sau đây là các phương thức ghi nhật ký có sẵn, được liệt kê theo thứ tự ưu tiên từ cao nhất đến thấp nhất:

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

Đối với mỗi phương thức ghi nhật ký, tham số đầu tiên là một thẻ tuỳ chỉnh. Đây có thể là chuỗi nhận dạng bất kỳ mà bạn thấy có ý nghĩa. CastDebugLogger sử dụng thẻ để lọc nhật ký. Việc sử dụng thẻ được giải thích chi tiết hơn ở phần dưới đây. Tham số thứ hai là thông điệp nhật ký.

Để xem nhật ký hoạt động, hãy thêm nhật ký vào trình chặn 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);
          }
      });
    });
  });

Bạn có thể kiểm soát những thông báo xuất hiện trên lớp gỡ lỗi bằng cách đặt cấp độ nhật ký trong loggerLevelByTags cho từng thẻ tuỳ chỉnh. Ví dụ: việc bật một thẻ tuỳ chỉnh có cấp nhật ký cast.framework.LoggerLevel.DEBUG sẽ hiển thị tất cả thông báo được thêm bằng thông báo nhật ký lỗi, cảnh báo, thông tin và gỡ lỗi. Việc bật thẻ tuỳ chỉnh ở cấp WARNING sẽ chỉ hiển thị thông báo nhật ký lỗi và cảnh báo.

Bạn không bắt buộc phải dùng cấu hình loggerLevelByTags. Nếu bạn không định cấu hình thẻ tuỳ chỉnh cho cấp độ trình ghi nhật ký, thì tất cả thông báo nhật ký sẽ xuất hiện trên lớp gỡ lỗi.

Thêm mã sau bên dưới trình ghi sự kiện 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,
};

Lớp phủ gỡ lỗi

Cast Debug Logger cung cấp một lớp phủ gỡ lỗi trên receiver để hiển thị thông báo nhật ký tuỳ chỉnh trên thiết bị truyền. Sử dụng showDebugLogs để bật/tắt lớp phủ gỡ lỗi và clearDebugLogs để xoá thông báo nhật ký trên lớp phủ.

Thêm mã sau để xem trước lớp gỡ lỗi trên bộ nhận.

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

Hình ảnh cho thấy lớp phủ gỡ lỗi, danh sách thông báo nhật ký gỡ lỗi trên nền mờ ở trên cùng của một khung hình video

13. Xin chúc mừng

Giờ đây, bạn đã biết cách tạo một ứng dụng web nhận tuỳ chỉnh bằng Cast Web Receiver SDK.

Để biết thêm thông tin chi tiết, hãy xem hướng dẫn dành cho nhà phát triển Web Receiver.