На этой странице содержатся фрагменты кода и описания функций, доступных для пользовательского приложения Web Receiver.
- Элемент
cast-media-player, который представляет встроенный интерфейс проигрывателя, поставляемый с веб-приемником. - Специальный стиль, похожий на CSS, для элемента
cast-media-player, который позволяет оформлять различные элементы интерфейса, такие какbackground-image,splash-imageиfont-family. - Элемент скрипта для загрузки фреймворка веб-приемника.
- Код JavaScript для перехвата сообщений и обработки событий.
- Добавить в очередь для автовоспроизведения.
- Параметры для настройки воспроизведения.
- Параметры для настройки контекста веб-приемника.
- Параметры для настройки команд, поддерживаемых приложением веб-приемника.
- Вызов JavaScript для запуска веб-приложения получателя.
Конфигурация и параметры приложения
Настройте приложение
CastReceiverContext – это внешний класс, доступный разработчику. Он управляет загрузкой базовых библиотек и инициализацией Web Receiver SDK. SDK предоставляет API, которые позволяют разработчикам приложений настраивать SDK с помощью CastReceiverOptions.
Эти конфигурации оцениваются один раз при запуске приложения и передаются в SDK при установке необязательного параметра в вызове start.
В примере ниже показано, как переопределить режим работы по умолчанию для определения того, активно ли подключение отправителя. Если веб-приемник не может связаться с отправителем в течение maxInactivity сек., отправляется событие SENDER_DISCONNECTED. Указанная ниже конфигурация переопределяет это время ожидания. Это может быть полезно при отладке, поскольку не позволяет веб-приемнику закрывать сеанс удаленного отладчика Chrome, когда нет подключенных отправителей в состоянии IDLE.
const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);
Настройка проигрывателя
При загрузке контента Web Receiver SDK позволяет настраивать переменные воспроизведения, такие как информация DRM, конфигурации повторных попыток и обработчики запросов, с помощью cast.framework.PlaybackConfig.
Эта информация обрабатывается PlayerManager и оценивается при создании проигрывателей. Проигрыватели создаются каждый раз, когда в Web Receiver SDK передается новая загрузка. Изменения, внесенные в PlaybackConfig после создания проигрывателя, будут учтены при следующей загрузке контента. В SDK есть следующие методы для изменения PlaybackConfig:
CastReceiverOptions.playbackConfig, чтобы переопределить параметры конфигурации по умолчанию при инициализацииCastReceiverContext.PlayerManager.getPlaybackConfig(), чтобы получить текущую конфигурацию.PlayerManager.setPlaybackConfig(), чтобы переопределить текущую конфигурацию. Эта настройка применяется ко всем последующим загрузкам или до тех пор, пока она не будет переопределена снова.PlayerManager.setMediaPlaybackInfoHandler()для применения дополнительных конфигураций только к загружаемому мультимедийному объекту поверх текущих конфигураций. Обработчик вызывается непосредственно перед созданием проигрывателя. Изменения, внесенные здесь, не сохраняются и не включаются в запросы кgetPlaybackConfig(). Когда загружается следующий мультимедийный объект, этот обработчик вызывается снова.
В примере ниже показано, как задать PlaybackConfig при инициализации CastReceiverContext. Конфигурация переопределяет исходящие запросы на получение манифестов. Обработчик указывает, что запросы CORS Access-Control должны выполняться с использованием учетных данных, таких как файлы cookie или заголовки авторизации.
const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});
В примере ниже показано, как переопределить PlaybackConfig с помощью методов получения и задания, предоставляемых в PlayerManager. Эта настройка указывает проигрывателю возобновлять воспроизведение контента после загрузки одного сегмента.
const playerManager =
cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);
В примере ниже показано, как переопределить PlaybackConfig для определенного запроса на загрузку с помощью обработчика информации о воспроизведении медиаконтента. Обработчик вызывает метод getLicenseUrlForMedia, реализованный в приложении, чтобы получить licenseUrl из contentId текущего элемента.
playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
const mediaInformation = loadRequestData.media;
playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);
return playbackConfig;
});
Прослушиватель событий
Web Receiver SDK позволяет веб-приложению получателя обрабатывать события проигрывателя. Прослушиватель событий принимает параметр cast.framework.events.EventType (или массив таких параметров), который указывает, какие события должны активировать прослушиватель. Предварительно настроенные массивы cast.framework.events.EventType, которые могут быть полезны для отладки, можно найти в cast.framework.events.category.
Параметр события предоставляет дополнительную информацию о событии.
Например, если вы хотите узнать, когда транслируется изменение mediaStatus, вы можете использовать следующую логику для обработки события:
const playerManager =
cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
cast.framework.events.EventType.MEDIA_STATUS, (event) => {
// Write your own event handling code, for example
// using the event.mediaStatus value
});
Перехват сообщений
Web Receiver SDK позволяет приложению Web Receiver перехватывать сообщения и выполнять для них пользовательский код. Перехватчик сообщений принимает параметр cast.framework.messages.MessageType, который указывает, какой тип сообщения должен быть перехвачен.
Перехватчик должен возвращать измененный запрос или объект Promise, который разрешается с измененным значением запроса. Если возвращается значение null, обработчик сообщений по умолчанию не вызывается. Подробнее о загрузке медиаконтента…
Например, если вы хотите изменить данные запроса на загрузку, вы можете использовать следующую логику, чтобы перехватить и изменить его:
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, loadRequestData => {
const error = new cast.framework.messages.ErrorData(
cast.framework.messages.ErrorType.LOAD_FAILED);
if (!loadRequestData.media) {
error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
return error;
}
if (!loadRequestData.media.entity) {
return loadRequestData;
}
return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
loadRequestData.credentials)
.then(asset => {
if (!asset) {
throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
}
loadRequestData.media.contentUrl = asset.url;
loadRequestData.media.metadata = asset.metadata;
loadRequestData.media.tracks = asset.tracks;
return loadRequestData;
}).catch(reason => {
error.reason = reason; // cast.framework.messages.ErrorReason
return error;
});
});
context.start();
Обработка ошибок
Если в перехватчике сообщений возникают ошибки, веб-приложение получателя должно возвращать соответствующие значения cast.framework.messages.ErrorType и cast.framework.messages.ErrorReason.
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, loadRequestData => {
const error = new cast.framework.messages.ErrorData(
cast.framework.messages.ErrorType.LOAD_CANCELLED);
if (!loadRequestData.media) {
error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
return error;
}
...
return fetchAssetAndAuth(loadRequestData.media.entity,
loadRequestData.credentials)
.then(asset => {
...
return loadRequestData;
}).catch(reason => {
error.reason = reason; // cast.framework.messages.ErrorReason
return error;
});
});
Перехват сообщений и прослушиватель событий
Ниже перечислены основные различия между перехватом сообщений и прослушивателем событий.
- Прослушиватель событий не позволяет изменять данные запроса.
- Прослушиватель событий лучше всего использовать для запуска аналитики или специальной функции.
playerManager.addEventListener(cast.framework.events.category.CORE,
event => {
console.log(event);
});
- Перехват сообщений позволяет прослушивать сообщения, перехватывать их и изменять данные запроса.
- Перехват сообщений лучше всего использовать для обработки пользовательской логики в отношении данных запроса.
Загрузка медиафайлов
MediaInformation предоставляет множество свойств для загрузки медиаконтента в сообщении cast.framework.messages.MessageType.LOAD, включая entity, contentUrl и contentId.
entity– это рекомендуемое свойство для использования в реализации как для приложения-отправителя, так и для приложения-получателя. Свойство представляет собой URL ссылки на контент, который может быть плейлистом или медиаконтентом. Приложение должно проанализировать этот URL и заполнить хотя бы одно из двух других полей.- Элемент
contentUrlсоответствует URL, который проигрыватель будет использовать для загрузки контента. Например, этот URL может указывать на манифест DASH. - Свойство
contentIdможет быть URL воспроизводимого контента (как и свойствоcontentUrl) или уникальным идентификатором загружаемого контента или плейлиста. Если вы используете это свойство в качестве идентификатора, ваше приложение должно заполнить URL воспроизведения вcontentUrl.
Рекомендуется использовать entity для хранения реального идентификатора или ключевых параметров, а contentUrl – для URL медиаконтента. Пример показан в следующем фрагменте, где entity присутствует в запросе LOAD и извлекается воспроизводимый contentUrl:
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, loadRequestData => {
...
if (!loadRequestData.media.entity) {
// Copy the value from contentId for legacy reasons if needed
loadRequestData.media.entity = loadRequestData.media.contentId;
}
return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
loadRequestData.credentials)
.then(asset => {
loadRequestData.media.contentUrl = asset.url;
...
return loadRequestData;
});
});
Возможности устройства
Метод getDeviceCapabilities предоставляет информацию о подключенном устройстве Cast и подключенном к нему видео- или аудиоустройстве. Метод getDeviceCapabilities предоставляет информацию о поддержке Google Ассистента, Bluetooth, а также подключенных дисплеев и аудиоустройств.
Этот метод возвращает объект, который можно запросить, передав одно из указанных перечислений, чтобы получить возможность устройства для этого перечисления. Перечисления определены в cast.framework.system.DeviceCapabilities.
В этом примере проверяется, может ли веб-приемник воспроизводить HDR и DolbyVision (DV) с помощью ключей IS_HDR_SUPPORTED и IS_DV_SUPPORTED соответственно.
const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
const deviceCapabilities = context.getDeviceCapabilities();
if (deviceCapabilities &&
deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
// Write your own event handling code, for example
// using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
}
if (deviceCapabilities &&
deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
// Write your own event handling code, for example
// using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
}
});
context.start();
Обработка действий пользователя
Пользователь может взаимодействовать с вашим приложением Web Receiver через приложения-отправители (Web, Android и iOS), голосовые команды на устройствах с поддержкой Ассистента, сенсорное управление на умных дисплеях и пульты дистанционного управления на устройствах Android TV. Cast SDK предоставляет различные API, позволяющие приложению веб-приемника обрабатывать эти взаимодействия, обновлять пользовательский интерфейс приложения через состояния действий пользователя и, при необходимости, отправлять изменения для обновления любых серверных служб.
Поддерживаемые команды для управления медиаконтентом
Состояния элементов управления пользовательского интерфейса определяются MediaStatus.supportedMediaCommands для расширенных контроллеров отправителей iOS и Android, приложений приемника и дистанционного управления, работающих на сенсорных устройствах, и приложений приемника на устройствах Android TV. Когда в свойстве включен определенный побитовый оператор Command, активируются кнопки, связанные с этим действием. Если значение не задано, кнопка отключена. Эти значения можно изменить в веб-приемнике следующим образом:
- Использование
PlayerManager.setSupportedMediaCommandsдля настройки определенногоCommands - Добавление новой команды с помощью
addSupportedMediaCommands - Удаление существующей команды с помощью
removeSupportedMediaCommands.
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
cast.framework.messages.Command.PAUSE);
Когда получатель подготовит обновленный файл MediaStatus, он будет содержать изменения в свойстве supportedMediaCommands. Когда статус транслируется, подключенные приложения-отправители соответствующим образом обновляют кнопки в своем пользовательском интерфейсе.
Подробную информацию о поддерживаемых командах и сенсорных устройствах можно найти в руководстве по Accessing UI controls.
Управление состояниями действий пользователя
Пользователи могут управлять воспроизведением контента и свойствами воспроизводимого элемента, взаимодействуя с интерфейсом или отправляя голосовые команды. Запросы, управляющие воспроизведением, обрабатываются SDK автоматически. Запросы, которые изменяют свойства воспроизводимого контента, например команда LIKE, должны обрабатываться принимающим приложением. В SDK есть ряд API для обработки таких запросов. Чтобы выполнить эти запросы, необходимо сделать следующее:
- Задайте
MediaInformationuserActionStatesс настройками пользователя при загрузке мультимедийного объекта. - Перехватывать сообщения
USER_ACTIONи определять запрошенное действие. - Чтобы обновить интерфейс, обновите
MediaInformationUserActionState.
В следующем фрагменте кода показано, как перехватить запрос LOAD и заполнить поле MediaInformation объекта LoadRequestData. В этом случае пользователю нравится
загружаемый контент.
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
const userActionLike = new cast.framework.messages.UserActionState(
cast.framework.messages.UserAction.LIKE);
loadRequestData.media.userActionStates = [userActionLike];
return loadRequestData;
});
В следующем фрагменте кода показано, как перехватить сообщение USER_ACTION и вызвать серверную часть с запрошенным изменением. Затем он вызывает метод, который обновляет UserActionState на приемнике.
playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
(userActionRequestData) => {
// Obtain the media information of the current content to associate the action to.
let mediaInfo = playerManager.getMediaInformation();
// If there is no media info return an error and ignore the request.
if (!mediaInfo) {
console.error('Not playing media, user action is not supported');
return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
}
// Reach out to backend services to store user action modifications. See sample below.
return sendUserAction(userActionRequestData, mediaInfo)
// Upon response from the backend, update the client's UserActionState.
.then(backendResponse => updateUserActionStates(backendResponse))
// If any errors occurred in the backend return them to the cast receiver.
.catch((error) => {
console.error(error);
return error;
});
});
В следующем фрагменте кода имитируется вызов бэкенд-службы. Функция проверяет UserActionRequestData, чтобы определить тип изменения, запрошенного пользователем, и выполняет сетевой вызов, только если действие поддерживается серверной частью.
function sendUserAction(userActionRequestData, mediaInfo) {
return new Promise((resolve, reject) => {
switch (userActionRequestData.userAction) {
// Handle user action changes supported by the backend.
case cast.framework.messages.UserAction.LIKE:
case cast.framework.messages.UserAction.DISLIKE:
case cast.framework.messages.UserAction.FOLLOW:
case cast.framework.messages.UserAction.UNFOLLOW:
case cast.framework.messages.UserAction.FLAG:
case cast.framework.messages.UserAction.SKIP_AD:
let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
setTimeout(() => {resolve(backendResponse)}, 1000);
break;
// Reject all other user action changes.
default:
reject(
new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
}
});
}
В следующем фрагменте кода показано, как добавить или удалить UserActionState из MediaInformation с помощью UserActionRequestData. Обновление UserActionState MediaInformation изменяет состояние кнопки, связанной с запрошенным действием. Это изменение отражено в интерфейсе управления умным дисплеем, приложении для дистанционного управления и интерфейсе Android TV. Оно также передается в исходящих сообщениях MediaStatus, чтобы обновить интерфейс расширенного контроллера для отправителей iOS и Android.
function updateUserActionStates(backendResponse) {
// Unwrap the backend response.
let mediaInfo = backendResponse.mediaInfo;
let userActionRequestData = backendResponse.userActionRequestData;
// If the current item playing has changed, don't update the UserActionState for the current item.
if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
return;
}
// Check for existing userActionStates in the MediaInformation.
// If none, initialize a new array to populate states with.
let userActionStates = mediaInfo.userActionStates || [];
// Locate the index of the UserActionState that will be updated in the userActionStates array.
let index = userActionStates.findIndex((currUserActionState) => {
return currUserActionState.userAction == userActionRequestData.userAction;
});
if (userActionRequestData.clear) {
// Remove the user action state from the array if cleared.
if (index >= 0) {
userActionStates.splice(index, 1);
}
else {
console.warn("Could not find UserActionState to remove in MediaInformation");
}
} else {
// Add the UserActionState to the array if enabled.
userActionStates.push(
new cast.framework.messages.UserActionState(userActionRequestData.userAction));
}
// Update the UserActionState array and set the new MediaInformation
mediaInfo.userActionStates = userActionStates;
playerManager.setMediaInformation(mediaInfo, true);
return;
}
Голосовые команды
Следующие медиа-команды в настоящее время поддерживаются в Web Receiver SDK для устройств с поддержкой Ассистента. Реализации этих команд по умолчанию находятся в cast.framework.PlayerManager.
| Команда | Описание |
|---|---|
| Воспроизвести | Начать или возобновить воспроизведение. |
| Приостановка комментариев | Приостановить воспроизведение контента. |
| Назад | Перейти к предыдущему объекту в очереди воспроизведения. |
| Далее | Перейти к следующему мультимедийному объекту в очереди воспроизведения. |
| Остановить | Остановить воспроизведение. |
| Не повторять | Отключить повтор мультимедийных объектов в очереди после воспроизведения последнего объекта. |
| Повторять один трек | Повторять воспроизведение текущего медиаконтента. |
| Повторять все | Повторять все элементы в очереди после воспроизведения последнего элемента. |
| Повторить все и перемешать | После воспроизведения последнего элемента в очереди перемешать очередь и повторить все элементы в очереди. |
| Перемешать | Перемешать мультимедийные объекты в очереди воспроизведения. |
| Включение и отключение субтитров | Включить или отключить субтитры для медиаконтента. Включить или отключить функцию можно для каждого языка отдельно. |
| Перемотка к абсолютному времени | Переход к указанному абсолютному времени. |
| Перейти к времени относительно текущего времени | Переход вперед или назад на указанный период времени относительно текущего времени воспроизведения. |
| Сыграть ещё раз | Перезапустить воспроизведение текущего медиаконтента или включить последний воспроизведенный мультимедийный объект, если сейчас ничего не воспроизводится. |
| Как задать скорость воспроизведения | Изменять скорость воспроизведения медиаконтента. Это должно обрабатываться по умолчанию. Чтобы переопределить входящие запросы тарифов, можно использовать перехватчик сообщений SET_PLAYBACK_RATE. |
Поддерживаемые голосовые команды для управления медиаконтентом
Чтобы голосовая команда не запускала команду мультимедиа на устройстве с поддержкой Ассистента, сначала нужно задать поддерживаемые команды мультимедиа, которые вы планируете использовать. Затем необходимо применить эти команды, включив свойство CastReceiverOptions.enforceSupportedCommands. Интерфейс на устройствах с сенсорным экраном и отправителях Cast SDK будет изменен в соответствии с этими конфигурациями. Если параметр не включен, входящие голосовые команды будут выполняться.
Например, если вы разрешаете PAUSE в приложениях-отправителях и на устройствах с сенсорным экраном, то должны также настроить приемник, чтобы отразить эти настройки. Если правило настроено, все входящие голосовые команды, не включенные в список поддерживаемых, будут отклоняться.
В примере ниже мы указываем CastReceiverOptions при запуске CastReceiverContext. Мы добавили поддержку команды PAUSE и сделали так, чтобы проигрыватель поддерживал только ее. Теперь, если голосовая команда запрашивает другую операцию, например SEEK, она будет отклонена. Пользователь получит уведомление о том, что команда пока не поддерживается.
const context = cast.framework.CastReceiverContext.getInstance();
context.start({
enforceSupportedCommands: true,
supportedCommands: cast.framework.messages.Command.PAUSE
});
Вы можете применить отдельную логику для каждой команды, которую хотите ограничить. Удалите флаг enforceSupportedCommands и перехватывайте входящие сообщения для каждой команды, которую хотите ограничить. Здесь мы перехватываем запрос,
предоставленный SDK, чтобы команды SEEK, отправленные на устройства с поддержкой Ассистента,
не запускали поиск в вашем приложении веб-приемника.
Если приложение не поддерживает команду, возвращайте соответствующую причину ошибки, например NOT_SUPPORTED.
playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
seekData => {
// Block seeking if the SEEK supported media command is disabled
if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
.INVALID_REQUEST);
e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
return e;
}
return seekData;
});
Переход в фоновый режим из-за голосовой активности
Если платформа Cast приглушает звук приложения из-за действий Ассистента, например когда он слушает пользователя или отвечает ему, то в начале действия веб-приемнику отправляется сообщение FocusState со значением NOT_IN_FOCUS. Когда занятие закончится, будет отправлено ещё одно сообщение с IN_FOCUS.
В зависимости от приложения и воспроизводимого контента вы можете приостанавливать воспроизведение, когда FocusState переходит в состояние NOT_IN_FOCUS, перехватывая сообщение типа FOCUS_STATE.
Например, если Ассистент отвечает на запрос пользователя, воспроизведение аудиокниги должно приостанавливаться.
playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
focusStateRequestData => {
// Pause content when the app is out of focus. Resume when focus is restored.
if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
playerManager.pause();
} else {
playerManager.play();
}
return focusStateRequestData;
});
Язык субтитров, заданный голосом
Если пользователь не указывает язык субтитров, они будут на том же языке, на котором была произнесена команда.
В таких случаях параметр isSuggestedLanguage входящего сообщения указывает, был ли связанный язык предложен или явно запрошен пользователем.
Например, для команды "Окей, Google, включи субтитры" isSuggestedLanguage устанавливается на true, поскольку язык определяется по языку, на котором была произнесена команда. Если язык указан явно, например "Окей, Google, включи субтитры на английском", для параметра isSuggestedLanguage задается значение false.
Метаданные и подбор голосов
Хотя голосовые команды по умолчанию обрабатываются веб-приемником, вы должны убедиться, что метаданные вашего контента полны и точны. Это гарантирует, что голосовые команды будут правильно обрабатываться Ассистентом, а метаданные – корректно отображаться в новых типах интерфейсов, таких как приложение Google Home и умные дисплеи, например Google Home Hub.
Перенос трансляции
Сохранение состояния сеанса – это основа переноса трансляции, когда пользователи могут перемещать существующие аудио- и видеопотоки между устройствами с помощью голосовых команд, приложения Google Home или умных дисплеев. Воспроизведение контента прекращается на одном устройстве (источнике) и продолжается на другом (целевом). Любое устройство Cast с последней версией встроенного ПО может служить источником или получателем при переносе трансляции.
Последовательность событий при переносе трансляции:
- На исходном устройстве:
- Воспроизведение контента прекращается.
- Веб-приемник получает команду на сохранение текущего состояния медиа.
- Веб-приложение получателя закрыто.
- На целевом устройстве:
- Приложение веб-приемника загружено.
- Веб-приемник получает команду восстановить сохраненное состояние медиаконтента.
- Воспроизведение возобновится.
Элементы состояния медиаконтента:
- Определенная позиция или временная метка в песне, видео или мультимедийном объекте.
- место трека в очереди воспроизведения (например, в плейлисте или на радиостанции исполнителя).
- Аутентифицированный пользователь.
- Состояние воспроизведения (например, воспроизводится или приостановлено).
Как включить перенос трансляции
Чтобы реализовать перенос трансляции для веб-приемника:
- Обновите
supportedMediaCommandsс помощью командыSTREAM_TRANSFER:playerManager.addSupportedMediaCommands( cast.framework.messages.Command.STREAM_TRANSFER, true);
- При необходимости переопределите перехватчики сообщений
SESSION_STATEиRESUME_SESSION, как описано в разделе Сохранение состояния сеанса. Переопределяйте их, только если в снимке сеанса нужно сохранить пользовательские данные. В противном случае перенос трансляции будет поддерживаться реализацией по умолчанию для сохранения состояний сеанса.
Сохранение состояния сеанса
В Web Receiver SDK есть стандартная реализация для приложений веб-приемника, которая позволяет сохранять состояния сеансов. Для этого создается снимок текущего статуса медиаконтента, который преобразуется в запрос на загрузку, а затем сеанс возобновляется с помощью этого запроса.
При необходимости запрос на загрузку, созданный веб-приемником, можно переопределить в перехватчике сообщений SESSION_STATE. Если вы хотите добавить в запрос на загрузку собственные данные, рекомендуем поместить их в loadRequestData.customData.
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.SESSION_STATE,
function (sessionState) {
// Override sessionState.loadRequestData if needed.
const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
sessionState.loadRequestData.credentials = newCredentials;
// Add custom data if needed.
sessionState.loadRequestData.customData = {
'membership': 'PREMIUM'
};
return sessionState;
});
Специальные данные можно получить из loadRequestData.customData в перехватчике сообщений RESUME_SESSION.
let cred_ = null;
let membership_ = null;
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.RESUME_SESSION,
function (resumeSessionRequest) {
let sessionState = resumeSessionRequest.sessionState;
// Modify sessionState.loadRequestData if needed.
cred_ = sessionState.loadRequestData.credentials;
// Retrieve custom data.
membership_ = sessionState.loadRequestData.customData.membership;
return resumeSessionRequest;
});
Предзагрузка контента
Веб-приемник поддерживает предзагрузку мультимедийных объектов, следующих за текущим воспроизводимым объектом в очереди.
При предварительной загрузке скачивается несколько сегментов предстоящих объектов. Для этого используется значение preloadTime в объекте QueueItem (по умолчанию 20 секунд). Время указывается в секундах относительно конца воспроизводимого в данный момент объекта . Допустимы только положительные значения. Например, если указано значение 10 секунд, то этот объект будет предварительно загружен за 10 секунд до окончания предыдущего. Если время до предварительной загрузки больше, чем время, оставшееся до конца текущего элемента, предварительная загрузка начнется как можно скорее. Если для параметра preload задано очень большое значение, то при воспроизведении текущего элемента будет выполняться предзагрузка следующего. Однако мы оставляем настройку и выбор этого параметра за разработчиком, поскольку это значение может повлиять на пропускную способность и производительность потоковой передачи текущего воспроизводимого элемента.
По умолчанию предзагрузка работает для контента, передаваемого по протоколам HLS, DASH и Smooth Streaming.
Обычные видеофайлы MP4 и аудиофайлы MP3 не будут предварительно загружаться, поскольку устройства Cast поддерживают только один медиаэлемент и не могут использоваться для предварительной загрузки, пока воспроизводится существующий элемент контента.
Специальные сообщения
Обмен сообщениями – ключевой метод взаимодействия для приложений Web Receiver.
Отправитель передает сообщения веб-получателю, используя API отправителя для платформы, на которой он работает (Android, iOS, веб). Объект события (который является проявлением сообщения), передаваемый прослушивателям событий, имеет элемент данных (event.data), в котором данные принимают свойства определенного типа события.
Приложение веб-приемника может прослушивать сообщения в указанном пространстве имен. В результате этого приложение Web Receiver поддерживает протокол пространства имен. После этого подключенные отправители, желающие обмениваться данными в этом пространстве имен, должны использовать соответствующий протокол.
Все пространства имен определяются строкой и должны начинаться с "urn:x-cast:", за которым следует любая строка. Пример: urn:x-cast:com.example.cast.mynamespace.
Ниже приведен фрагмент кода, который позволяет веб-приемнику получать специальные сообщения от подключенных отправителей.
const context = cast.framework.CastReceiverContext.getInstance();
const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
// handle customEvent.
});
context.start();
Аналогичным образом веб-приложения-приемники могут информировать отправителей о своем состоянии, отправляя им сообщения. Веб-приложение получателя может отправлять сообщения с помощью sendCustomMessage(namespace, senderId, message) в CastReceiverContext.
Веб-приемник может отправлять сообщения отдельному отправителю либо в ответ на полученное сообщение, либо в связи с изменением состояния приложения. Помимо обмена сообщениями между двумя устройствами (с ограничением в 64 КБ), веб-приемник может также транслировать сообщения всем подключенным отправителям.
Cast для аудиоустройств
Информацию о воспроизведении только аудио можно найти в руководстве по Google Cast для аудиоустройств.
Android TV
В этом разделе рассказывается, как веб-приемник Google использует входные данные для воспроизведения и совместимости с Android TV.
Интеграция приложения с пультом ДУ
Google Web Receiver, работающий на устройстве Android TV, преобразует входные данные от элементов управления устройства (например, от пульта дистанционного управления) в сообщения о воспроизведении медиаконтента, определенные для пространства имен urn:x-cast:com.google.cast.media, как описано в разделе Сообщения о воспроизведении медиаконтента. Чтобы пользователи могли управлять воспроизведением медиаконтента в приложении с помощью элементов управления Android TV, ваше приложение должно поддерживать эти сообщения.
Рекомендации по обеспечению совместимости с Android TV
Ниже приведены рекомендации и распространенные ошибки, которых следует избегать, чтобы обеспечить совместимость приложения с Android TV.
- Обратите внимание, что строка агента пользователя содержит как Android, так и CrKey. Некоторые сайты могут перенаправлять на мобильную версию, поскольку они обнаруживают метку Android. Не думайте, что слово Android в строке агента пользователя всегда указывает на мобильное устройство.
- Медиастек Android может использовать прозрачный GZIP для получения данных. Убедитесь, что ваши медиаданные могут отвечать на
Accept-Encoding: gzip. - События мультимедиа HTML5 на Android TV могут запускаться в другое время, чем на Chromecast, что может выявить проблемы, которые были скрыты на Chromecast.
- При обновлении медиаконтента используйте связанные с ним события, которые запускаются элементами
<audio>/<video>, напримерtimeupdate,pauseиwaiting. Не используйте события, связанные с сетью, напримерprogress,suspendиstalled, поскольку они зависят от платформы. Подробнее об обработке медиасобытий в приемнике… - При настройке сертификатов HTTPS для сайта-приемника обязательно включите промежуточные сертификаты ЦС. Чтобы проверить, так ли это, перейдите на страницу тестирования SSL Qualsys. Если доверенный путь сертификации для вашего сайта включает сертификат ЦС с пометкой "extra download" (дополнительное скачивание), то сайт может не загружаться на платформах Android.
- Chromecast показывает страницу приемника в разрешении 720p, а другие платформы Cast, включая Android TV, могут показывать ее в разрешении до 1080p. Убедитесь, что страница приемника корректно масштабируется при разных разрешениях.