Включение трансляции в веб-приложении

1. Обзор

логотип Google Cast

В этом практическом занятии вы узнаете, как модифицировать существующее веб-приложение для видео, чтобы оно транслировало контент на устройство с поддержкой Google Cast .

Что такое Google Cast?

Google Cast позволяет пользователям транслировать контент с мобильного устройства на телевизор. Затем пользователи могут использовать свое мобильное устройство в качестве пульта дистанционного управления для воспроизведения мультимедиа на телевизоре.

SDK Google Cast позволяет расширить функциональность вашего приложения для управления телевизором или звуковой системой. SDK Cast позволяет добавлять необходимые компоненты пользовательского интерфейса в соответствии с контрольным списком дизайна Google Cast .

Контрольный список по дизайну Google Cast предназначен для того, чтобы сделать взаимодействие с Cast простым и предсказуемым на всех поддерживаемых платформах.

Что мы будем строить?

После завершения этого практического занятия у вас будет веб-приложение Chrome для воспроизведения видео, которое сможет транслировать видео на устройство Google Cast.

Что вы узнаете

  • Как добавить SDK Google Cast в пример видеоприложения.
  • Как добавить кнопку Cast для выбора устройства Google Cast.
  • Как подключиться к устройству Cast и запустить медиаплеер.
  • Как организовать кастинг видео.
  • Как интегрировать Cast Connect

Что вам понадобится

  • Последняя версия браузера Google Chrome .
  • HTTPS-хостинг, например, Firebase Hosting или ngrok .
  • Устройство Google Cast, такое как Chromecast или Android TV, с подключением к интернету.
  • Телевизор или монитор с HDMI-входом.
  • Для тестирования интеграции Cast Connect требуется Chromecast с Google TV, но для остальных заданий Codelab он необязателен. Если у вас его нет, можете пропустить шаг добавления поддержки Cast Connect в конце этого руководства.

Опыт

  • Вам потребуются предварительные знания в области веб-разработки.
  • Вам также понадобятся предварительные знания о просмотре телевизора :)

Как вы будете использовать этот учебный материал?

Прочитайте только от начала до конца. Прочитайте текст и выполните упражнения.

Как бы вы оценили свой опыт в разработке веб-приложений?

Новичок Средний Профессионал

Как бы вы оценили свой опыт просмотра телевизора?

Новичок Средний Профессионал

2. Получите пример кода.

Вы можете загрузить весь примерный код на свой компьютер...

и распакуйте загруженный zip-файл.

3. Запустите демонстрационное приложение.

Логотип Google Chrome

Для начала давайте посмотрим, как выглядит готовый пример приложения. Это простой видеоплеер. Пользователь может выбрать видео из списка, а затем воспроизвести его локально на устройстве или транслировать на устройство Google Cast.

Для использования готового продукта необходимо, чтобы он был размещен на хостинге.

Если у вас нет доступного сервера, вы можете использовать Firebase Hosting или ngrok .

Запустите сервер

После того, как вы настроите выбранный вами сервис, перейдите в app-done и запустите свой сервер.

В браузере перейдите по адресу https, указанному на размещенном вами образце.

  1. Вы должны увидеть, как появится видеоприложение.
  2. Нажмите кнопку «Трансляция» и выберите ваше устройство Google Cast.
  3. Выберите видео и нажмите кнопку воспроизведения.
  4. Видео начнет воспроизводиться на вашем устройстве Google Cast.

Изображение видео, воспроизводимого на устройстве Cast.

Нажмите кнопку паузы в видеоэлементе, чтобы приостановить воспроизведение видео на приемнике. Нажмите кнопку воспроизведения в видеоэлементе, чтобы возобновить воспроизведение видео.

Нажмите кнопку «Трансляция», чтобы остановить трансляцию на устройство Google Cast.

Прежде чем продолжить, остановите сервер.

4. Подготовьте стартовый проект.

Изображение видео, воспроизводимого на устройстве Cast.

Нам необходимо добавить поддержку Google Cast в загруженное вами стартовое приложение. Вот некоторые термины, связанные с Google Cast, которые мы будем использовать в этом практическом занятии:

  • Приложение отправителя работает на мобильном устройстве или ноутбуке.
  • Приложение- приемник работает на устройстве Google Cast.

Теперь вы готовы продолжить работу над стартовым проектом, используя свой любимый текстовый редактор:

  1. Выберите значок папки Каталог app-start из загруженного вами примера кода.
  2. Запустите приложение, используя свой сервер, и изучите пользовательский интерфейс.

