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 thiết bị có 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 sang TV. Sau đó, người dùng có thể 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ế Google Cast.

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

Chúng ta sẽ xây dự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, chẳng hạn như Lưu trữ Firebase hoặc ngrok.
  • Thiết bị Google Cast như Chromecast hoặc Android TV được định cấu hình để có quyền truy cập Internet.
  • TV hoặc màn hình có đầu vào HDMI.
  • Bạn cần có Chromecast với Google TV để kiểm thử tính năng tích hợp Cast Connect, nhưng không bắt buộc phải có thiết bị này cho phần còn lại của Lớp học lập trình. Nếu không có, bạn có thể bỏ qua bước Thêm dịch vụ hỗ trợ Cast Connect ở cuối hướng dẫn này.

Trải nghiệm

  • Bạn cần có kiến thức phát triển web trước đó.
  • Bạn cũng cần có kiến thức trước đây về việc xem TV :)

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

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

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

Tân binh 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?

Tân binh 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 xem ứng dụng mẫu hoàn chỉnh trông như thế nào. Ứng dụng này 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, bạn cần lưu trữ trang hoàn chỉnh.

Nếu không có máy chủ để sử dụng, bạn có thể sử dụ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 rồi chọn thiết bị Google Cast.
  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.

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

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 phần tử video để tiếp tục phát lại video.

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

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

