Bật tính năng truyền cho ứng dụng web

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 sửa đổi một ứng dụng video trên web hiện có để truyền nội dung trên một thiết bị hỗ trợ Google 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 tới TV. Sau đó, người dùng có thể sử dụng thiết bị di động làm điều khiển từ xa để phát nội dung nghe nhìn trên TV.

SDK Google Cast cho phép bạn mở rộng ứng dụng của mình để điều khiển TV hoặc hệ thống âm thanh. SDK Cast cho phép bạn thêm 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ế của 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ễ dự đoán trên tất cả các nền tảng được hỗ trợ.

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 video trên web dành cho Chrome có khả năng Truyền video tới thiết bị Google Cast.

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

  • Cách thêm SDK Google Cast vào ứng dụng video mẫu.
  • Cách thêm nút Truyền để chọn thiết bị Google Cast.
  • Cách kết nối với một Thiết bị truyền và khởi chạy bộ thu nội dung đa phương tiện.
  • Cách truyền video.
  • Cách tích hợp Cast Connect

Bạn cần có

  • Trình duyệt Google Chrome mới nhất.
  • Dịch vụ lưu trữ HTTPS như Lưu trữ Firebase hoặc ngrok.
  • Một thiết bị Google Cast như Chromecast hoặc Android TV được định cấu hình có kết nối Internet.
  • TV hoặc màn hình có đầu vào HDMI.
  • Bạn cần có Chromecast có Google TV để kiểm tra quá trình tích hợp Cast Connect nhưng không bắt buộc trong phần còn lại của lớp học lập trình này. Nếu bạn chưa có dịch vụ hỗ trợ Cast Connect, vui lòng bỏ qua bước Thêm tính năng hỗ trợ Cast Connect ở cuối hướng dẫn này.

Trải nghiệm

  • Bạn sẽ cần phải có kiến thức phát triển web trước đó.
  • Bạn cũng sẽ cần có kiến thức trước về cách xem TV :)

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

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

Bạn đánh giá trải nghiệm xây dựng ứng dụng web của mình như thế nào?

Người mới tập Trung cấp Thành thạo

Bạn đánh giá trải nghiệm xem TV của mình ở mức nào?

Người mới tập 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. Chạy ứng dụng mẫu

Biểu trưng Google Chrome

Trước tiên, hãy cùng xem ứng dụng mẫu hoàn chỉnh sẽ có giao diện như thế nào. Ứng dụng là một trình phát video cơ bản. Người dùng có thể chọn một video trong danh sách rồi phát video đó trên thiết bị hoặc Truyền video đó tới thiết bị Google Cast.

Để có thể sử dụng tệp hoàn chỉnh, bạn cần lưu trữ tệp đó.

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

Chạy máy chủ

Sau khi thiết lập dịch vụ mà mình muốn, hãy chuyển đến app-done rồi khởi động máy chủ.

Trong trình duyệt, hãy truy cập vào URL https của mẫu mà bạn đã lưu trữ.

  1. Bạn sẽ thấy ứng dụng video xuất hiện.
  2. Nhấp vào nút Truyền và chọn thiết bị Google Cast của bạn.
  3. Chọn một video, nhấp vào nút phát.
  4. Video sẽ bắt đầu phát trên thiết bị Google Cast của bạn.

Hình ảnh video đang phát trên thiết bị truyền

Nhấp vào nút tạm dừng trong phần tử video để tạm dừng video trên bộ thu. Nhấp vào nút phát trong thành phần video để tiếp tục phát lại video đó.

Nhấp vào nút Truyền để dừng truyền tới thiết bị Google Cast.

Trước khi chúng ta tiếp tục, hãy dừng máy chủ.

4. Chuẩn bị dự án bắt đầu

Hình ảnh video đang phát trên thiết bị truyền

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

  • một ứng dụng của người gửi chạy trên thiết bị di động hoặc máy tính xách tay
  • một ứng dụng receiver (trình thu nhận) chạy trên thiết bị Google Cast.