Обратите внимание, что в процессе выполнения этого практического задания вам потребуется перенести пример на свой сервер в зависимости от используемого сервиса.

дизайн приложения

Приложение получает список видеороликов с удаленного веб-сервера и предоставляет пользователю возможность просмотреть его. Пользователи могут выбрать видео, чтобы увидеть подробную информацию, или воспроизвести видео локально на мобильном устройстве.

Приложение состоит из одного основного представления, определенного в index.html , и основного контроллера, CastVideos.js.

index.html

В этом HTML-файле описан практически весь пользовательский интерфейс веб-приложения.

Здесь несколько разделов, содержащих видеоэлементы. В первую очередь, есть div#main_video , который включает видеоэлемент. К нему относится div#media_control , определяющий все элементы управления для видеоэлемента. Ниже находится media_info , отображающий подробную информацию о видео. Наконец, div- carousel отображает список видео в отдельном div.

Файл index.html также инициализирует SDK Cast и указывает функции CastVideos на необходимость загрузки.

Большая часть контента, который будет заполнять эти элементы, определяется, внедряется и управляется в CastVideos.js . Давайте рассмотрим это подробнее.

CastVideos.js

Этот скрипт управляет всей логикой веб-приложения Cast Videos. Список видеороликов и связанные с ними метаданные, определенные в CastVideos.js , содержатся в объекте с именем mediaJSON .

В состав приложения входят несколько основных разделов, которые совместно отвечают за управление и воспроизведение видео как локально, так и удаленно. В целом, это довольно простое веб-приложение.

CastPlayer — это основной класс, который управляет всем приложением, настраивая плеер, выбирая медиафайлы и привязывая события к PlayerHandler для воспроизведения медиафайлов. CastPlayer.prototype.initializeCastPlayer настраивает всю функциональность CastPlayer. Метод CastPlayer.prototype.switchPlayer переключает состояние между локальным и удаленным плеерами. CastPlayer.prototype.setupLocalPlayer и CastPlayer.prototype.setupRemotePlayer инициализируют локальный и удаленный плееры.

Класс PlayerHandler отвечает за управление воспроизведением мультимедиа. Существует ряд других методов, отвечающих за детали управления воспроизведением мультимедиа.

Часто задаваемые вопросы

5. Добавление кнопки трансляции.

Изображение приложения с поддержкой Cast

В приложении с поддержкой Cast кнопка Cast отображается в видеоэлементе. Нажатие на кнопку Cast отображает список устройств Cast, которые пользователь может выбрать. Если пользователь воспроизводил контент локально на устройстве-отправителе, выбор устройства Cast запускает или возобновляет воспроизведение на этом устройстве Cast. В любой момент во время сеанса Cast пользователь может нажать на кнопку Cast и остановить трансляцию вашего приложения на устройство Cast. Пользователь должен иметь возможность подключаться к устройству Cast или отключаться от него на любом экране вашего приложения, как описано в контрольном списке Google Cast Design Checklist .

Конфигурация

Для запуска проекта требуются те же зависимости и настройка, что и для готового демонстрационного приложения, но на этот раз для размещения содержимого app-start .

В браузере перейдите по адресу https , указанному на размещенном вами образце.

Помните, что по мере внесения изменений вам потребуется разместить образец на своем сервере в зависимости от используемого сервиса.

Инициализация

Фреймворк Cast имеет глобальный объект-синглтон, CastContext , который координирует все действия фреймворка. Этот объект должен быть инициализирован на раннем этапе жизненного цикла приложения, обычно это вызывается из функции обратного вызова, назначенной window['__onGCastApiAvailable'] , которая вызывается после загрузки SDK Cast и его доступности для использования. В данном случае CastContext вызывается в CastPlayer.prototype.initializeCastPlayer , которая, в свою очередь, вызывается из вышеупомянутой функции обратного вызова.

При инициализации CastContext необходимо предоставить JSON-объект options . Этот класс содержит параметры, влияющие на поведение фреймворка. Наиболее важным из них является идентификатор приложения-приемника, который используется для фильтрации списка доступных устройств Cast, чтобы отображались только устройства, способные запускать указанное приложение, и для запуска приложения-приемника при запуске сессии Cast.

При разработке собственного приложения с поддержкой Cast вам необходимо зарегистрироваться в качестве разработчика Cast, а затем получить идентификатор приложения. В этом практическом занятии мы будем использовать пример идентификатора приложения.

Добавьте следующий код в файл index.html в самом конце раздела body :

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

Добавьте следующий код в index.html для инициализации приложения CastVideos , а также для инициализации CastContext :

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

