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

1. Обзор

Логотип Google Cast

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

Что такое Google Cast?

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

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

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

Что мы собираемся строить?

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

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

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

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

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

Опыт

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

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

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

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

Новичок Средний Опытный

Как бы вы оценили свои впечатления от просмотра телевидения?

Новичок Средний Опытный

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

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

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

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

Логотип Google Chrome

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

Чтобы иметь возможность использовать завершенное, его необходимо разместить на хостинге.

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

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

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

В браузере перейдите по URL-адресу https для размещенного вами образца.

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

Изображение видео, воспроизводимого на устройстве 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 также загружает Cast SDK и сообщает функции CastVideos о необходимости загрузки.

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

CastVideos.js

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

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

CastPlayer — это основной класс, который управляет всем приложением, настраивает проигрыватель, выбирает медиафайлы и привязывает события к PlayerHandler для воспроизведения мультимедиа. CastPlayer.prototype.initializeCastPlayer — это метод, который настраивает все функции Cast. 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 .

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

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

В браузере перейдите по URL-адресу https для размещенного вами образца.

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

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

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

Объект JSON options должен быть предоставлен при инициализации CastContext . Этот класс содержит параметры, влияющие на поведение платформы. Наиболее важным из них является идентификатор приложения-приемника, который используется для фильтрации списка доступных устройств 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. Cast SDK предоставляет компонент кнопки 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. Нажмите кнопку Cast, чтобы остановить трансляцию.

6. Кастинг видеоконтента

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

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

Кастинг СМИ

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

  1. Создайте объект MediaInfo JSON из 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) {
    //...

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

На данный момент локальный проигрыватель всегда находится в состоянии локального воспроизведения, поскольку он еще ничего не знает о состояниях кастинга. Нам нужно обновить пользовательский интерфейс на основе переходов состояний, которые происходят в среде 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 , поддерживающего воспроизведение мультимедиа, SDK автоматически создаст экземпляры RemotePlayer и RemotePlayerController . Доступ к ним можно получить, создав экземпляры 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-приемником

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

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

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

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

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

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

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

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

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

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

Если ваше приложение веб-приемника и приложение 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. Теперь вы сможете увидеть приложение под названием Cast Videos в меню «Ваши приложения» на своем устройстве Android TV.
  2. Запустите обновленный код веб-отправителя и установите сеанс трансляции на своем устройстве Android TV, используя значок трансляции или выбрав Cast.. в раскрывающемся меню браузера Chrome. Теперь на вашем Android-приемнике должно запуститься приложение Android TV, и вы сможете управлять воспроизведением с помощью пульта Android TV.

8. Поздравления

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

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