Bây giờ, 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 yêu thích của mình:

  1. Chọn thư mục biểu tượng thư mụcapp-start trong tệp mã mẫu mà bạn tải xuống.
  2. Chạy ứng dụng bằng máy chủ của bạn và khám phá giao diện người dùng.

Lưu ý: Khi thực hiện lớp học lập trình này, bạn sẽ cần lưu trữ lại mẫu trên máy chủ của mình, tuỳ thuộc vào dịch vụ.

Thiết kế ứng dụng

Ứng dụng tìm nạp danh sách video từ máy chủ web từ xa và cung cấp danh sách để người dùng duyệt qua. Người dùng có thể chọn một video để xem chi tiết hoặc phát video đó trên thiết bị di động.

Ứng dụng bao gồm một khung hiển thị chính, được xác định trong index.html và trình điều khiển chính là CastVideos.js.

index.html

Tệp html này khai báo gần như toàn bộ giao diện người dùng cho ứng dụng web.

Trong một số phần lượt xem, chúng ta có div#main_video, trong đó chứa phần tử video. Liên quan đến div video, chúng ta có div#media_control xác định tất cả các chế độ điều khiển cho phần tử video. Bên dưới là media_info, cho thấy thông tin chi tiết của video đang xem. Cuối cùng, div carousel hiển thị danh sách các video trong một div.

Tệp index.html cũng khởi động SDK Truyền và yêu cầu hàm CastVideos tải.

Hầu hết nội dung sẽ điền sẵn các phần tử này đều được xác định, chèn và kiểm soát trong CastVideos.js. Hãy cùng xem xét việc đó.

CastVideos.js

Tập lệnh này quản lý tất cả logic cho ứng dụng web Truyền video. Danh sách video và siêu dữ liệu liên quan được xác định trong CastVideos.js nằm trong một đối tượng có tên là mediaJSON.

Có một số phần chính chịu trách nhiệm quản lý và phát video cả trên thiết bị và từ xa. Nhìn chung, đây là một ứng dụng web khá đơn giản.

CastPlayer là lớp chính quản lý toàn bộ ứng dụng, thiết lập trình phát, chọn nội dung nghe nhìn và liên kết các sự kiện với PlayerHandler để phát nội dung nghe nhìn. CastPlayer.prototype.initializeCastPlayer là phương thức thiết lập tất cả chức năng Truyền. CastPlayer.prototype.switchPlayer chuyển trạng thái giữa trình phát cục bộ và người chơi từ xa. CastPlayer.prototype.setupLocalPlayerCastPlayer.prototype.setupRemotePlayer khởi chạy người chơi cục bộ và từ xa.

PlayerHandler là lớp chịu trách nhiệm quản lý việc phát nội dung nghe nhìn. Có một số phương pháp khác chịu trách nhiệm về chi tiết quản lý nội dung nghe nhìn và chế độ phát.

Câu hỏi thường gặp

5. Thêm nút Truyền

Hình ảnh về ứng dụng hỗ trợ Cast

Ứng dụng hỗ trợ Cast hiển thị nút Truyền trong phần tử video. Nhấp vào nút Truyền sẽ hiển thị danh sách Thiết bị truyền mà người dùng có thể chọn. Nếu người dùng đang phát nội dung cục bộ trên thiết bị truyền, việc chọn một Thiết bị truyền sẽ bắt đầu hoặc tiếp tục phát trên thiết bị Truyền đó. Bất cứ lúc nào trong phiên Truyền, người dùng có thể nhấp vào nút Truyền và dừng truyền ứng dụng tới Thiết bị truyền. Người dùng phải kết nối hoặc ngắt kết nối khỏi Thiết bị truyền khi đang ở bất kỳ màn hình nào của ứng dụng, như được mô tả trong Danh sách kiểm tra thiết kế của Google Cast.

Cấu hình

Dự án khởi đầu yêu cầu các phần phụ thuộc và chế độ thiết lập giống như đối với ứng dụng mẫu hoàn chỉnh, nhưng lần này lưu trữ nội dung của app-start.