Теперь нам нужно добавить новый метод в CastVideos.js , который соответствует методу, который мы только что вызвали в index.html . Давайте добавим новый метод с именем initializeCastPlayer , который устанавливает параметры для CastContext и инициализирует новые RemotePlayer и RemotePlayerControllers :

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

Наконец, нам нужно создать переменные для RemotePlayer и RemotePlayerController :

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

кнопка трансляции

Теперь, когда CastContext инициализирован, нам нужно добавить кнопку Cast, чтобы пользователь мог выбрать устройство Cast. SDK Cast предоставляет компонент кнопки Cast под названием google-cast-launcher с идентификатором " castbutton" . Его можно добавить к видеоэлементу приложения, просто добавив button в раздел media_control .

Вот как будет выглядеть элемент кнопки:

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

Добавьте следующий код в index.html в раздел 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>

Теперь обновите страницу в браузере Chrome. Вы должны увидеть кнопку Cast в элементе видео, и при нажатии на нее отобразится список устройств Cast в вашей локальной сети. Обнаружение устройств осуществляется автоматически браузером Chrome. Выберите ваше устройство Cast, и на нем загрузится демонстрационное приложение-приемник.

Мы пока не добавили поддержку воспроизведения мультимедиа, поэтому вы не сможете воспроизводить видео на устройстве Cast. Нажмите кнопку Cast, чтобы остановить трансляцию.

6. Подбор видеоконтента

Изображение приложения с поддержкой Cast и меню выбора устройства Cast.

Мы расширим функциональность тестового приложения, чтобы оно также воспроизводило видео удаленно на устройстве Cast. Для этого нам нужно отслеживать различные события, генерируемые фреймворком Cast.

СМИ для кастинга

В общих чертах, чтобы воспроизвести медиафайл на устройстве Cast, необходимо выполнить следующие действия:

  1. Создайте JSON объект MediaInfo из Cast SDK, который моделирует медиафайл.
  2. Пользователь подключается к устройству Cast для запуска приложения вашего ресивера.
  3. Загрузите объект MediaInfo в свой ресивер и воспроизведите контент.
  4. Отслеживайте статус в СМИ.
  5. Отправляйте команды воспроизведения на приемник в зависимости от действий пользователя.

Шаг 1 сводится к сопоставлению одного объекта с другим; MediaInfo — это то, что понимает Cast SDK, а mediaJSON — это инкапсуляция медиафайла в нашем приложении; мы можем легко сопоставить mediaJSON с MediaInfo . Шаг 2 мы уже выполнили в предыдущем разделе. Шаг 3 легко выполнить с помощью Cast SDK.

В демонстрационном приложении CastPlayer уже реализовано различие между локальным и удаленным воспроизведением в методе switchPlayer :

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

В рамках этого практического занятия вам не обязательно точно понимать всю логику работы тестового проигрывателя. Однако важно понимать, что медиаплеер вашего приложения необходимо будет модифицировать, чтобы он распознавал как локальное, так и удалённое воспроизведение.

В данный момент локальный плеер всегда находится в состоянии локального воспроизведения, поскольку он ещё ничего не знает о состояниях Casting. Нам необходимо обновлять пользовательский интерфейс на основе переходов состояний, происходящих во фреймворке Cast. Например, если мы начинаем трансляцию, нам нужно остановить локальное воспроизведение и отключить некоторые элементы управления. Аналогично, если мы останавливаем трансляцию, находясь в этом контроллере представления, нам нужно перейти к локальному воспроизведению. Для этого нам необходимо отслеживать различные события, генерируемые фреймворком Cast.

управление кастингом

В рамках платформы Cast сессия Cast объединяет этапы подключения к устройству, запуска (или присоединения к существующей сессии), подключения к приложению-приемнику и инициализации канала управления воспроизведением мультимедиа, если это необходимо. Канал управления воспроизведением мультимедиа — это способ, с помощью которого платформа Cast отправляет и получает сообщения, связанные с воспроизведением мультимедиа, от приемника.

Сеанс Cast запускается автоматически, когда пользователь выбирает устройство с помощью кнопки Cast, и автоматически останавливается при отключении пользователя. Повторное подключение к сеансу приемника из-за проблем с сетью также автоматически обрабатывается платформой Cast.

Управление сессиями Cast осуществляется с помощью CastSession , доступ к которому можно получить через cast.framework.CastContext.getInstance().getCurrentSession() . Колбэки EventListener можно использовать для отслеживания событий сессии, таких как создание, приостановка, возобновление и завершение.

