En esta página, se incluyen fragmentos de código y descripciones de las funciones disponibles para una app de receptor web personalizado.
- Un elemento
cast-media-playerque representa la IU del reproductor integrado que se proporciona con Web Receiver - Es un diseño personalizado similar a CSS para el elemento
cast-media-playerque permite aplicar diseño a varios elementos de la IU, comobackground-image,splash-imageyfont-family. - Un elemento de secuencia de comandos para cargar el framework de Web Receiver
- Código JavaScript para interceptar mensajes y controlar eventos
- Agrega contenido a la fila para la reproducción automática.
- Son las opciones para configurar la reproducción.
- Opciones para establecer el contexto del receptor web.
- Son opciones para establecer comandos que admite la app de Web Receiver.
- Una llamada de JavaScript para iniciar la aplicación de receptor web
Configuración y opciones de la aplicación
Configura la aplicación
CastReceiverContext
es la clase más externa expuesta al desarrollador, y administra la carga de
las bibliotecas subyacentes y controla la inicialización del SDK de Web Receiver. El SDK proporciona APIs que permiten a los desarrolladores de aplicaciones configurar el SDK a través de CastReceiverOptions.
Estas opciones de configuración se evalúan una vez por cada inicio de la aplicación y se pasan al
SDK cuando se establece el parámetro opcional en la llamada a
start.
En el siguiente ejemplo, se muestra cómo anular el comportamiento predeterminado para detectar si una conexión del remitente sigue activa. Cuando el receptor web no se puede comunicar con un remitente durante maxInactivity segundos, se envía un evento SENDER_DISCONNECTED. La configuración que se muestra a continuación
anula este tiempo de espera. Esto puede ser útil para depurar problemas, ya que evita que la app de Web Receiver cierre la sesión del depurador remoto de Chrome cuando no hay remitentes conectados en un estado IDLE.
const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);
Configura el reproductor
Cuando se carga contenido, el SDK de Web Receiver proporciona una forma de configurar variables de reproducción, como la información de DRM, las configuraciones de reintentos y los controladores de solicitudes con cast.framework.PlaybackConfig.
PlayerManager controla esta información, que se evalúa cuando se crean los reproductores. Los reproductores se crean cada vez que se pasa una carga nueva al SDK de Web Receiver. Las modificaciones en el objeto PlaybackConfig después de que se crea el reproductor se evalúan en la siguiente carga de contenido. El SDK proporciona los siguientes métodos para modificar el objeto
PlaybackConfig.
CastReceiverOptions.playbackConfigpara anular las opciones de configuración predeterminadas cuando se inicializaCastReceiverContext.PlayerManager.getPlaybackConfig()para obtener la configuración actual.PlayerManager.setPlaybackConfig()para anular la configuración actual. Este parámetro de configuración se aplica a todas las cargas posteriores o hasta que se vuelva a anular.PlayerManager.setMediaPlaybackInfoHandler()para aplicar parámetros de configuración adicionales solo al elemento multimedia que se carga sobre los parámetros de configuración actuales Se llama al controlador justo antes de que se cree el reproductor. Los cambios que se realicen aquí no son permanentes y no se incluyen en las consultas agetPlaybackConfig(). Cuando se carga el siguiente elemento multimedia, se vuelve a llamar a este controlador.
En el siguiente ejemplo, se muestra cómo establecer el PlaybackConfig cuando se inicializa el CastReceiverContext. La configuración anula las solicitudes salientes para
obtener manifiestos. El controlador especifica que las solicitudes de control de acceso de CORS
se deben realizar con credenciales como cookies o encabezados de autorización.
const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});
En el siguiente ejemplo, se muestra cómo anular PlaybackConfig con el método get y set proporcionado en PlayerManager. Este parámetro configura el reproductor para que reanude la reproducción del contenido después de que se haya cargado 1 segmento.
const playerManager =
cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);
En el siguiente ejemplo, se muestra cómo anular el PlaybackConfig para una solicitud de carga específica con el controlador de información de reproducción de contenido multimedia. El controlador llama a un método getLicenseUrlForMedia implementado por la aplicación para obtener el licenseUrl del contentId del elemento actual.
playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
const mediaInformation = loadRequestData.media;
playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);
return playbackConfig;
});
Objeto de escucha de eventos
El SDK de Web Receiver permite que tu app de Web Receiver controle los eventos del reproductor. El objeto de escucha de eventos toma un parámetro cast.framework.events.EventType (o un array de estos parámetros) que especifica los eventos que deben activar el objeto de escucha. Los arrays preconfigurados de
cast.framework.events.EventType que son útiles para la depuración se pueden encontrar en
cast.framework.events.category.
El parámetro de evento proporciona información adicional sobre el evento.
Por ejemplo, si quieres saber cuándo se transmite un cambio de mediaStatus, puedes usar la siguiente lógica para controlar el evento:
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
});
Intercepción de mensajes
El SDK de Web Receiver permite que tu app de Web Receiver intercepte mensajes y ejecute código personalizado en ellos. El interceptor de mensajes toma un parámetro cast.framework.messages.MessageType que especifica qué tipo de mensaje se debe interceptar.
El interceptor debe devolver la solicitud modificada o una promesa que se resuelva
con el valor de la solicitud modificada. Si se muestra null, se evitará que se llame al controlador de mensajes predeterminado. Consulta Cómo cargar contenido multimedia para obtener más detalles.
Por ejemplo, si quieres cambiar los datos de la solicitud de carga, puedes usar la siguiente lógica para interceptarlos y modificarlos:
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();
Manejo de errores
Cuando se producen errores en el interceptor de mensajes, tu app de Web Receiver debe mostrar un cast.framework.messages.ErrorType y un cast.framework.messages.ErrorReason adecuados.
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;
});
});
Intercepción de mensajes frente a objeto de escucha de eventos
Estas son algunas diferencias clave entre la intercepción de mensajes y el objeto de escucha de eventos:
- Un objeto de escucha de eventos no te permite modificar los datos de la solicitud.
- Un objeto de escucha de eventos se usa mejor para activar estadísticas o una función personalizada.
playerManager.addEventListener(cast.framework.events.category.CORE,
event => {
console.log(event);
});
- La intercepción de mensajes te permite escuchar un mensaje, interceptarlo y modificar los datos de la solicitud.
- La interceptación de mensajes se usa mejor para controlar la lógica personalizada en relación con los datos de la solicitud.
Carga de contenido multimedia
MediaInformation proporciona numerosas propiedades para cargar contenido multimedia en el mensaje cast.framework.messages.MessageType.LOAD, incluidas entity, contentUrl y contentId.
entityes la propiedad que se sugiere usar en tu implementación para las apps emisora y receptora. La propiedad es una URL de vínculo directo que puede ser una playlist o contenido multimedia. Tu aplicación debe analizar esta URL y completar al menos uno de los otros dos campos.- El
contentUrlcorresponde a la URL reproducible que usará el reproductor para cargar el contenido. Por ejemplo, esta URL podría apuntar a un manifiesto de DASH. contentIdpuede ser una URL de contenido reproducible (similar a la de la propiedadcontentUrl) o un identificador único para el contenido o la playlist que se carga. Si usas esta propiedad como identificador, tu aplicación debe propagar una URL reproducible en elcontentUrl.
Se sugiere usar entity para almacenar el ID real o los parámetros clave, y
usar contentUrl para la URL del contenido multimedia. En el siguiente fragmento, se muestra un ejemplo de esto, en el que el entity está presente en la solicitud LOAD y se recupera el contentUrl reproducible:
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;
});
});
Funciones del dispositivo
El método getDeviceCapabilities proporciona información sobre el dispositivo de Cast conectado y el dispositivo de video o audio conectado a él. El método getDeviceCapabilities proporciona información de compatibilidad para el Asistente de Google, Bluetooth y los dispositivos de audio y pantalla conectados.
Este método devuelve un objeto que puedes consultar pasando uno de los
enums especificados para obtener la capacidad del dispositivo para ese enum. Las enumeraciones se definen en cast.framework.system.DeviceCapabilities.
En este ejemplo, se verifica si el dispositivo receptor web puede reproducir HDR y DolbyVision (DV) con las claves IS_HDR_SUPPORTED y IS_DV_SUPPORTED, respectivamente.
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();
Cómo controlar la interacción del usuario
Un usuario puede interactuar con tu aplicación de receptor web a través de aplicaciones emisoras (Web, Android y iOS), comandos por voz en dispositivos compatibles con el Asistente, controles de tacto en pantallas inteligentes y controles remotos en dispositivos Android TV. El SDK de Cast proporciona varias APIs para permitir que la app de receptor web controle estas interacciones, actualice la IU de la aplicación a través de los estados de acción del usuario y, de manera opcional, envíe los cambios para actualizar los servicios de backend.
Comandos multimedia compatibles
Los estados de los controles de la IU se rigen por la clase MediaStatus.supportedMediaCommands para los controles expandidos de emisores de iOS y Android, las apps de receptor y control remoto que se ejecutan en dispositivos táctiles, y las apps de receptor en dispositivos Android TV. Cuando se habilita un Command bit a bit en particular en la propiedad, se habilitan los botones relacionados con esa acción. Si no se establece el valor, el botón se inhabilita. Estos valores se pueden cambiar en el receptor web de la siguiente manera:
- Usa
PlayerManager.setSupportedMediaCommandspara establecer elCommandsespecífico. - Agrega un comando nuevo con
addSupportedMediaCommands - Quita un comando existente con
removeSupportedMediaCommands.
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
cast.framework.messages.Command.PAUSE);
Cuando el receptor prepare el MediaStatus actualizado, incluirá los
cambios en la propiedad supportedMediaCommands. Cuando se transmite el estado, las apps emisoras conectadas actualizan los botones de su IU según corresponda.
Para obtener más información sobre los comandos multimedia y los dispositivos táctiles compatibles, consulta la guía de Accessing UI controls.
Administra los estados de acción del usuario
Cuando los usuarios interactúan con la IU o envían comandos por voz, pueden controlar la reproducción del contenido y las propiedades relacionadas con el elemento que se está reproduciendo. El SDK controla automáticamente las solicitudes que controlan la reproducción. Las solicitudes que modifican las propiedades del elemento que se está reproduciendo, como un comando LIKE, requieren que la aplicación receptora las controle. El SDK proporciona una serie de
APIs para controlar estos tipos de solicitudes. Para admitir estas solicitudes, se debe hacer lo siguiente:
- Establece el
MediaInformationuserActionStatescon las preferencias de un usuario cuando se cargue un elemento multimedia. - Intercepta los mensajes de
USER_ACTIONy determina la acción solicitada. - Actualiza el
MediaInformationUserActionStatepara actualizar la IU.
En el siguiente fragmento, se intercepta la solicitud LOAD y se propaga el MediaInformation de LoadRequestData. En este caso, al usuario le gusta el
contenido que se está cargando.
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;
});
En el siguiente fragmento, se intercepta el mensaje USER_ACTION y se controla la llamada
al backend con el cambio solicitado. Luego, realiza una llamada para actualizar el UserActionState en el receptor.
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;
});
});
En el siguiente fragmento, se simula una llamada a un servicio de backend. La función verifica
el UserActionRequestData para ver el tipo de cambio que solicitó el usuario
y solo realiza una llamada de red si el backend admite la acción.
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));
}
});
}
En el siguiente fragmento, se toma el UserActionRequestData y se agrega o
quita el UserActionState del MediaInformation. Cuando se actualiza el UserActionState de MediaInformation, cambia el estado del botón asociado con la acción solicitada. Este cambio se refleja en la IU de los controles de la pantalla inteligente, la app de control remoto y la IU de Android TV. También se transmite a través de mensajes MediaStatus salientes para actualizar la IU del control expandido para los remitentes de iOS y 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;
}
Comandos por voz
Actualmente, se admiten los siguientes comandos multimedia en el SDK de Web Receiver para
dispositivos compatibles con el Asistente. Las implementaciones predeterminadas de estos comandos se encuentran en cast.framework.PlayerManager.
| Comando | Descripción |
|---|---|
| Reproducir | Reproduce o reanuda la reproducción desde el estado de pausa. |
| Pausar | Pausa el contenido que se está reproduciendo. |
| Anterior | Ir al elemento multimedia anterior de la fila de contenido multimedia |
| Siguiente | Ir al siguiente elemento multimedia de la fila |
| Detener | Detener el contenido multimedia que se está reproduciendo |
| No repetir | Inhabilita la repetición de los elementos multimedia de la fila una vez que se termine de reproducir el último elemento. |
| Repetir una canción | Repite el contenido multimedia que se está reproduciendo de forma indefinida. |
| Repetir todo | Repite todos los elementos de la fila una vez que se reproduzca el último elemento. |
| Repetir todo y reproducir aleatoriamente | Una vez que se termine de reproducir el último elemento de la fila, se mezclará la fila y se repetirán todos los elementos. |
| Shuffle | Reproduce de forma aleatoria los elementos multimedia de tu fila de contenido multimedia. |
| Activar o desactivar los subtítulos | Habilitar o inhabilitar los subtítulos para tu contenido multimedia La opción de habilitar o inhabilitar también está disponible por idioma. |
| Busca un momento absoluto | Salta al tiempo absoluto especificado. |
| Busca un tiempo relativo a la hora actual | Avanza o retrocede el período especificado en relación con el tiempo de reproducción actual. |
| Volver a jugar | Reinicia el contenido multimedia que se está reproduciendo o reproduce el último elemento multimedia que se reprodujo si no se está reproduciendo nada. |
| Cómo establecer la velocidad de reproducción | Variar la velocidad de reproducción de contenido multimedia Esto debería controlarse de forma predeterminada. Puedes usar el interceptor de mensajes SET_PLAYBACK_RATE para anular las solicitudes de calificación entrantes. |
Comandos de contenido multimedia compatibles con la voz
Para evitar que un comando por voz active un comando de contenido multimedia en un dispositivo compatible con el Asistente, primero debes establecer los comandos de contenido multimedia compatibles que planeas admitir. Luego, debes aplicar esos comandos habilitando la propiedad CastReceiverOptions.enforceSupportedCommands. La IU de los emisores del SDK de Cast y los dispositivos táctiles cambiará para reflejar estos parámetros de configuración. Si no se habilita la marca, se ejecutarán los comandos por voz entrantes.
Por ejemplo, si permites PAUSE desde tus aplicaciones emisoras y dispositivos táctiles, también debes configurar el receptor para que refleje esos parámetros de configuración. Cuando se configuran, se descartan los comandos por voz entrantes que no
se incluyen en la lista de comandos compatibles.
En el siguiente ejemplo, proporcionamos el CastReceiverOptions cuando se inicia
el CastReceiverContext. Agregamos compatibilidad con el comando PAUSE y
forzamos al reproductor a admitir solo ese comando. Ahora, si un comando por voz
solicita otra operación, como SEEK, se rechazará. Se notificará al usuario que el comando aún no es compatible.
const context = cast.framework.CastReceiverContext.getInstance();
context.start({
enforceSupportedCommands: true,
supportedCommands: cast.framework.messages.Command.PAUSE
});
Puedes aplicar una lógica independiente para cada comando que quieras restringir. Quita
la marca enforceSupportedCommands y, para cada comando que quieras
restringir, puedes interceptar el mensaje entrante. Aquí interceptamos la solicitud que proporciona el SDK para que los comandos SEEK que se emiten a los dispositivos compatibles con el Asistente no activen una búsqueda en tu aplicación de receptor web.
En el caso de los comandos de contenido multimedia que tu aplicación no admita, devuelve un motivo de error apropiado, como 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;
});
Ejecución en segundo plano desde la actividad de voz
Si la plataforma de Cast pone en segundo plano el sonido de tu aplicación debido a la actividad de Asistente, como escuchar el discurso del usuario o responder, se envía un mensaje FocusState de NOT_IN_FOCUS a la aplicación de Web Receiver cuando se inicia la actividad. Cuando finaliza la actividad, se envía otro mensaje con IN_FOCUS.
Según tu aplicación y el contenido multimedia que se esté reproduciendo, es posible que quieras pausar el contenido multimedia cuando el FocusState sea NOT_IN_FOCUS interceptando el tipo de mensaje FOCUS_STATE.
Por ejemplo, es una buena experiencia del usuario pausar la reproducción de un audiolibro si el Asistente responde a una consulta del usuario.
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;
});
Idioma de los subtítulos especificado por voz
Cuando un usuario no indica de forma explícita el idioma de los subtítulos, el idioma que se usa para los subtítulos es el mismo en el que se pronunció el comando.
En estas situaciones, el parámetro isSuggestedLanguage del mensaje entrante indica si el idioma asociado fue sugerido o solicitado de forma explícita por el usuario.
Por ejemplo, isSuggestedLanguage se establece en true para el comando "Hey Google, activa los subtítulos", porque el idioma se infirió por el idioma en el que se pronunció el comando. Si el idioma se solicita de forma explícita, como en "Hey Google, activa los subtítulos en inglés", isSuggestedLanguage se establece en false.
Metadatos y selección de voces
Si bien el receptor web controla los comandos por voz de forma predeterminada, debes asegurarte de que los metadatos de tu contenido sean completos y precisos. Esto garantiza que Asistente controle correctamente los comandos por voz y que los metadatos aparezcan de forma adecuada en los nuevos tipos de interfaces, como la app de Google Home y las pantallas inteligentes, como Google Home Hub.
Transferencia de transmisión
La preservación del estado de la sesión es la base de la transferencia de transmisión, en la que los usuarios pueden mover transmisiones de audio y video existentes entre dispositivos con comandos por voz, la app de Google Home o pantallas inteligentes. El contenido multimedia deja de reproducirse en un dispositivo (la fuente) y continúa en otro (el destino). Cualquier dispositivo Cast con el firmware más reciente puede funcionar como origen o destino en una transferencia de transmisión.
El flujo de eventos para la transferencia de transmisión es el siguiente:
- En el dispositivo de origen:
- Se detiene la reproducción del contenido multimedia.
- La aplicación de Web Receiver recibe un comando para guardar el estado actual del contenido multimedia.
- Se cierra la aplicación de Web Receiver.
- En el dispositivo de destino, haz lo siguiente:
- Se carga la aplicación de receptor web.
- La aplicación de Web Receiver recibe un comando para restablecer el estado del contenido multimedia guardado.
- Se reanuda la reproducción del contenido multimedia.
Entre los elementos del estado de contenido multimedia, se incluyen los siguientes:
- Es la posición o marca de tiempo específica de la canción, el video o el elemento multimedia.
- Su lugar en una fila más amplia (como una playlist o una radio de artista)
- Es el usuario autenticado.
- Estado de reproducción (por ejemplo, reproduciendo o en pausa)
Habilita la transferencia de transmisión
Para implementar la transferencia de transmisión en tu receptor web, haz lo siguiente:
- Actualiza
supportedMediaCommandscon el comandoSTREAM_TRANSFER:playerManager.addSupportedMediaCommands( cast.framework.messages.Command.STREAM_TRANSFER, true);
- De manera opcional, anula los interceptores de mensajes
SESSION_STATEyRESUME_SESSIONcomo se describe en Conserva el estado de la sesión. Anula estos métodos solo si es necesario almacenar datos personalizados como parte de la instantánea de la sesión. De lo contrario, la implementación predeterminada para conservar los estados de sesión admitirá la transferencia de transmisión.
Conservación del estado de la sesión
El SDK de Web Receiver proporciona una implementación predeterminada para que las apps de Web Receiver conserven los estados de sesión. Para ello, toma una instantánea del estado actual del contenido multimedia, lo convierte en una solicitud de carga y reanuda la sesión con la solicitud de carga.
Si es necesario, la solicitud de carga que genera el receptor web se puede anular en el interceptor de mensajes SESSION_STATE. Si quieres agregar datos personalizados
a la solicitud de carga, te sugerimos que los coloques en
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;
});
Los datos personalizados se pueden recuperar de loadRequestData.customData en el interceptor de mensajes 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;
});
Carga previa de contenido
El receptor web admite la carga previa de elementos multimedia después del elemento de reproducción actual en la fila.
La operación de carga previa descarga varios segmentos de los próximos elementos. La especificación se realiza en el valor preloadTime del objeto QueueItem (el valor predeterminado es de 20 segundos si no se proporciona). El tiempo se expresa en segundos, en relación con el final del elemento que se está reproduciendo . Solo se permiten valores positivos. Por ejemplo, si el valor es de 10 segundos, este elemento se precargará 10 segundos antes de que finalice el elemento anterior. Si el tiempo de carga previa es mayor que el tiempo restante en el currentItem, la carga previa se realizará lo antes posible. Por lo tanto, si se especifica un valor muy grande de precarga en el queueItem, se podría lograr el efecto de que, cada vez que se reproduzca el elemento actual, ya se esté precargando el siguiente. Sin embargo, dejamos la configuración y la elección de este valor al desarrollador, ya que puede afectar el ancho de banda y el rendimiento de la transmisión del elemento que se está reproduciendo.
La carga previa funcionará de forma predeterminada para el contenido de transmisión de HLS, DASH y Smooth.
Los archivos de video MP4 y de audio normales, como MP3, no se precargarán, ya que los dispositivos de transmisión solo admiten un elemento multimedia y no se pueden usar para precargar mientras se reproduce un elemento de contenido existente.
Mensajes personalizados
El intercambio de mensajes es el método de interacción clave para las aplicaciones de receptor web.
Un remitente envía mensajes a un receptor web con las APIs de remitente para la plataforma en la que se ejecuta el remitente (Android, iOS, Web). El objeto de evento (que
es la manifestación de un mensaje) que se pasa a los objetos de escucha de eventos tiene un
elemento de datos (event.data) en el que los datos adoptan las propiedades del
tipo de evento específico.
Una aplicación de receptor web puede elegir escuchar mensajes en un espacio de nombres específico. Por lo tanto, se dice que la aplicación de receptor web admite ese protocolo de espacio de nombres. Luego, depende de los remitentes conectados que deseen comunicarse en ese espacio de nombres usar el protocolo adecuado.
Todos los espacios de nombres se definen con una cadena y deben comenzar con "urn:x-cast:"
seguido de cualquier cadena. Por ejemplo:
"urn:x-cast:com.example.cast.mynamespace".
Este es un fragmento de código para que el receptor web escuche los mensajes personalizados de los emisores conectados:
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();
De manera similar, las aplicaciones de receptor web pueden mantener informados a los remitentes sobre el estado del receptor web enviando mensajes a los remitentes conectados. Una aplicación de receptor web puede enviar mensajes con sendCustomMessage(namespace, senderId, message) en CastReceiverContext.
Un receptor web puede enviar mensajes a un remitente individual, ya sea en respuesta a un mensaje recibido o debido a un cambio de estado de la aplicación. Además de la mensajería punto a punto (con un límite de 64 KB), un receptor web también puede enviar anuncios a todos los remitentes conectados.
Dispositivos de audio compatibles con Cast
Consulta la guía de Google Cast para dispositivos de audio para obtener asistencia sobre la reproducción solo de audio.
Android TV
En esta sección, se analiza cómo el receptor web de Google usa tus entradas como reproducción y la compatibilidad con Android TV.
Integra tu aplicación con el control remoto
El receptor web de Google que se ejecuta en el dispositivo Android TV traduce la entrada de los controles del dispositivo (es decir, el control remoto portátil) como mensajes de reproducción de contenido multimedia definidos para el espacio de nombres urn:x-cast:com.google.cast.media, como se describe en Mensajes de reproducción de contenido multimedia. Tu aplicación debe admitir estos mensajes para controlar la reproducción de contenido multimedia de la aplicación y permitir el control básico de la reproducción desde las entradas de control de Android TV.
Lineamientos para la compatibilidad con Android TV
A continuación, se incluyen algunas recomendaciones y errores comunes que debes evitar para garantizar que tu aplicación sea compatible con Android TV:
- Ten en cuenta que la cadena de usuario-agente contiene "Android" y "CrKey". Algunos sitios pueden redireccionar a un sitio solo para dispositivos móviles porque detectan la etiqueta "Android". No asumas que "Android" en la cadena de usuario-agente siempre indica un usuario de dispositivo móvil.
- La pila de contenido multimedia de Android puede usar GZIP transparente para recuperar datos. Asegúrate de que tus datos de contenido multimedia puedan responder a
Accept-Encoding: gzip. - Los eventos de contenido multimedia HTML5 de Android TV se pueden activar en momentos diferentes que los de Chromecast, lo que puede revelar problemas que estaban ocultos en Chromecast.
- Cuando actualices el contenido multimedia, usa los eventos relacionados con el contenido multimedia que activan los elementos
<audio>/<video>, comotimeupdate,pauseywaiting. Evita usar eventos relacionados con las redes, comoprogress,suspendystalled, ya que suelen depender de la plataforma. Consulta Eventos multimedia para obtener más información sobre cómo controlar eventos multimedia en tu receptor. - Cuando configures los certificados HTTPS de tu sitio receptor, asegúrate de incluir certificados de AC intermedios. Consulta la página de prueba de SSL de Qualsys para verificar si la ruta de certificación de confianza de tu sitio incluye un certificado de la AC etiquetado como “descarga adicional”, ya que, de ser así, es posible que no se cargue en plataformas basadas en Android.
- Mientras que Chromecast muestra la página del receptor en un plano de gráficos de 720p, otras plataformas de Cast, como Android TV, pueden mostrar la página hasta en 1080p. Asegúrate de que la página del receptor se ajuste correctamente a diferentes resoluciones.