Trong trình duyệt, hãy truy cập vào URL https của mẫu mà bạn đã lưu trữ.

Hãy nhớ rằng khi thực hiện thay đổi, bạn sẽ cần phải lưu trữ lại mẫu trên máy chủ của mình tuỳ thuộc vào dịch vụ.

Khởi chạy

Khung Cast có một đối tượng singleton toàn cầu là CastContext, giúp điều phối tất cả hoạt động của khung. Đối tượng này phải được khởi tạo sớm trong vòng đời của ứng dụng, thường được gọi qua một lệnh gọi lại được chỉ định cho window['__onGCastApiAvailable']. Lệnh này được gọi sau khi đã tải SDK Truyền và có thể sử dụng được. Trong trường hợp này, CastContext được gọi trong CastPlayer.prototype.initializeCastPlayer. Lệnh này được gọi từ lệnh gọi lại nêu trên.

Bạn phải cung cấp đối tượng JSON options khi khởi tạo CastContext. Lớp này chứa các tuỳ chọn ảnh hưởng đến hành vi của khung. Quan trọng nhất trong số này là ID ứng dụng nhận. ID này được dùng để lọc danh sách các thiết bị Truyền hiện có để chỉ hiển thị các thiết bị có thể chạy ứng dụng đã chỉ định và để khởi chạy ứng dụng nhận khi phiên Truyền bắt đầu.

Khi phát triển ứng dụng hỗ trợ Cast của riêng mình, bạn phải đăng ký làm nhà phát triển Cast và sau đó lấy ID ứng dụng cho ứng dụng của mình. Đối với lớp học lập trình này, chúng ta sẽ sử dụng mã ứng dụng mẫu.

Thêm mã sau vào index.html ở cuối phần body:

<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

Thêm mã sau vào index.html để khởi chạy ứng dụng CastVideos, cũng như để khởi chạy CastContext:

<script src="CastVideos.js"></script>
<script type="text/javascript">
var castPlayer = new CastPlayer();
window['__onGCastApiAvailable'] = function(isAvailable) {
  if (isAvailable) {
    castPlayer.initializeCastPlayer();
  }
};
</script>

Bây giờ, chúng ta cần thêm một phương thức mới trong CastVideos.js, tương ứng với phương thức mà chúng ta vừa gọi trong index.html. Hãy thêm một phương thức mới có tên là initializeCastPlayer. Phương thức này sẽ đặt các tuỳ chọn trên CastContext và khởi chạy RemotePlayerRemotePlayerControllers mới:

/**
 * This method sets up the CastContext, and a few other members
 * that are necessary to play and control videos on a Cast
 * device.
 */
CastPlayer.prototype.initializeCastPlayer = function() {

    var options = {};

    // Set the receiver application ID to your own (created in
    // the Google Cast Developer Console), or optionally
    // use the chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
    options.receiverApplicationId = 'C0868879';

    // Auto join policy can be one of the following three:
    // ORIGIN_SCOPED - Auto connect from same appId and page origin
    // TAB_AND_ORIGIN_SCOPED - Auto connect from same appId, page origin, and tab
    // PAGE_SCOPED - No auto connect
    options.autoJoinPolicy = chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED;

    cast.framework.CastContext.getInstance().setOptions(options);

    this.remotePlayer = new cast.framework.RemotePlayer();
    this.remotePlayerController = new cast.framework.RemotePlayerController(this.remotePlayer);
    this.remotePlayerController.addEventListener(
        cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED,
        this.switchPlayer.bind(this)
    );
};

Cuối cùng, chúng ta cần tạo các biến cho RemotePlayerRemotePlayerController:

var CastPlayer = function() {
  //...
  /* Cast player variables */
  /** @type {cast.framework.RemotePlayer} */
  this.remotePlayer = null;
  /** @type {cast.framework.RemotePlayerController} */
  this.remotePlayerController = null;
  //...
};

Nút truyền