4. Chuẩn bị dự án khởi động

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

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ữ 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,
  • ứng dụng receiver (trình 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 động bằng trình soạn thảo văn 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 xuống mã mẫu.
  2. Chạy ứng dụng bằng máy chủ và khám phá giao diện người dùng.

Xin lưu ý rằng khi làm việc trong 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ột máy chủ web từ xa và cung cấp danh sách để người dùng duyệt xem. Người dùng có thể chọn một video để xem thông tin chi tiết hoặc phát video trên thiết bị di động.

Ứng dụng bao gồm một thành phần hiển thị chính, được xác định trong index.html và trình điều khiển chính, 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.

Có một vài phần của thành phần hiển thị, chúng ta có div#main_video chứa phần tử video. Liên quan đến div video, chúng ta có div#media_control, giúp 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, hiển thị thông tin chi tiết về video đang xem. Cuối cùng, div carousel hiển thị danh sách video trong một div.

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

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

CastVideos.js

Tập lệnh này quản lý tất cả logic cho ứng dụng web Cast Videos. 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 mediaJSON.

Có một vài phần chính chịu trách nhiệm quản lý và phát video cả cục 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 trình phát 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 thức khác chịu trách nhiệm về thông tin chi tiết về việc quản lý nội dung nghe nhìn và phát.

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

5. Thêm nút Truyền

Hình ảnh một ứng dụng hỗ trợ tính năng Truyền

Ứng dụng hỗ trợ tính năng Truyền sẽ 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ị gửi, thì 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à ngừng truyền ứng dụng của bạn đến thiết bị Truyền. Người dùng phải có thể kết nối hoặc ngắt kết nối với thiết bị Cast trong bất kỳ màn hình nào của ứng dụng, như mô tả trong Danh sách kiểm tra thiết kế 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, có chức năng điều phối tất cả hoạt động của khung. Bạn phải khởi tạo đối tượng này sớm trong vòng đời của ứng dụng, thường được gọi từ lệnh gọi lại được chỉ định cho window['__onGCastApiAvailable']. Lệnh gọi lại này được gọi sau khi SDK truyền đã được tải và có thể sử dụng. 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à mã nhận dạng ứng dụng nhận, dùng để lọc danh sách các thiết bị Cast có sẵn để chỉ hiển thị những thiết bị có thể chạy ứng dụng đã chỉ định và khởi chạy ứng dụng nhận khi bắt đầu một phiên Cast.

Khi phát triển ứng dụng hỗ trợ tính năng Truyền của riêng mình, bạn phải đăng ký làm nhà phát triển Cast rồi lấy mã ứng dụng cho ứng dụng của mình. Trong 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 phát cung cấp một thành phần nút Truyền phát có tên là google-cast-launcher với mã nhận dạng là "castbutton"". Bạn có thể thêm thành phần này vào phần tử video của ứng dụng 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ẽ thấy một nút Truyền trong phần tử video. Khi nhấp vào nút này, bạn sẽ thấy danh sách các thiết bị Truyền trên mạng cục bộ. Trình duyệt Chrome sẽ tự động quản lý tính năng khám phá thiết bị. Chọn thiết bị Truyền và ứng dụng trình 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 để phát nội dung nghe nhìn, vì vậy, 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. Truyền nội dung video

Hình ảnh ứng dụng hỗ trợ Cast có trình đơn lựa chọn thiết bị Cast

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 nhiều sự kiện do khung Cast tạo ra.

Truyền nội dung đa phương tiệ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 đối tượng JSON MediaInfo từ SDK Cast mô hình hoá một mục nội dung nghe nhìn.
  2. Người dùng kết nối với thiết bị Cast để chạy ứng dụng receiver.
  3. Tải đối tượng MediaInfo vào trình thu và phát nội dung.
  4. Theo dõi trạng thái nội dung nghe nhìn.
  5. Gửi lệnh phát đến bộ thu dựa trên hoạt động tương tác của người dùng.

Bước 1 là liên kết một đối tượng với một đối tượng khác; MediaInfo là nội dung mà SDK truyền phát hiểu được và mediaJSON là nội dung đóng gói của ứng dụng cho một mục nội dung nghe nhì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 người chơi mẫu. Tuy nhiên, điều quan trọng là bạn phải hiểu rằng 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ả chế độ phát cục bộ và 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ề các 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 các quá trình chuyển đổi trạng thái diễn ra trong khung Cast. Ví dụ: nếu bắt đầu truyền, chúng ta cần dừng chế độ phát cục bộ và tắt một số chế độ điều khiển. Tương tự, nếu dừng truyền khi đang ở trong trình điều khiển thành phần hiển thị 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 theo dõi nhiều sự kiện do khung Cast tạo ra.

Quản lý phiên truyền

Đối với khung Truyền, một phiên Truyền 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 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 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. Khung Cast cũng tự động xử lý việc kết nối lại với phiên của trình nhận do các vấn đề về mạng.

Các phiên truyền được quản lý bởi CastSession. Bạn có thể truy cập vào phiên truyền 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ả các phiên và hoạt động quản lý trạng thái đều được xử lý cho chúng ta trong phương thức setupRemotePlayer. Hãy bắt đầu định cấu hình 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 cùng thực hiện ngay:

/**
 * 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 SDK truyền, RemotePlayerRemotePlayerController cung cấp một tập hợp các API thuận tiện để quản lý việc phát nội dung đa phương tiện từ xa trên thiết bị nhận. Đối với CastSession hỗ trợ phát nội dung đa phương tiện, SDK sẽ tự động tạo các thực thể của RemotePlayerRemotePlayerController. Bạn có thể truy cập vào các lớp này bằng cách tạo các thực thể của cast.framework.RemotePlayercast.framework.RemotePlayerController tương ứng, như đã trình bày trước đó trong lớp học lập trình.

Tiếp theo, chúng ta cần tải video đang được chọn trên bộ thu bằng cách tạo đối tượng MediaInfo để SDK xử lý và truyền vào 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);

    //...
};

Bây giờ, hãy thêm một 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 Cast:

/**
 * 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ị Cast và bắt đầu phát video. Bạn sẽ thấy video phát trên thiết bị nhận.

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 thông 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 đóng vai trò là trình thu.

Phần phụ thuộc

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

Thiết lập Android Receiver Compatible

Để chạy ứng dụng Android TV (còn 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 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 để biểu thị người đang tham gia phiên. credentials là một chuỗi có thể do người dùng 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 đặt lại giá trị này trong khi đang kết nối, thì giá trị này sẽ không được truyền đến ứng dụng Android TV.

Để đặt Thông tin xác thực chạy, CredentialsData cần được xác định bất cứ lúc nào sau khi đặt 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 trên yêu cầu tải

Trong trường hợp ứng dụng Web Receiver và ứng dụng Android TV xử lý credentials theo cách khác nhau, bạn có thể cần xác định thông tin xác thực riêng cho từng ứng dụng. Để xử lý vấn đề đó, hãy thêm mã sau vào CastVideos.js trong 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 dụng gửi đang truyền đến, SDK hiện 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 tệp 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, bạn có thể tìm thấy phần này 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). Ở bên phải, bạn sẽ thấy thông tin chi tiết và địa chỉ 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à Cast Videos (Truyền video) trong trình đơn Your Apps (Ứ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 tính năng Truyền cho một ứng dụng video bằng tiện ích SDK Truyền trên ứng dụng web Chrome.

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