В нашем текущем приложении управление сессиями и состоянием осуществляется в методе setupRemotePlayer . Давайте начнем настройку этого в вашем приложении, добавив следующий код в файл 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();
};

Нам еще нужно связать все события из колбэков и обработать все входящие события. Это довольно простая задача, так что давайте займемся этим сейчас:

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

Загрузка медиафайлов

В Cast SDK объекты RemotePlayer и RemotePlayerController предоставляют набор удобных API для управления воспроизведением медиафайлов на приемнике. Для CastSession , поддерживающего воспроизведение медиафайлов, экземпляры RemotePlayer и RemotePlayerController будут автоматически созданы SDK. Доступ к ним можно получить, создав экземпляры cast.framework.RemotePlayer и cast.framework.RemotePlayerController соответственно, как показано ранее в практическом задании.

Далее нам необходимо загрузить выбранное в данный момент видео на приемник, создав объект MediaInfo, который SDK сможет обработать и передать в запросе. Для этого добавьте следующий код в setupRemotePlayer :

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

    //...
};

Теперь добавим метод для переключения между локальным и удалённым воспроизведением:

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

Наконец, добавьте метод для обработки любых сообщений об ошибках 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 : '');
  }
};

Теперь запустите приложение. Подключитесь к своему устройству Cast и начните воспроизведение видео. Вы должны увидеть видео на ресивере.

7. Добавить поддержку Cast Connect.

Библиотека Cast Connect позволяет существующим приложениям-отправителям взаимодействовать с приложениями Android TV через протокол Cast. Cast Connect строится на основе инфраструктуры Cast, при этом ваше приложение Android TV выступает в качестве приемника.

Зависимости

  • Версия браузера Chrome: M87 или выше

Установить совместимость с Android Receiver

Для запуска приложения Android TV, также известного как Android Receiver, необходимо установить флаг androidReceiverCompatible в значение true в объекте CastOptions .

Добавьте следующий код в функцию initializeCastPlayer в файл CastVideos.js :

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

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

Установить учетные данные для запуска

На стороне отправителя вы можете указать CredentialsData , представляющую того, кто присоединяется к сессии. credentials представляют собой строку, которую может задать пользователь, если ваше приложение для Android TV может ее распознать. CredentialsData передается в ваше приложение Android TV только во время запуска или присоединения. Если вы установите ее снова во время подключения, она не будет передана в ваше приложение Android TV.

Для установки учетных данных запуска необходимо задать CredentialsData CredentialsData в любое время после установки параметров запуска.

Добавьте следующий код в класс CastVideos.js в функцию initializeCastPlayer :

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

Установка учетных данных для запроса на загрузку

Если ваше приложение Web Receiver и приложение для Android TV обрабатывают credentials по-разному, вам может потребоваться определить отдельные учетные данные для каждого из них. Для этого добавьте следующий код в файл CastVideos.js в раздел playerTarget.load в функции setupRemotePlayer :

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

В зависимости от того, какое приложение-получатель отправляет данные, SDK теперь будет автоматически определять, какие учетные данные использовать для текущей сессии.

Тестирование Cast Connect

Инструкция по установке APK-файла Android TV на Chromecast с Google TV:

  1. Узнайте IP-адрес вашего устройства Android TV. Обычно он находится в разделе «Настройки» > «Сеть и интернет» > (Название сети, к которой подключено ваше устройство) . Справа отобразятся подробные сведения и IP-адрес вашего устройства в этой сети.
  2. Используйте IP-адрес вашего устройства для подключения к нему через ADB с помощью терминала:
$ adb connect <device_ip_address>:5555
  1. В окне терминала перейдите в корневую папку, содержащую примеры кода, которые вы скачали в начале этого задания. Например:
$ cd Desktop/chrome_codelab_src
  1. Установите файл .apk из этой папки на свой Android TV, выполнив следующую команду:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. Теперь в меню «Ваши приложения» на вашем устройстве Android TV должно отображаться приложение под названием Cast Videos .
  2. Запустите обновленный код веб-отправителя и установите сеанс трансляции на ваше устройство Android TV, используя значок трансляции или выбрав Cast.. в выпадающем меню вашего браузера Chrome. Это должно запустить приложение Android TV на вашем Android-ресивере и позволить вам управлять воспроизведением с помощью пульта дистанционного управления Android TV.

8. Поздравляем!

Теперь вы знаете, как включить функцию Cast для видеоприложения с помощью виджетов Cast SDK в веб-приложении Chrome.

Для получения более подробной информации см. руководство разработчика Web Sender .