Giờ đây, CastContext đã được khởi chạy, chúng ta cần thêm nút Truyền để cho phép người dùng chọn thiết bị Truyền. SDK Truyền cung cấp thành phần nút Truyền có tên là google-cast-launcher với mã nhận dạng là "castbutton". Bạn có thể thêm phần tử này vào thành phần video của ứng dụng đơn giản bằng cách thêm button vào phần media_control.

Phần tử nút sẽ có dạng như sau:

<google-cast-launcher id="castbutton"></google-cast-launcher>

Thêm mã sau vào index.html trong phần media_control:

<div id="media_control">
  <div id="play"></div>
  <div id="pause"></div>
  <div id="progress_bg"></div>
  <div id="progress"></div>
  <div id="progress_indicator"></div>
  <div id="fullscreen_expand"></div>
  <div id="fullscreen_collapse"></div>
  <google-cast-launcher id="castbutton"></google-cast-launcher>
  <div id="audio_bg"></div>
  <div id="audio_bg_track"></div>
  <div id="audio_indicator"></div>
  <div id="audio_bg_level"></div>
  <div id="audio_on"></div>
  <div id="audio_off"></div>
  <div id="duration">00:00:00</div>
</div>

Bây giờ, hãy làm mới trang trong trình duyệt Chrome. Bạn sẽ nhìn thấy nút Truyền trong phần tử video và khi bạn nhấp vào nút đó, nút này sẽ liệt kê các thiết bị Truyền trên mạng cục bộ của bạn. Tính năng phát hiện thiết bị được trình duyệt Chrome quản lý tự động. Chọn Thiết bị truyền của bạn và ứng dụng bộ nhận mẫu sẽ tải trên Thiết bị truyền.

Chúng tôi chưa kết nối bất kỳ tính năng hỗ trợ nào cho tính năng phát nội dung nghe nhìn nên bạn chưa thể phát video trên Thiết bị truyền. Nhấp vào nút Truyền để dừng truyền.

6. Đang truyền nội dung video

Hình ảnh ứng dụng hỗ trợ Cast với trình đơn chọn Thiết bị truyền

Chúng tôi sẽ mở rộng ứng dụng mẫu để có thể phát video từ xa trên thiết bị truyền. Để làm được điều đó, chúng ta cần theo dõi các sự kiện khác nhau do khung Truyền tạo.

Đang truyền nội dung nghe nhìn

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

  1. Tạo một đối tượng MediaInfo JSON từ SDK Truyền để mô hình hoá một mục nội dung đa phương tiện.
  2. Người dùng kết nối với Thiết bị truyền để chạy ứng dụng nhận tín hiệu.
  3. Tải đối tượng MediaInfo vào trình thu nhận và phát nội dung.
  4. Theo dõi trạng thái của nội dung nghe nhìn.
  5. Gửi lệnh phát đến người nhận dựa trên tương tác của người dùng.

Bước 1 tương tự như ánh xạ một đối tượng với đối tượng khác; MediaInfo là nội dung mà SDK truyền hiểu được và mediaJSON là gói ứng dụng của chúng ta dành cho một mục nội dung đa phương tiện; chúng ta có thể dễ dàng liên kết mediaJSON với MediaInfo. Chúng ta đã thực hiện Bước 2 ở phần trước. Bước 3 là dễ dàng thực hiện với SDK Truyền.

Ứng dụng mẫu CastPlayer đã phân biệt giữa chế độ phát cục bộ và từ xa trong phương thức switchPlayer:

