1. Обзор
В этой лаборатории кода вы узнаете, как создать приложение Custom Web Receiver для воспроизведения контента на устройствах с поддержкой Cast .
Что такое Google Cast?
Google Cast позволяет пользователям транслировать контент с мобильного устройства на телевизор. Затем пользователи могут использовать свое мобильное устройство или браузер Chrome на настольном компьютере в качестве пульта дистанционного управления для воспроизведения мультимедиа на телевизоре.
Google Cast SDK позволяет вашему приложению управлять устройствами с поддержкой Google Cast (например, телевизором или аудиосистемой). Cast SDK предоставляет необходимые компоненты пользовательского интерфейса на основе контрольного списка Google Cast Design .
Контрольный список 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 или ngrok .
Запустить сервер
После того, как вы настроите выбранную вами службу, перейдите к app-start
и запустите свой сервер.
Запишите URL-адрес вашего размещенного приемника. Вы будете использовать его в следующем разделе.
4. Зарегистрируйте приложение в консоли разработчика Cast.
Вам необходимо зарегистрировать свое приложение , чтобы иметь возможность запускать собственный приемник, встроенный в эту кодовую лабораторию, на устройствах 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. Кастинг «базового» видеоконтента
Для целей этой лаборатории кода используйте CaC Tool, чтобы опробовать свой новый приемник.
Направьте свой веб-браузер на инструмент управления и контроля (CaC) .
Обязательно замените в поле свой собственный идентификатор приложения , зарегистрированный ранее, и нажмите «Установить идентификатор приложения». Это указывает инструменту использовать ваш приемник при запуске сеанса трансляции.
Кастинг СМИ
На высоком уровне для воспроизведения мультимедиа на устройстве Cast должно произойти следующее:
- Отправитель создает объект
MediaInfo
JSON
из Cast SDK, который моделирует элемент мультимедиа. - Отправитель подключается к устройству Cast для запуска приложения-получателя.
- Получатель загружает объект
MediaInfo
с помощью запросаLOAD
для воспроизведения содержимого. - Ресивер контролирует и отслеживает состояние носителя.
- Отправитель отправляет получателю команды воспроизведения для управления воспроизведением на основе взаимодействия пользователя с приложением отправителя.
В этой первой базовой попытке мы собираемся заполнить MediaInfo
URL-адресом воспроизводимого ресурса (хранящимся в MediaInfo.contentUrl
).
Реальный отправитель использует идентификатор мультимедиа, специфичный для приложения, в MediaInfo.contentId
. Получатель использует contentId
в качестве идентификатора для выполнения соответствующих вызовов внутреннего API для разрешения фактического URL-адреса ресурса и установки для него значения MediaInfo.contentUrl.
Ресивер также будет выполнять такие задачи, как получение лицензии DRM или вставка информации о рекламных паузах.
В следующем разделе мы собираемся расширить возможности вашего приемника, чтобы он мог делать что-то подобное. А пока нажмите значок Cast и выберите свое устройство, чтобы открыть ресивер.
Перейдите на вкладку «Загрузить медиафайл» и нажмите кнопку «Загрузить по содержимому». Ваш ресивер должен начать воспроизведение образца контента.
Итак, в стандартной комплектации Receiver SDK обрабатывает:
- Инициализация сеанса трансляции
- Обработка входящих запросов
LOAD
от отправителей, содержащих игровые ресурсы. - Предоставьте базовый пользовательский интерфейс проигрывателя, готовый к отображению на большом экране.
Не стесняйтесь изучить инструмент CaC и его код, прежде чем перейти к следующему разделу, где мы собираемся расширить наш приемник, чтобы он мог взаимодействовать с простым примером API для выполнения входящих запросов LOAD
от отправителей.
9. Интеграция с внешним API
В соответствии с тем, как большинство разработчиков взаимодействуют со своими приемниками Cast в реальных приложениях, мы собираемся модифицировать наш приемник для обработки запросов LOAD
, которые ссылаются на предполагаемый медиаконтент по его ключу API вместо отправки URL-адреса воспроизводимого ресурса.
Приложения обычно делают это, потому что:
- Отправитель может не знать URL-адрес контента.
- Приложение Cast предназначено для обработки аутентификации, другой бизнес-логики или вызовов API непосредственно на получателе.
Эта функциональность в основном реализована в методе PlayerManager
setMessageInterceptor()
. Это позволяет перехватывать входящие сообщения по типу и изменять их до того, как они достигнут внутреннего обработчика сообщений 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
объект элементов управления пользовательского интерфейса для интеллектуальных дисплеев будет отображаться, как показано в примере ниже.
-
--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
, макет элемента управления по умолчанию будет отображаться, как показано ниже:
Когда значение supportMediaCommands равно 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.title
-
BrowseContent.items
Соотношение сторон
Используйте targetAspectRatio property
, чтобы выбрать наилучшее соотношение сторон для ваших изображений. SDK CAF Receiver SDK поддерживает три соотношения сторон: SQUARE_1_TO_1
, PORTRAIT_2_TO_3
, LANDSCAPE_16_TO_9
.
ОбзорЭлемент
Используйте 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
, чтобы удалить пользовательский интерфейс просмотра мультимедиа.
12. Отладка приложений-приемников
Пакет Cast Receiver SDK предоставляет разработчикам еще один вариант простой отладки приложений-приемников с помощью API CastDebugLogger и сопутствующего инструмента управления и контроля (CaC) для сбора журналов.
Инициализация
Чтобы включить API, добавьте исходный сценарий CastDebugLogger
в файл index.html. Источник должен быть объявлен в теге <head> после объявления Cast Receiver SDK.
<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
}
Сообщения журнала и пользовательские теги
API CastDebugLogger позволяет создавать сообщения журнала, которые отображаются на наложении отладки получателя разными цветами. Доступны следующие методы журналирования, перечисленные в порядке от высшего к низшему приоритету:
-
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.
Более подробную информацию см. в руководстве разработчика веб-приемника .
1. Обзор
В этой лаборатории кода вы узнаете, как создать приложение Custom Web Receiver для воспроизведения контента на устройствах с поддержкой Cast .
Что такое Google Cast?
Google Cast позволяет пользователям транслировать контент с мобильного устройства на телевизор. Затем пользователи могут использовать свое мобильное устройство или браузер Chrome на настольном компьютере в качестве пульта дистанционного управления для воспроизведения мультимедиа на телевизоре.
Google Cast SDK позволяет вашему приложению управлять устройствами с поддержкой Google Cast (например, телевизором или аудиосистемой). Cast SDK предоставляет необходимые компоненты пользовательского интерфейса на основе контрольного списка Google Cast Design .
Контрольный список 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 или ngrok .
Запустить сервер
После того, как вы настроите выбранную вами службу, перейдите к app-start
и запустите свой сервер.
Запишите URL-адрес вашего размещенного приемника. Вы будете использовать его в следующем разделе.
4. Зарегистрируйте приложение в консоли разработчика Cast.
Вам необходимо зарегистрировать свое приложение , чтобы иметь возможность запускать собственный приемник, встроенный в эту кодовую лабораторию, на устройствах 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
.
Дизайн приложения
Приложение приемника инициализирует сеанс актеров и будет стоять до тех пор, пока не появится запрос на загрузку (другими словами, команда воспроизвести кусок носителя) от отправителя не появится.
Приложение состоит из одного основного представления, определенного в index.html
, и один файл JavaScript с именем js/receiver.js
содержащий всю логику, чтобы заставить наш получатель работать.
index.html
Этот HTML -файл будет содержать пользовательский интерфейс для нашего приложения приемника. На данный момент это пусто, и мы будем добавлять к нему во всей лаборатории кода.
приемник
Этот скрипт будет управлять всей логикой для нашего приложения приемника. Прямо сейчас это просто пустой файл, но мы собираемся превратить его в полностью функционирующий литой приемник с несколькими строками кода в следующем разделе.
7. базовый актерский приемник
Базовый актерский приемник инициализирует актеров при запуске. Это необходимо, чтобы сообщить всем приложениям подключенных отправителей, что поднятие получателя было успешным. Кроме того, новый 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
, вашу основную точку входа на весь приемник SDK - Хранив ссылку на
PlayerManager
, воспроизведение обработки объектов и предоставление вам всех крючков, необходимых для подключения собственной собственной логики - Инициализация SDK, вызывая
start()
наCastReceiverContext
Добавьте следующее в js/receiver.js
.
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
context.start();
8. Casting "Basic" видеоконтента
Для целей этого CodeLab используйте инструмент CAC, чтобы попробовать свой новый приемник.
Укажите свой веб -браузер на инструмент команды и управления (CAC) .
Обязательно замените свой собственный идентификатор приложения , как зарегистрировано ранее в поле, и нажмите «Установить идентификатор приложения». Это дает инструмент использовать ваш приемник при запуске актеров.
Кастинг СМИ
На высоком уровне, чтобы воспроизвести носитель на листовом устройстве, должно произойти следующее:
- Отправитель создает объект
MediaInfo
JSON
из актеров SDK, который моделирует медиа -элемент. - Отправитель подключается к устройству CAST для запуска приложения приемника.
- Получатель загружает объект
MediaInfo
через запросLOAD
чтобы воспроизводить контент. - Приемник контролирует и отслеживает статус СМИ.
- Отправитель отправляет команды воспроизведения получателю для управления воспроизведением на основе взаимодействия с пользователем с приложением отправителя.
В этой первой основной попытке мы собираемся заполнить MediaInfo
с помощью URL -адреса игрового актива (сохраненный в MediaInfo.contentUrl
).
Отправитель в реальном мире использует идентификатор медиа, специфичный для приложения, в MediaInfo.contentId
. Получатель использует contentId
в качестве идентификатора для выполнения соответствующих бэкэнд -вызовов для разрешения фактического URL -адреса актива и установить его на MediaInfo.contentUrl.
Получатель также будет выполнять такие задачи, как приобретение лицензий DRM или инъекция информации о разрывах рекламы.
Мы собираемся продлить ваш приемник, чтобы сделать что -то подобное в следующем разделе. На данный момент нажмите на значок актера и выберите свое устройство, чтобы открыть приемник.
Перейдите на вкладку «Загрузить мультимедиа» и нажмите кнопку «Загрузить контент». Ваш приемник должен начать воспроизводить выборку содержимого.
Итак, за рубежом SDK-получателя:
- Инициализация сессии
- Обработка входящих запросов
LOAD
от отправителей, которые содержат воспроизводимые активы - Предоставьте базовый пользовательский интерфейс Player, готовый к отображению на большом экране.
Не стесняйтесь исследовать инструмент CAC и его код, прежде чем перейти к следующему разделу, где мы собираемся расширить наш приемник, чтобы поговорить с простым образцом API, чтобы выполнить входящие запросы LOAD
от отправителей.
9. Интегрируйте с внешним API
В соответствии с тем, как большинство разработчиков взаимодействуют со своими актерами в реальных приложениях, мы собираемся изменить наш приемник для обработки запросов LOAD
, которые ссылаются на предполагаемый медиа-контент по его ключу API вместо того, чтобы отправлять URL-адрес игры.
Приложения обычно делают это, потому что:
- Отправитель может не знать URL контента.
- Приложение CAST предназначено для обработки аутентификации, другой бизнес -логики или вызовов API непосредственно на приемнике.
Эта функциональность в основном реализована в методе PlayerManager
setMessageInterceptor()
. Это позволяет перехватить входящие сообщения по типу и изменять их до того, как они достигнут внутреннего обработчика 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
.
Перехватить запрос на загрузку
На этом этапе мы будем создавать перехватчик загрузки с функцией, которая делает запрос XHR
в размещенном файле JSON
. Как только файл JSON
будет получен, мы проанализируем контент и установим метаданные. В следующих разделах мы будем настраивать параметры MediaInformation
, чтобы указать тип контента.
Добавьте следующий код в свой файл js/receiver.js
, непосредственно перед Call to 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 Content
Теперь, когда мы подготовили перехватчик нагрузки, мы указам тип содержимого в приемник. Эта информация предоставит приемнику URL -адрес Master Playlist и тип Stream Mime. Добавьте следующий код в файл js/receiver.js в перспективе перехватчика LOAD
Promise()
:
...
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 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. Оптимизация для интеллектуальных дисплеев
Smart Displays-это устройства с функциональностью сенсорной функции, которые позволяют приложениям приемника поддерживать элементы управления с поддержкой.
В этом разделе объясняется, как оптимизировать приложение для получателя при запуске на Smart Displays, и как настроить элементы управления игроком.
Доступ к управлению пользовательским интерфейсом
Объект управления пользовательским интерфейсом для интеллектуальных дисплеев можно получить с помощью 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
объект управления пользовательским интерфейсом для интеллектуальных дисплеев будет отображаться, как в примере ниже.
-
--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
Обновление поддерживаемых медиа -команд
Объект управления пользовательским интерфейсом также определяет, отображается ли ControlsButton
или не основан на MediaStatus.supportedMediaCommands
.
Когда значение supportedMediaCommands
равно ALL_BASIC_MEDIA
, макет управления по умолчанию будет отображаться, как показано ниже:
Когда значение supportedMediaCommands
равна ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT
, макет управления по умолчанию отобразится, как ниже:
Когда значение поддерживаемых средних маммандов равна 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 Spearse - это функция приемника CAF, которая позволяет пользователям изучать дополнительный контент на сенсорных устройствах. Чтобы реализовать это, вы будете использовать PlayerDataBinder
для установки пользовательского интерфейса BrowseContent
. Затем вы можете заполнить его BrowseItems
на основе контента, который вы хотите отобразить.
Browsecontent
Ниже приведен пример пользовательского интерфейса BrowseContent
и его свойства:
-
BrowseContent.title
-
BrowseContent.items
Соотношение сторон
Используйте targetAspectRatio property
, чтобы выбрать наилучшее соотношение сторон для ваших активов изображения. Три соотношения сторон поддерживаются приемником CAF SDK: SQUARE_1_TO_1
, PORTRAIT_2_TO_3
, LANDSCAPE_16_TO_9
.
Rowseitem
Используйте BrowseItem
, чтобы отобразить заголовок, подзаголовок, продолжительность и изображение для каждого элемента:
-
BrowseItem.image
-
BrowseItem.duration
-
BrowseItem.title
-
BrowseItem.subtitle
Установить данные об просмотре СМИ
Вы можете предоставить список медиа -контента для просмотра, позвонив в setBrowseContent
. Добавьте следующий код в свой файл js/receiver.js
под вашим playerDataBinder
и в вашем слушателе MEDIA_CHANGED
события, чтобы установить элементы просмотра с названием «Up Next».
// 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);
});
Нажатие на предмет Media Browse запустит перехватчик LOAD
. Добавьте следующий код в свой перехватчик LOAD
, чтобы отобразить request.media.contentId
в request.media.entity
из Media Exeme ise:
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 предоставляет разработчикам еще один вариант для легко отладка приложений приемника, используя API Castdebuglogger и инструмент Companion Command и Control (CAC) для захвата журналов.
Инициализация
Чтобы включить API, добавьте сценарий источника CastDebugLogger
в свой файл index.html. Источник должен быть объявлен в теге <Head> после объявления SDK -приемника.
<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 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
}
Сообщения журнала и пользовательские теги
API API Castdebuglogger позволяет создавать сообщения журналов, которые появляются в наложении отладки приемника с разными цветами. Доступны следующие методы журнала, перечисленные по порядку от наименования до самого низкого приоритета:
-
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. Используйте 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.
Для получения более подробной информации см. Руководство по разработчику веб -приемника .