На этой странице содержатся фрагменты кода и описания функций, доступных для приложения Custom Web Receiver.
- Элемент
cast-media-player
, представляющий встроенный пользовательский интерфейс проигрывателя, предоставляемый Web Receiver. - Пользовательский стиль в стиле CSS для элемента
cast-media-player
позволяющий стилизовать различные элементы пользовательского интерфейса, такие какbackground-image
,splash-image
иfont-family
. - Элемент скрипта для загрузки фреймворка Web Receiver.
- Код JavaScript для перехвата сообщений и обработки событий.
- Очередь на автовоспроизведение.
- Параметры настройки воспроизведения.
- Параметры настройки контекста веб-приемника.
- Параметры настройки команд, поддерживаемых приложением Web Receiver.
- Вызов JavaScript для запуска приложения Web Receiver.
Конфигурация и параметры приложения
Настройте приложение
CastReceiverContext
— это внешний класс, доступный разработчику. Он управляет загрузкой базовых библиотек и отвечает за инициализацию Web Receiver SDK. SDK предоставляет API, позволяющие разработчикам приложений настраивать SDK через CastReceiverOptions
. Эти конфигурации оцениваются один раз при запуске приложения и передаются в SDK при установке необязательного параметра в вызове start
.
В примере ниже показано, как переопределить поведение по умолчанию для определения наличия активного соединения с отправителем. Если веб-приёмник не может связаться с отправителем в течение maxInactivity
секунд, отправляется событие SENDER_DISCONNECTED
. Приведённая ниже конфигурация переопределяет это время ожидания. Это может быть полезно при отладке, поскольку не позволяет приложению веб-приёмника закрыть сеанс Chrome Remote Debugger, если нет ни одного подключённого отправителя в состоянии 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
с помощью методов getter и setter, предоставленных в 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 позволяет вашему приложению Web Receiver обрабатывать события проигрывателя. Обработчик событий принимает параметр cast.framework.events.EventType
(или массив этих параметров), который определяет события, которые должны активировать обработчик. Предварительно настроенные массивы cast.framework.events.EventType
, полезные для отладки, можно найти в cast.framework.events.category
. Параметр event предоставляет дополнительную информацию о событии.
Например, если вы хотите узнать, когда транслируется изменение 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();
Обработка ошибок
При возникновении ошибок в перехватчике сообщений ваше приложение Web Receiver должно возвращать соответствующие 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
, а извлекается playable 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
.
В этом примере проверяется, может ли устройство Web Receiver воспроизводить 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 через приложения-отправители (веб-приложения, Android и iOS), голосовые команды на устройствах с поддержкой Assistant, сенсорное управление на смарт-дисплеях и пульты дистанционного управления на устройствах Android TV. Cast SDK предоставляет различные API, позволяющие приложению Web Receiver обрабатывать эти взаимодействия, обновлять пользовательский интерфейс приложения с помощью состояний действий пользователя и, при необходимости, отправлять изменения для обновления любых внутренних служб.
Поддерживаемые медиа-команды
Состояния элементов управления пользовательского интерфейса определяются 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 для обработки таких запросов. Для поддержки этих запросов необходимо выполнить следующие действия:
- При загрузке медиа-элемента задайте
MediaInformation
userActionStates
в соответствии с предпочтениями пользователя. - Перехватывайте сообщения
USER_ACTION
и определяйте запрошенное действие. - Обновите
MediaInformation
UserActionState
, чтобы обновить пользовательский интерфейс.
Следующий фрагмент перехватывает запрос 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));
}
});
}
Следующий фрагмент кода принимает UserActionRequestData
и добавляет или удаляет UserActionState
из MediaInformation
. Обновление 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 для устройств с поддержкой Assistant поддерживаются следующие медиа-команды. Реализации этих команд по умолчанию находятся в cast.framework.PlayerManager
.
Команда | Описание |
---|---|
Играть | Воспроизвести или возобновить воспроизведение с приостановленного состояния. |
Пауза | Приостановить текущее воспроизведение контента. |
Предыдущий | Перейти к предыдущему элементу мультимедиа в очереди мультимедиа. |
Следующий | Перейти к следующему элементу мультимедиа в очереди мультимедиа. |
Останавливаться | Остановите воспроизводимое в данный момент медиа-содержимое. |
Повторить нет | Отключить повторение элементов мультимедиа в очереди после завершения воспроизведения последнего элемента в очереди. |
Повторить сингл | Повторять текущий воспроизводимый медиафайл бесконечно. |
Повторить все | Повторить все элементы в очереди после воспроизведения последнего элемента в очереди. |
Повторить все и перемешать | Как только последний элемент в очереди завершит воспроизведение, перемешайте очередь и повторите воспроизведение всех элементов в очереди. |
Перемешать | Перемешивайте медиафайлы в очереди медиафайлов. |
Субтитры ВКЛ/ВЫКЛ | Включите/отключите субтитры для ваших медиафайлов. Включение/отключение также доступно для разных языков. |
Стремитесь к абсолютному времени | Переход к указанному абсолютному времени. |
Поиск времени относительно текущего времени | Переход вперед или назад на указанный период времени относительно текущего времени воспроизведения. |
Играть снова | Перезапустите текущий воспроизводимый медиафайл или воспроизведите последний воспроизведенный медиафайл, если в данный момент ничего не воспроизводится. |
Установить скорость воспроизведения | Изменяйте скорость воспроизведения медиафайлов. Это должно быть реализовано по умолчанию. Вы можете использовать перехватчик сообщений SET_PLAYBACK_RATE для переопределения входящих запросов скорости. |
Поддерживаемые голосовые медиа-команды
Чтобы голосовая команда не запускала медиа-команду на устройстве с поддержкой Google Assistant, необходимо сначала настроить поддерживаемые медиа-команды , которые вы планируете поддерживать. Затем необходимо принудительно включить эти команды, включив свойство 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
, отправленные устройствам с поддержкой Assistant, не запускали поиск в вашем приложении Web Receiver.
Для медиа-команд, которые ваше приложение не поддерживает, верните соответствующую причину ошибки, например 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 воспроизводит звук вашего приложения в фоновом режиме из-за активности Помощника, например, прослушивания речи пользователя или ответа, при запуске активности в приложение Web Receiver отправляется сообщение 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
входящего сообщения указывает, был ли соответствующий язык предложен или явно запрошен пользователем.
Например, для команды «OK Google, включи субтитры» isSuggestedLanguage
устанавливается в true
, поскольку язык был определен на основе языка, на котором была произнесена команда. Если язык запрошен явно, например, в «OK Google, включи субтитры на английском языке», параметр isSuggestedLanguage
устанавливается в false
.
Метаданные и озвучивание
Хотя голосовые команды по умолчанию обрабатываются Web Receiver, вам следует убедиться в полноте и точности метаданных вашего контента. Это гарантирует корректную обработку голосовых команд Ассистентом и корректное отображение метаданных в новых типах интерфейсов, таких как приложение Google Home и умные дисплеи, например, Google Home Hub.
Потоковая передача
Сохранение состояния сеанса — основа потоковой передачи, при которой пользователи могут перемещать существующие аудио- и видеопотоки между устройствами с помощью голосовых команд, приложения Google Home или умных дисплеев. Воспроизведение медиафайлов останавливается на одном устройстве (источнике) и продолжается на другом (приемнике). Любое устройство Cast с последней версией прошивки может служить источником или приемником потоковой передачи.
Поток событий для потоковой передачи следующий:
- На исходном устройстве:
- Медиафайлы останавливаются.
- Приложение Web Receiver получает команду на сохранение текущего состояния мультимедиа.
- Приложение Web Receiver закрыто.
- На целевом устройстве:
- Приложение Web Receiver загружено.
- Приложение Web Receiver получает команду на восстановление сохраненного состояния мультимедиа.
- Возобновляется воспроизведение медиа.
Элементы медиагосударства включают в себя:
- Конкретная позиция или временная метка песни, видео или медиа-элемента.
- Его место в более широкой очереди (например, в плейлисте или радиопередаче исполнителя).
- Аутентифицированный пользователь.
- Состояние воспроизведения (например, воспроизведение или пауза).
Включение потоковой передачи
Чтобы реализовать потоковую передачу для вашего веб-приемника:
- Обновите
supportedMediaCommands
с помощью командыSTREAM_TRANSFER
:playerManager.addSupportedMediaCommands( cast.framework.messages.Command.STREAM_TRANSFER, true);
- При необходимости можно переопределить перехватчики сообщений
SESSION_STATE
иRESUME_SESSION
, как описано в разделе «Сохранение состояния сеанса» . Переопределяйте их только в том случае, если необходимо сохранить пользовательские данные как часть снимка сеанса. В противном случае реализация по умолчанию для сохранения состояний сеанса будет поддерживать потоковую передачу.
Сохранение состояния сеанса
Web Receiver SDK предоставляет реализацию по умолчанию для приложений Web Receiver, которая позволяет сохранять состояния сеанса путем создания снимка текущего состояния мультимедиа, преобразования состояния в запрос на загрузку и возобновления сеанса с запросом на загрузку.
Запрос на загрузку, сгенерированный веб-приёмником, при необходимости можно переопределить в перехватчике сообщений 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 секунд до завершения предыдущего элемента. Если время предварительной загрузки больше, чем оставшееся время currentItem, предварительная загрузка произойдет как можно скорее. Таким образом, если указать очень большое значение preload для queueItem, можно добиться эффекта, когда при воспроизведении текущего элемента мы уже предварительно загружаем следующий элемент. Однако мы оставляем настройку и выбор этого разработчику, поскольку это значение может повлиять на пропускную способность и производительность потоковой передачи текущего воспроизводимого элемента.
Предварительная загрузка по умолчанию будет работать для потокового контента HLS, DASH и Smooth.
Обычные видео- и аудиофайлы MP4, такие как MP3, не будут предварительно загружены, поскольку устройства Cast поддерживают только один медиаэлемент и не могут использоваться для предварительной загрузки во время воспроизведения существующего элемента контента.
Пользовательские сообщения
Обмен сообщениями является ключевым методом взаимодействия для приложений Web Receiver.
Отправитель отправляет сообщения веб-приёмнику, используя API отправителя для платформы, на которой он работает (Android, iOS, веб). Объект события (являющийся проявлением сообщения), передаваемый прослушивателям событий, содержит элемент данных ( event.data
), где данные принимают свойства конкретного типа события.
Приложение Web Receiver может прослушивать сообщения в указанном пространстве имён. В этом случае считается, что приложение 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();
Аналогичным образом, приложения Web Receiver могут информировать отправителей о состоянии Web Receiver, отправляя сообщения подключенным отправителям. Приложение Web Receiver может отправлять сообщения, используя sendCustomMessage(namespace, senderId, message)
в CastReceiverContext
. Web Receiver может отправлять сообщения отдельному отправителю, как в ответ на полученное сообщение, так и в связи с изменением состояния приложения. Помимо обмена сообщениями «точка-точка» (с ограничением в 64 КБ), Web Receiver может также рассылать сообщения всем подключенным отправителям.
Трансляция для аудиоустройств
Информацию о поддержке воспроизведения только аудио см. в руководстве Google Cast для аудиоустройств .
Android TV
В этом разделе обсуждается, как Google Web Receiver использует ваши входные данные для воспроизведения, а также совместимость с Android TV.
Интеграция вашего приложения с пультом дистанционного управления
Приёмник Google Web, работающий на устройстве Android TV, преобразует входные сигналы с управляющих устройств устройства (например, с пульта дистанционного управления) в сообщения воспроизведения мультимедиа, определённые для пространства имён urn:x-cast:com.google.cast.media
, как описано в разделе Сообщения воспроизведения мультимедиа . Ваше приложение должно поддерживать эти сообщения для управления воспроизведением мультимедиа в приложении, чтобы обеспечить базовое управление воспроизведением с управляющих устройств Android TV.
Рекомендации по совместимости с Android TV
Вот несколько рекомендаций и распространенных ошибок, которых следует избегать, чтобы обеспечить совместимость вашего приложения с Android TV:
- Обратите внимание, что строка user-agent содержит как «Android», так и «CrKey»; некоторые сайты могут перенаправлять пользователей на сайт, предназначенный только для мобильных устройств, поскольку обнаруживают метку «Android». Не думайте, что «Android» в строке user-agent всегда указывает на мобильного пользователя.
- Медиа-стек Android может использовать прозрачный GZIP для извлечения данных. Убедитесь, что ваши медиа-данные поддерживают
Accept-Encoding: gzip
. - События мультимедиа HTML5 на Android TV могут запускаться в разное время, чем на Chromecast. Это может выявить проблемы, скрытые на Chromecast.
- При обновлении медиа используйте события, связанные с медиа, которые вызываются элементами
<audio>/<video>
, например,timeupdate
,pause
иwaiting
. Избегайте использования сетевых событий, таких какprogress
,suspend
иstalled
, поскольку они, как правило, зависят от платформы. Подробнее об обработке медиа -событий в приемнике см. в разделе «События медиа». - При настройке HTTPS-сертификатов вашего сайта-получателя обязательно включите промежуточные сертификаты CA. См. страницу тестирования SSL Qualsys, чтобы убедиться в этом: если доверенный путь сертификации для вашего сайта включает сертификат CA с пометкой «дополнительная загрузка», он может не загружаться на платформах Android.
- Chromecast отображает страницу приёмника в графическом разрешении 720p, в то время как другие платформы Cast, включая Android TV, могут отображать страницу в разрешении до 1080p. Убедитесь, что страница приёмника корректно масштабируется при разных разрешениях.