1. Обзор
В этой лабораторной работе вы узнаете, как создать пользовательское приложение Web Receiver для воспроизведения контента на устройствах с поддержкой Cast .
Что такое Google Cast?
Google Cast позволяет пользователям транслировать контент с мобильного устройства на телевизор. Затем пользователи могут использовать свое мобильное устройство или настольный браузер Chrome в качестве пульта дистанционного управления для воспроизведения мультимедиа на телевизоре.
Google Cast SDK позволяет вашему приложению управлять устройствами с поддержкой Google Cast (например, телевизором или аудиосистемой). Cast SDK предоставляет необходимые компоненты пользовательского интерфейса на основе контрольного списка Google Cast Design Checklist .
Контрольный список Google Cast Design предназначен для того, чтобы сделать работу с Cast простой и предсказуемой на всех поддерживаемых платформах. Подробнее здесь.
Что мы будем строить?
Когда вы закончите эту лабораторную работу, у вас будет приложение HTML5, которое действует как ваш собственный пользовательский приемник , способный отображать видеоконтент на устройствах с поддержкой Cast.
Что вы узнаете
- Как настроиться на разработку приемника.
- Основы приемника с поддержкой Cast на базе Cast Application Framework.
- Как получить отлитое видео.
- Как интегрировать Debug Logger.
- Как оптимизировать ваш приемник для интеллектуальных дисплеев.
Что вам понадобится
- Последний браузер Google Chrome .
- Служба хостинга HTTPS, такая как Firebase Hosting или ngrok .
- Устройство Google Cast, например Chromecast или Android TV, с доступом в Интернет.
- Телевизор или монитор с входом HDMI.
Опыт
- Вам понадобятся предыдущие знания в области веб-разработки.
- Вам также понадобятся предварительные знания о просмотре телевизора :)
Как вы будете использовать этот учебник?
Как бы вы оценили свой опыт создания веб-приложений?
Как бы вы оценили свой опыт просмотра телевизора?
2. Получите пример кода
Вы можете загрузить весь пример кода на свой компьютер...
и распакуйте загруженный zip-файл.
3. Локальное развертывание ресивера
Чтобы иметь возможность использовать ваш веб-приемник с устройством Cast, он должен быть размещен где-то, где ваше устройство Cast может получить к нему доступ. Если у вас уже есть сервер, поддерживающий https, пропустите следующие инструкции и запишите URL-адрес , так как он понадобится вам в следующем разделе.
Если у вас нет доступного сервера, вы можете использовать Firebase Hosting или ngrok .
Запустить сервер
После того, как вы настроите службу по вашему выбору, перейдите к app-start
и запустите свой сервер.
Запишите URL-адрес вашего размещенного приемника. Вы будете использовать его в следующем разделе.
4. Зарегистрируйте приложение в Cast Developer Console.
Вы должны зарегистрировать свое приложение , чтобы иметь возможность запускать собственный приемник, созданный в этой лаборатории кода, на устройствах Chromecast. После регистрации приложения вы получите идентификатор приложения, который ваше приложение-отправитель должно использовать для выполнения вызовов API, например для запуска приложения-получателя.
Нажмите «Добавить новое приложение»
Выберите «Пользовательский приемник», это то, что мы создаем.
Введите данные вашего нового приемника, обязательно используйте URL-адрес, который вы получили.
в последнем разделе. Запишите идентификатор приложения , присвоенный вашему новому приемнику.
Вы также должны зарегистрировать свое устройство Google Cast , чтобы оно могло получить доступ к вашему приложению-приемнику, прежде чем вы его опубликуете. После того как вы опубликуете свое приложение-приемник, оно будет доступно для всех устройств Google Cast. Для целей этой кодовой лаборатории рекомендуется работать с неопубликованным приложением-приемником.
Нажмите «Добавить новое устройство».
Введите серийный номер, напечатанный на задней панели вашего устройства Cast, и дайте ему описательное имя. Вы также можете найти свой серийный номер, транслируя свой экран в Chrome при доступе к консоли разработчика Google Cast SDK.
Прежде чем ваш приемник и устройство будут готовы к тестированию, пройдет 5-15 минут. Подождав 5-15 минут, вы должны перезагрузить устройство Cast.
5. Запустите пример приложения
Пока мы ждем, пока наше новое приложение-приемник будет готово к тестированию, давайте посмотрим, как выглядит образец завершенного приложения-приемника. Ресивер, который мы собираемся создать, сможет воспроизводить мультимедиа с использованием потоковой передачи с адаптивным битрейтом (мы будем использовать образец контента, закодированный для динамической адаптивной потоковой передачи через HTTP (DASH)).
В браузере откройте инструмент управления и контроля (CaC) .
- Вы должны увидеть наш инструмент CaC.
- Используйте идентификатор приемника образца по умолчанию «CC1AD845» и нажмите кнопку «Установить идентификатор приложения».
- Нажмите кнопку Cast в левом верхнем углу и выберите свое устройство Google Cast.
- Перейдите на вкладку «Загрузить носитель» вверху.
- Нажмите кнопку «Загрузить по содержимому», чтобы воспроизвести образец видео.
- Видео начнет воспроизводиться на вашем устройстве Google Cast, чтобы показать, как выглядят основные функции приемника при использовании приемника по умолчанию.
6. Подготовьте стартовый проект
Нам нужно добавить поддержку Google Cast в загруженное вами начальное приложение. Вот некоторые термины Google Cast, которые мы будем использовать в этой кодовой лаборатории:
- приложение отправителя работает на мобильном устройстве или ноутбуке,
- приложение- приемник работает на устройстве Google Cast.
Теперь вы готовы строить поверх начального проекта с помощью вашего любимого текстового редактора:
- Выберите
каталог
app-start
из загрузки примера кода. - Откройте
js/receiver.js
иindex.html
Обратите внимание, что пока вы работаете с этой кодовой лабораторией, http-server
должен собирать изменения, которые вы вносите. Если вы заметили, что это не так, попробуйте убить и перезапустить http-server
.
Дизайн приложений
Приложение-получатель инициализирует сеанс Cast и будет находиться в режиме ожидания, пока не поступит запрос LOAD (другими словами, команда на воспроизведение фрагмента мультимедиа) от отправителя.
Приложение состоит из одного основного представления, определенного в index.html
, и одного файла JavaScript с именем js/receiver.js
, содержащего всю логику для работы нашего приемника.
index.html
Этот html-файл будет содержать пользовательский интерфейс для нашего приложения-приемника. На данный момент он пуст, и мы будем добавлять его на протяжении всей лаборатории кода.
приемник.js
Этот скрипт будет управлять всей логикой нашего приложения-приемника. Сейчас это просто пустой файл, но мы собираемся превратить его в полностью функционирующий приемник Cast, написав всего несколько строк кода в следующем разделе.
7. Базовый ресивер Cast
Базовый приемник Cast инициализирует сеанс Cast при запуске. Это необходимо, чтобы сообщить всем подключенным приложениям-отправителям, что вызов получателя прошел успешно. Кроме того, новый SDK поставляется предварительно настроенным для обработки потокового мультимедиа с адаптивным битрейтом (с использованием DASH, HLS и Smooth Streaming) и обычных файлов MP4. Давайте попробуем это.
Инициализация
Добавьте следующий код в index.html
в шапке:
<head>
...
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>
Добавьте следующий код в index.html
<body>
перед < footer>
загрузкой receiver.js,
чтобы предоставить SDK приемника место для вызова пользовательского интерфейса приемника по умолчанию, который поставляется с только что добавленным сценарием.
<cast-media-player></cast-media-player>
Теперь нам нужно инициализировать SDK в js/receiver.js
, состоящий из:
- получить ссылку на
CastReceiverContext
, вашу основную точку входа во весь Receiver SDK. - хранение ссылки на
PlayerManager
, объект, обрабатывающий воспроизведение и предоставляющий вам все хуки, необходимые для подключения вашей собственной пользовательской логики. - инициализация SDK путем вызова
start()
вCastReceiverContext
Добавьте следующее в js/receiver.js
.
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
context.start();
8. Кастинг «базового» видеоконтента
Для целей этой Codelab используйте CaC Tool, чтобы опробовать свой новый приемник.
Откройте в веб-браузере Command and Control (CaC) Tool .
Обязательно подставьте свой собственный идентификатор приложения , зарегистрированный ранее, в поле и нажмите «Установить идентификатор приложения». Это указывает инструменту использовать ваш приемник при запуске сеанса Cast.
Кастинг СМИ
На высоком уровне для воспроизведения мультимедиа на устройстве Cast должно произойти следующее:
- Отправитель создает объект
MediaInfo
JSON
из Cast SDK, который моделирует элемент мультимедиа. - Отправитель подключается к устройству Cast, чтобы запустить приложение получателя.
- Получатель загружает объект
MediaInfo
через запросLOAD
для воспроизведения содержимого. - Ресивер отслеживает и отслеживает состояние носителя.
- Отправитель отправляет команды воспроизведения получателю для управления воспроизведением на основе взаимодействия пользователя с приложением-отправителем.
В этой первой базовой попытке мы собираемся заполнить MediaInfo
URL-адресом воспроизводимого ресурса (хранящимся в MediaInfo.contentUrl
).
Реальный отправитель использует идентификатор мультимедиа для конкретного приложения в MediaInfo.contentId
. Получатель использует contentId
в качестве идентификатора, чтобы сделать соответствующие вызовы внутреннего API для разрешения фактического URL-адреса ресурса и установить для него значение MediaInfo.contentUrl.
Приемник также будет выполнять такие задачи, как получение лицензии DRM или ввод информации о рекламных паузах.
Мы собираемся расширить ваш приемник, чтобы сделать что-то подобное в следующем разделе. А пока щелкните значок Cast и выберите свое устройство, чтобы открыть приемник.
Перейдите на вкладку «Загрузить медиаданные» и нажмите кнопку «Загрузить по содержимому». Ресивер должен начать воспроизводить образец содержимого.
Таким образом, Receiver SDK по умолчанию обрабатывает:
- Инициализация сеанса Cast
- Обрабатывать входящие запросы
LOAD
от отправителей, которые содержат игровые активы - Предоставьте базовый пользовательский интерфейс проигрывателя, готовый к отображению на большом экране.
Не стесняйтесь изучить инструмент CaC и его код, прежде чем перейти к следующему разделу, где мы собираемся расширить наш приемник, чтобы он мог общаться с простым примером API для выполнения входящих запросов LOAD
от отправителей.
9. Интеграция с внешним API
В соответствии с тем, как большинство разработчиков взаимодействуют со своими приемниками Cast в реальных приложениях, мы собираемся модифицировать наш приемник для обработки запросов LOAD
, которые ссылаются на предполагаемый медиаконтент по его ключу API, а не отправляют по URL-адресу воспроизводимого ресурса.
Приложения обычно делают это, потому что:
- Отправитель может не знать URL контента.
- Приложение Cast предназначено для обработки аутентификации, другой бизнес-логики или вызовов API непосредственно на приемнике.
Эта функциональность в основном реализована в методе setMessageInterceptor()
PlayerManager
. Это позволяет перехватывать входящие сообщения по типу и изменять их до того, как они достигнут внутреннего обработчика сообщений SDK. В этом разделе мы имеем дело с запросами LOAD
, где мы сделаем следующее:
- Прочитайте входящий запрос
LOAD
и его пользовательскийcontentId
. - Сделайте запрос
GET
к нашему API, чтобы найти потоковый актив по егоcontentId
. - Измените запрос
LOAD
, указав URL-адрес потока. - Измените объект
MediaInformation
, чтобы задать параметры типа потока. - Передайте запрос в SDK для воспроизведения или отклоните команду, если мы не можем найти запрошенный носитель.
Предоставленный пример API демонстрирует возможности SDK для настройки общих задач приемника, при этом по-прежнему полагаясь на стандартные возможности.
Пример API
Откройте в браузере страницу https://storage.googleapis.com/cpe-sample-media/content.json и просмотрите наш каталог примеров видео. Контент включает URL-адреса изображений постеров в формате png, а также потоки DASH и HLS. Потоки DASH и HLS указывают на демультиплексированные видео- и аудиоисточники, хранящиеся в фрагментированных контейнерах mp4.
{
"bbb": {
"author": "The Blender Project",
"description": "Grumpy Bunny is grumpy",
"poster": "https://[...]/[...]/BigBuckBunny/images/screenshot1.png",
"stream": {
"dash": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.mpd",
"hls": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.m3u8",
"title": "Big Buck Bunny"
},
"fbb_ad": {
"author": "Google Inc.",
"description": "Introducing Chromecast. The easiest way to enjoy [...]",
"poster": "https://[...]/[...]/ForBiggerBlazes/images/screenshot8.png",
"stream": {
"dash": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.mpd",
"hls": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.m3u8",
"title": "For Bigger Blazes"
},
[...]
}
На следующем шаге мы сопоставим ключ каждой записи (например, bbb, fbb_ad
) с URL-адресом потока после того, как получатель будет вызван с запросом LOAD
.
Перехватить запрос LOAD
На этом этапе мы создадим перехватчик загрузки с функцией, которая отправляет XHR
запрос к размещенному JSON
файлу. Как только файл JSON
будет получен, мы проанализируем содержимое и установим метаданные. В следующих разделах мы настроим параметры MediaInformation
, чтобы указать тип контента.
Добавьте следующий код в файл js/receiver.js
непосредственно перед вызовом context.start()
.
function makeRequest (method, url) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
// Fetch content repository by requested contentId
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json').then(function (data) {
let item = data[request.media.contentId];
if(!item) {
// Content could not be found in repository
reject();
} else {
// Add metadata
let metadata = new
cast.framework.messages.GenericMediaMetadata();
metadata.title = item.title;
metadata.subtitle = item.author;
request.media.metadata = metadata;
// Resolve request
resolve(request);
}
});
});
});
В следующем разделе будет описано, как настроить media
свойство запроса на загрузку для содержимого DASH.
Использование примера контента API DASH
Теперь, когда мы подготовили перехватчик нагрузки, мы укажем тип контента получателю. Эта информация предоставит получателю URL-адрес основного списка воспроизведения и тип MIME потока. Добавьте следующий код в файл js/receiver.js в Promise()
перехватчика LOAD
:
...
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
...
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.dash;
request.media.contentType = 'application/dash+xml';
...
}
});
});
});
Выполнив этот шаг, вы можете перейти к тестированию, чтобы попробовать загрузить содержимое DASH. Если вы хотите протестировать загрузку с содержимым HLS, перейдите к следующему шагу.
Использование примера содержимого API HLS
Пример API включает содержимое HLS, а также DASH. В дополнение к настройке contentType
, как мы сделали на предыдущем шаге, запросу на загрузку потребуются некоторые дополнительные свойства, чтобы использовать URL-адреса HLS примера API. Когда приемник настроен на воспроизведение потоков HLS, ожидаемым типом контейнера по умолчанию является транспортный поток (TS). В результате получатель попытается открыть образцы потоков MP4 в формате TS, если изменено только свойство contentUrl
. В запросе на загрузку объект MediaInformation
должен быть модифицирован дополнительными свойствами, чтобы получатель знал, что содержимое имеет тип MP4, а не TS. Добавьте следующий код в файл js/receiver.js в перехватчике загрузки, чтобы изменить свойства contentUrl
и contentType
. Дополнительно добавьте свойства HlsSegmentFormat
и HlsVideoSegmentFormat
.
...
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
...
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.hls;
request.media.contentType = 'application/x-mpegurl';
request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
...
}
});
});
});
Тестирование
Снова откройте инструмент управления и контроля (CaC) и установите идентификатор приложения на идентификатор приложения вашего приемника. Выберите свое устройство с помощью кнопки Cast.
Перейдите на вкладку «Загрузить носитель». На этот раз удалите текст в поле «URL-адрес содержимого» рядом с кнопкой «Загрузить по содержимому», что заставит наше приложение отправить запрос LOAD
, содержащий только ссылку contentId
на наш медиафайл.
Предполагая, что все работает нормально с вашими изменениями в приемнике, перехватчик должен позаботиться о формировании объекта MediaInfo
во что-то, что SDK может воспроизводить на экране.
Нажмите кнопку «Загрузить по содержимому», чтобы проверить, правильно ли воспроизводится ваш медиафайл. Не стесняйтесь изменить идентификатор контента на другой идентификатор в файле content.json .
10. Оптимизация для смарт-дисплеев
Смарт-дисплеи — это устройства с сенсорными функциями, которые позволяют приложениям-приемникам поддерживать сенсорное управление.
В этом разделе объясняется, как оптимизировать приложение-приемник при запуске на смарт-дисплеях и как настроить элементы управления проигрывателем.
Доступ к элементам управления пользовательского интерфейса
Доступ к объекту элементов управления пользовательского интерфейса для смарт-дисплеев можно получить с помощью cast.framework.ui.Controls.GetInstance()
. Добавьте следующий код в файл js/receiver.js
выше context.start()
:
...
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
context.start();
Если вы не используете элемент <cast-media-player>, вам потребуется установить touchScreenOptimizedApp
в CastReceiverOptions
. В этой кодовой лаборатории мы используем элемент <cast-media-player>.
context.start({ touchScreenOptimizedApp: true });
Кнопки управления по умолчанию назначаются каждому слоту на основе MetadataType
и MediaStatus.supportedMediaCommands
.
Управление видео
Для MetadataType.MOVIE
, MetadataType.TV_SHOW
и MetadataType.GENERIC
объект UI Controls для Smart Displays будет отображаться, как в примере ниже.
-
--playback-logo-image
-
MediaMetadata.subtitle
-
MediaMetadata.title
-
MediaStatus.currentTime
-
MediaInformation.duration
-
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.QUEUE_PREV
-
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.SEEK_BACKWARD_30
-
PLAY/PAUSE
-
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.SEEK_FORWARD_30
-
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.QUEUE_NEXT
Звуковые элементы управления
Для MetadataType.MUSIC_TRACK
объект элементов управления пользовательского интерфейса для смарт-дисплеев будет отображаться, как показано ниже:
-
--playback-logo-image
-
MusicTrackMediaMetadata.albumName
-
MusicTrackMediaMetadata.title
-
MusicTrackMediaMetadata.albumArtist
-
MusicTrackMediaMetadata.images[0]
-
MediaStatus.currentTime
-
MediaInformation.duration
-
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.NO_BUTTON
-
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.QUEUE_PREV
-
PLAY/PAUSE
-
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.QUEUE_NEXT
-
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.NO_BUTTON
Обновление поддерживаемых мультимедийных команд
Объект UI Controls также определяет, отображается ли ControlsButton
или нет, на основе MediaStatus.supportedMediaCommands
.
Когда значение supportedMediaCommands
равно ALL_BASIC_MEDIA
, макет элемента управления по умолчанию будет отображаться, как показано ниже:
Когда значение supportedMediaCommands
равно ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT
, макет элемента управления по умолчанию будет отображаться следующим образом:
Когда значение supportedMediaCommands равно PAUSE | QUEUE_PREV | QUEUE_NEXT
, макет элемента управления по умолчанию будет отображаться следующим образом:
Когда доступны текстовые дорожки, кнопка субтитров всегда будет отображаться на SLOT_1
.
Чтобы динамически изменить значение supportedMediaCommands
после запуска контекста приемника, вы можете вызвать PlayerManager.setSupportedMediaCommands
, чтобы переопределить значение. Кроме того, вы можете добавить новую команду с помощью addSupportedMediaCommands
или удалить существующую команду с помощью removeSupportedMediaCommands
.
Настройка кнопок управления
Вы можете настроить элементы управления с помощью PlayerDataBinder
. Добавьте следующий код в файл js/receiver.js
под touchControls, чтобы установить первый слот ваших элементов управления:
...
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
playerDataBinder.addEventListener(
cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
(e) => {
if (!e.value) return;
// Clear default buttons and re-assign
touchControls.clearDefaultSlotAssignments();
touchControls.assignButton(
cast.framework.ui.ControlsSlot.SLOT_PRIMARY_1,
cast.framework.ui.ControlsButton.SEEK_BACKWARD_30
);
});
context.start();
11. Реализация просмотра мультимедиа на смарт-дисплеях
Media Browse — это функция CAF Receiver, которая позволяет пользователям просматривать дополнительный контент на сенсорных устройствах. Чтобы реализовать это, вы будете использовать PlayerDataBinder
для установки пользовательского интерфейса BrowseContent
. Затем вы можете заполнить его BrowseItems
на основе содержимого, которое вы хотите отобразить.
BrowseContent
Ниже приведен пример пользовательского интерфейса BrowseContent
и его свойств:
-
BrowseContent.title
-
BrowseContent.items
Соотношение сторон
Используйте targetAspectRatio property
, чтобы выбрать наилучшее соотношение сторон для ваших изображений. SDK приемника CAF поддерживает три соотношения сторон: SQUARE_1_TO_1
, PORTRAIT_2_TO_3
, LANDSCAPE_16_TO_9
.
BrowseItem
Используйте BrowseItem
для отображения заголовка, подзаголовка, продолжительности и изображения для каждого элемента:
-
BrowseItem.image
-
BrowseItem.duration
-
BrowseItem.title
-
BrowseItem.subtitle
Установить данные просмотра мультимедиа
Вы можете предоставить список медиа-контента для просмотра, вызвав setBrowseContent
. Добавьте следующий код в файл js/receiver.js
под вашим playerDataBinder
и в прослушиватель событий MEDIA_CHANGED
, чтобы установить элементы просмотра с заголовком «Далее».
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
...
let browseItems = getBrowseItems();
function getBrowseItems() {
let browseItems = [];
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
.then(function (data) {
for (let key in data) {
let item = new cast.framework.ui.BrowseItem();
item.entity = key;
item.title = data[key].title;
item.subtitle = data[key].description;
item.image = new cast.framework.messages.Image(data[key].poster);
item.imageType = cast.framework.ui.BrowseImageType.MOVIE;
browseItems.push(item);
}
});
return browseItems;
}
let browseContent = new cast.framework.ui.BrowseContent();
browseContent.title = 'Up Next';
browseContent.items = browseItems;
browseContent.targetAspectRatio = cast.framework.ui.BrowseImageAspectRatio.LANDSCAPE_16_TO_9;
playerDataBinder.addEventListener(
cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
(e) => {
if (!e.value) return;
....
// Media browse
touchControls.setBrowseContent(browseContent);
});
Нажатие на элемент просмотра мультимедиа вызовет перехватчик LOAD
. Добавьте следующий код в свой перехватчик LOAD
, чтобы сопоставить request.media.contentId
с request.media.entity
из элемента просмотра мультимедиа:
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
...
// Map contentId to entity
if (request.media && request.media.entity) {
request.media.contentId = request.media.entity;
}
return new Promise((resolve, reject) => {
...
});
});
Вы также можете установить для объекта BrowseContent
значение null
, чтобы удалить пользовательский интерфейс Media Browse.
12. Отладка приложений приемника
Cast Receiver SDK предоставляет разработчикам еще один вариант простой отладки приложений-приемников с помощью CastDebugLogger API и сопутствующего инструмента Command and Control (CaC) для сбора журналов.
Инициализация
Чтобы включить API, добавьте исходный сценарий CastDebugLogger
в файл index.html. Источник должен быть объявлен в теге <head> после объявления SDK Cast Receiver.
<head>
...
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
<!-- Cast Debug Logger -->
<script src="//www.gstatic.com/cast/sdk/libs/devtools/debug_layer/caf_receiver_logger.js"></script>
</head>
В js/receiver.js
в верхней части файла и под playerManager
добавьте следующий код, чтобы получить экземпляр CastDebugLogger
и включить регистратор:
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MyAPP.LOG';
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
castDebugLogger.setEnabled(true);
}
});
Когда регистратор отладки включен, на приемнике отображается наложение с надписью DEBUG MODE
.
Записывать события игрока
Используя CastDebugLogger
вы можете легко регистрировать события игрока, которые запускаются CAF Receiver SDK, и использовать различные уровни ведения журнала для регистрации данных событий. Конфигурация loggerLevelByEvents
использует cast.framework.events.EventType
и cast.framework.events.category
, чтобы указать, какие события будут регистрироваться.
Добавьте следующий код под объявлением castDebugLogger
, чтобы регистрировать, когда запускается событие CORE
проигрывателя или транслируется изменение mediaStatus
:
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
castDebugLogger.setEnabled(true);
}
});
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}
Сообщения журнала и пользовательские теги
CastDebugLogger API позволяет создавать сообщения журнала, которые отображаются в наложении отладки приемника разными цветами. Доступны следующие методы ведения журнала, перечисленные в порядке от высшего к низшему приоритету:
-
castDebugLogger.error(custom_tag, message);
-
castDebugLogger.warn(custom_tag, message);
-
castDebugLogger.info(custom_tag, message);
-
castDebugLogger.debug(custom_tag, message);
Для каждого метода журнала первым параметром является настраиваемый тег. Это может быть любая идентифицирующая строка, которую вы считаете значимой. CastDebugLogger
использует теги для фильтрации журналов. Использование тегов подробно объясняется ниже. Второй параметр — это сообщение журнала .
Чтобы показать журналы в действии, добавьте журналы в свой перехватчик LOAD
.
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
castDebugLogger.info(LOG_TAG, 'Intercepting LOAD request');
// Map contentId to entity
if (request.media && request.media.entity) {
request.media.contentId = request.media.entity;
}
return new Promise((resolve, reject) => {
// Fetch content repository by requested contentId
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
.then(function (data) {
let item = data[request.media.contentId];
if(!item) {
// Content could not be found in repository
castDebugLogger.error(LOG_TAG, 'Content not found');
reject();
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.dash;
request.media.contentType = 'application/dash+xml';
castDebugLogger.warn(LOG_TAG, 'Playable URL:', request.media.contentUrl);
// Add metadata
let metadata = new cast.framework.messages.MovieMediaMetadata();
metadata.metadataType = cast.framework.messages.MetadataType.MOVIE;
metadata.title = item.title;
metadata.subtitle = item.author;
request.media.metadata = metadata;
// Resolve request
resolve(request);
}
});
});
});
Вы можете контролировать, какие сообщения будут отображаться в наложении отладки, задав уровень журнала в loggerLevelByTags
для каждого пользовательского тега. Например, при включении пользовательского тега с уровнем журнала cast.framework.LoggerLevel.DEBUG
будут отображаться все сообщения, добавленные с ошибками, предупреждениями, информацией и сообщениями журнала отладки. При включении пользовательского тега с уровнем WARNING
будут отображаться только сообщения журнала ошибок и предупреждений.
Конфигурация loggerLevelByTags
не является обязательной. Если для пользовательского тега не настроен уровень ведения журнала, все сообщения журнала будут отображаться в оверлее отладки.
Добавьте следующий код под регистратором событий CORE
:
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}
// Set verbosity level for custom tags.
castDebugLogger.loggerLevelByTags = {
[LOG_TAG]: cast.framework.LoggerLevel.DEBUG,
};
Наложение отладки
Cast Debug Logger обеспечивает наложение отладки на приемник для отображения ваших пользовательских сообщений журнала на устройстве трансляции. Используйте showDebugLogs
для переключения наложения отладки и clearDebugLogs
для очистки сообщений журнала в наложении.
Добавьте следующий код для предварительного просмотра наложения отладки на приемнике.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
castDebugLogger.setEnabled(true);
// Show debug overlay
castDebugLogger.showDebugLogs(true);
// Clear log messages on debug overlay
castDebugLogger.clearDebugLogs();
}
});
13. Поздравления
Теперь вы знаете, как создать пользовательское приложение веб-приемника с помощью Cast Web Receiver SDK.
Дополнительные сведения см. в руководстве разработчика Web Receiver .