if (cast && cast.framework) {
  if (this.remotePlayer.isConnected) {
    //...

Trong lớp học lập trình này, bạn không cần phải hiểu chính xác cách hoạt động của tất cả logic của trình phát mẫu. Tuy nhiên, điều quan trọng cần hiểu là trình phát nội dung đa phương tiện của ứng dụng sẽ phải được sửa đổi để nhận biết được cả chế độ phát cục bộ lẫn từ xa.

Hiện tại, trình phát cục bộ luôn ở trạng thái phát cục bộ vì chưa biết gì về trạng thái Truyền. Chúng ta cần cập nhật giao diện người dùng dựa trên quá trình chuyển đổi trạng thái xảy ra trong khung Truyền. Ví dụ: nếu bắt đầu truyền, chúng ta cần dừng quá trình phát trên thiết bị và tắt một số nút điều khiển. Tương tự, nếu ngừng truyền khi đang ở bộ điều khiển chế độ xem này, chúng ta cần chuyển sang chế độ phát cục bộ. Để xử lý vấn đề đó, chúng ta cần nghe các sự kiện khác nhau do khung Truyền tạo.

Quản lý phiên truyền

Đối với khung Truyền, phiên Truyền sẽ kết hợp các bước kết nối với thiết bị, khởi chạy (hoặc tham gia một phiên hiện có), kết nối với ứng dụng nhận và khởi chạy kênh điều khiển nội dung nghe nhìn nếu thích hợp. Kênh điều khiển nội dung nghe nhìn là cách khung Truyền gửi và nhận các thông báo liên quan đến việc phát nội dung nghe nhìn từ bộ nhận.

Phiên Truyền sẽ tự động bắt đầu khi người dùng chọn một thiết bị trong nút Truyền và sẽ tự động dừng khi người dùng ngắt kết nối. Kết nối lại với một phiên nhận do sự cố kết nối mạng cũng được khung Truyền tự động xử lý.

Phiên truyền được quản lý bằng CastSession. Bạn có thể truy cập vào ứng dụng này thông qua cast.framework.CastContext.getInstance().getCurrentSession(). Bạn có thể dùng các lệnh gọi lại EventListener để theo dõi các sự kiện trong phiên, chẳng hạn như tạo, tạm ngưng, tiếp tục và chấm dứt.

Trong ứng dụng hiện tại, tất cả phiên và trạng thái quản lý trạng thái đều được xử lý thay cho chúng ta trong phương thức setupRemotePlayer. Hãy bắt đầu định cấu hình tính năng đó trong ứng dụng bằng cách thêm mã sau vào CastVideos.js:

/**
 * Set the PlayerHandler target to use the remote player
 */
CastPlayer.prototype.setupRemotePlayer = function () {
    var castSession = cast.framework.CastContext.getInstance().getCurrentSession();

    this.playerHandler.setTarget(playerTarget);

    // Setup remote player volume right on setup
    // The remote player may have had a volume set from previous playback
    if (this.remotePlayer.isMuted) {
        this.playerHandler.mute();
    }
    var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
    var p = document.getElementById('audio_bg_level');
    p.style.height = currentVolume + 'px';
    p.style.marginTop = -currentVolume + 'px';

    this.hideFullscreenButton();

    this.playerHandler.play();
};

Chúng ta vẫn cần liên kết tất cả sự kiện từ lệnh gọi lại và xử lý tất cả sự kiện xuất hiện. Đây là một việc khá đơn giản, vì vậy, hãy thực hiện ngay bây giờ:

/**
 * Set the PlayerHandler target to use the remote player
 */
CastPlayer.prototype.setupRemotePlayer = function () {
    var castSession = cast.framework.CastContext.getInstance().getCurrentSession();

    // Add event listeners for player changes which may occur outside sender app
    this.remotePlayerController.addEventListener(
        cast.framework.RemotePlayerEventType.IS_PAUSED_CHANGED,
        function() {
            if (this.remotePlayer.isPaused) {
                this.playerHandler.pause();
            } else {
                this.playerHandler.play();
            }
        }.bind(this)
    );

    this.remotePlayerController.addEventListener(
        cast.framework.RemotePlayerEventType.IS_MUTED_CHANGED,
        function() {
            if (this.remotePlayer.isMuted) {
                this.playerHandler.mute();
            } else {
                this.playerHandler.unMute();
            }
        }.bind(this)
    );

    this.remotePlayerController.addEventListener(
        cast.framework.RemotePlayerEventType.VOLUME_LEVEL_CHANGED,
        function() {
            var newVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
            var p = document.getElementById('audio_bg_level');
            p.style.height = newVolume + 'px';
            p.style.marginTop = -newVolume + 'px';
        }.bind(this)
    );

    // This object will implement PlayerHandler callbacks with
    // remotePlayerController, and makes necessary UI updates specific
    // to remote playback
    var playerTarget = {};

    playerTarget.play = function () {
        if (this.remotePlayer.isPaused) {
            this.remotePlayerController.playOrPause();
        }

        var vi = document.getElementById('video_image');
        vi.style.display = 'block';
        var localPlayer = document.getElementById('video_element');
        localPlayer.style.display = 'none';
    }.bind(this);

    playerTarget.pause = function () {
        if (!this.remotePlayer.isPaused) {
            this.remotePlayerController.playOrPause();
        }
    }.bind(this);

    playerTarget.stop = function () {
         this.remotePlayerController.stop();
    }.bind(this);

    playerTarget.getCurrentMediaTime = function() {
        return this.remotePlayer.currentTime;
    }.bind(this);

    playerTarget.getMediaDuration = function() {
        return this.remotePlayer.duration;
    }.bind(this);

    playerTarget.updateDisplayMessage = function () {
        document.getElementById('playerstate').style.display = 'block';
        document.getElementById('playerstatebg').style.display = 'block';
        document.getElementById('video_image_overlay').style.display = 'block';
        document.getElementById('playerstate').innerHTML =
            this.mediaContents[ this.currentMediaIndex]['title'] + ' ' +
            this.playerState + ' on ' + castSession.getCastDevice().friendlyName;
    }.bind(this);

    playerTarget.setVolume = function (volumeSliderPosition) {
        // Add resistance to avoid loud volume
        var currentVolume = this.remotePlayer.volumeLevel;
        var p = document.getElementById('audio_bg_level');
        if (volumeSliderPosition < FULL_VOLUME_HEIGHT) {
            var vScale =  this.currentVolume * FULL_VOLUME_HEIGHT;
            if (volumeSliderPosition > vScale) {
                volumeSliderPosition = vScale + (pos - vScale) / 2;
            }
            p.style.height = volumeSliderPosition + 'px';
            p.style.marginTop = -volumeSliderPosition + 'px';
            currentVolume = volumeSliderPosition / FULL_VOLUME_HEIGHT;
        } else {
            currentVolume = 1;
        }
        this.remotePlayer.volumeLevel = currentVolume;
        this.remotePlayerController.setVolumeLevel();
    }.bind(this);

    playerTarget.mute = function () {
        if (!this.remotePlayer.isMuted) {
            this.remotePlayerController.muteOrUnmute();
        }
    }.bind(this);

    playerTarget.unMute = function () {
        if (this.remotePlayer.isMuted) {
            this.remotePlayerController.muteOrUnmute();
        }
    }.bind(this);

    playerTarget.isMuted = function() {
        return this.remotePlayer.isMuted;
    }.bind(this);

    playerTarget.seekTo = function (time) {
        this.remotePlayer.currentTime = time;
        this.remotePlayerController.seek();
    }.bind(this);

    this.playerHandler.setTarget(playerTarget);

    // Setup remote player volume right on setup
    // The remote player may have had a volume set from previous playback
    if (this.remotePlayer.isMuted) {
        this.playerHandler.mute();
    }
    var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
    var p = document.getElementById('audio_bg_level');
    p.style.height = currentVolume + 'px';
    p.style.marginTop = -currentVolume + 'px';

    this.hideFullscreenButton();

    this.playerHandler.play();
};

Đang tải nội dung nghe nhìn

Trong Cast SDK, RemotePlayerRemotePlayerController cung cấp một bộ API tiện lợi để quản lý việc phát nội dung nghe nhìn từ xa trên receiver. Đối với CastSession có hỗ trợ phát nội dung nghe nhìn, SDK sẽ tự động tạo các bản sao của RemotePlayerRemotePlayerController. Bạn có thể truy cập vào các thực thể này bằng cách tạo các thực thể của cast.framework.RemotePlayercast.framework.RemotePlayerController tương ứng, như minh hoạ trước đó trong lớp học lập trình.

Tiếp theo, chúng ta cần tải video hiện được chọn trên bộ thu bằng cách tạo đối tượng MediaInfo để SDK xử lý và truyền yêu cầu. Thêm mã sau vào setupRemotePlayer để thực hiện việc này:

/**
 * Set the PlayerHandler target to use the remote player
 */
CastPlayer.prototype.setupRemotePlayer = function () {
    //...

    playerTarget.load = function (mediaIndex) {
        console.log('Loading...' + this.mediaContents[mediaIndex]['title']);
        var mediaInfo = new chrome.cast.media.MediaInfo(
            this.mediaContents[mediaIndex]['sources'][0], 'video/mp4');

        mediaInfo.metadata = new chrome.cast.media.GenericMediaMetadata();
        mediaInfo.metadata.metadataType = chrome.cast.media.MetadataType.GENERIC;
        mediaInfo.metadata.title = this.mediaContents[mediaIndex]['title'];
        mediaInfo.metadata.images = [
            {'url': MEDIA_SOURCE_ROOT + this.mediaContents[mediaIndex]['thumb']}];

        var request = new chrome.cast.media.LoadRequest(mediaInfo);
        castSession.loadMedia(request).then(
            this.playerHandler.loaded.bind(this.playerHandler),
            function (errorCode) {
                this.playerState = PLAYER_STATE.ERROR;
                console.log('Remote media load error: ' +
                    CastPlayer.getErrorMessage(errorCode));
            }.bind(this));
    }.bind(this);

    //...
};

Giờ hãy thêm phương thức để chuyển đổi giữa chế độ phát cục bộ và từ xa:

/**
 * This is a method for switching between the local and remote
 * players. If the local player is selected, setupLocalPlayer()
 * is run. If there is a cast device connected we run
 * setupRemotePlayer().
 */
CastPlayer.prototype.switchPlayer = function() {
    this.stopProgressTimer();
    this.resetVolumeSlider();
    this.playerHandler.stop();
    this.playerState = PLAYER_STATE.IDLE;
    if (cast && cast.framework) {
        if (this.remotePlayer.isConnected) {
            this.setupRemotePlayer();
            return;
        }
    }
    this.setupLocalPlayer();
};

Cuối cùng, hãy thêm một phương thức để xử lý mọi thông báo lỗi Truyền:

/**
 * Makes human-readable message from chrome.cast.Error
 * @param {chrome.cast.Error} error
 * @return {string} error message
 */
CastPlayer.getErrorMessage = function(error) {
  switch (error.code) {
    case chrome.cast.ErrorCode.API_NOT_INITIALIZED:
      return 'The API is not initialized.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.CANCEL:
      return 'The operation was canceled by the user' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.CHANNEL_ERROR:
      return 'A channel to the receiver is not available.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.EXTENSION_MISSING:
      return 'The Cast extension is not available.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.INVALID_PARAMETER:
      return 'The parameters to the operation were not valid.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.RECEIVER_UNAVAILABLE:
      return 'No receiver was compatible with the session request.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.SESSION_ERROR:
      return 'A session could not be created, or a session was invalid.' +
        (error.description ? ' :' + error.description : '');
    case chrome.cast.ErrorCode.TIMEOUT:
      return 'The operation timed out.' +
        (error.description ? ' :' + error.description : '');
  }
};

Bây giờ, hãy chạy ứng dụng. Kết nối với Thiết bị truyền của bạn và bắt đầu phát video. Bạn sẽ thấy video đang phát trên đầu thu.

7. Thêm tính năng hỗ trợ Cast Connect

Thư viện Cast Connect cho phép các ứng dụng gửi hiện có giao tiếp với các ứng dụng Android TV qua giao thức Cast. Cast Connect được xây dựng dựa trên cơ sở hạ tầng Cast, trong đó ứng dụng Android TV của bạn hoạt động như một bộ thu.

Phần phụ thuộc

  • Trình duyệt Chrome phiên bản M87 trở lên

Thiết lập tính năng tương thích với bộ thu Android

Để chạy ứng dụng Android TV, còn được gọi là Android receiver, chúng ta cần đặt cờ androidReceiverCompatible thành true trong đối tượng CastOptions.

Thêm mã sau vào CastVideos.js của bạn trong hàm initializeCastPlayer:

var options = {};
...
options.androidReceiverCompatible = true;

cast.framework.CastContext.getInstance().setOptions(options);

Đặt thông tin xác thực chạy

Ở phía người gửi, bạn có thể chỉ định CredentialsData để đại diện cho người tham gia phiên. credentials là một chuỗi mà người dùng có thể xác định, miễn là ứng dụng ATV của bạn có thể hiểu được chuỗi đó. CredentialsData chỉ được chuyển đến ứng dụng Android TV của bạn trong thời gian chạy hoặc tham gia. Nếu bạn thiết lập lại thiết bị trong khi kết nối, thì thiết bị sẽ không được chuyển đến ứng dụng Android TV.

Để đặt Thông tin đăng nhập khi chạy, bạn cần xác định CredentialsData bất cứ lúc nào sau khi đặt các tuỳ chọn khởi chạy.

Thêm mã sau vào lớp CastVideos.js trong hàm initializeCastPlayer:

cast.framework.CastContext.getInstance().setOptions(options);
...
let credentialsData = new chrome.cast.CredentialsData("{\"userId\": \"abc\"}");
cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData);
...

Đặt thông tin xác thực khi có yêu cầu tải

Trong trường hợp ứng dụng Trình thu phát web và ứng dụng Android TV xử lý credentials theo cách khác nhau, có thể bạn cần phải xác định thông tin đăng nhập riêng cho mỗi ứng dụng. Để xử lý vấn đề này, hãy thêm mã sau vào CastVideos.js của bạn dưới playerTarget.load trong hàm setupRemotePlayer:

...
var request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
request.atvCredentials = 'atv-user-credentials';
...

Tuỳ thuộc vào ứng dụng nhận mà người gửi đang truyền tới, SDK giờ đây sẽ tự động xử lý thông tin xác thực cần sử dụng cho phiên hiện tại.

Kiểm thử Cast Connect

Các bước để cài đặt APK Android TV trên Chromecast có Google TV:

  1. Tìm địa chỉ IP của thiết bị Android TV. Thông thường, công cụ này có trong phần Cài đặt > Mạng và Internet > (Tên mạng mà thiết bị của bạn đang kết nối). Ở phía bên phải, ứng dụng sẽ hiển thị thông tin chi tiết và IP của thiết bị trên mạng.
  2. Sử dụng địa chỉ IP cho thiết bị của bạn để kết nối với thiết bị đó qua ADB bằng thiết bị đầu cuối:
$ adb connect <device_ip_address>:5555
  1. Từ cửa sổ dòng lệnh, hãy chuyển đến thư mục cấp cao nhất của các mẫu trong lớp học lập trình mà bạn đã tải xuống ở đầu lớp học lập trình này. Ví dụ:
$ cd Desktop/chrome_codelab_src
  1. Cài đặt tệp .apk trong thư mục này vào Android TV bằng cách chạy:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. Giờ đây, bạn có thể thấy một ứng dụng có tên là Truyền video trong trình đơn Ứng dụng của bạn trên thiết bị Android TV.
  2. Chạy mã người gửi web đã cập nhật và thiết lập phiên truyền với thiết bị Android TV bằng cách sử dụng biểu tượng truyền hoặc chọn Cast.. từ trình đơn thả xuống của trình duyệt Chrome. Thao tác này sẽ khởi chạy ứng dụng Android TV trên Bộ thu Android của bạn và cho phép bạn điều khiển quá trình phát bằng điều khiển từ xa cho Android TV.

8. Xin chúc mừng

Giờ đây, bạn đã biết cách bật ứng dụng video bằng cách sử dụng tiện ích SDK Truyền trên ứng dụng web Chrome.

Để biết thêm chi tiết, hãy xem hướng dẫn dành cho nhà phát triển về Trình gửi web.