1. Descripción general
En este codelab, aprenderás a compilar una app receptora web personalizada para reproducir contenido en dispositivos compatibles con Cast.
¿Qué es Google Cast?
Google Cast permite a los usuarios transmitir contenido desde un dispositivo móvil a una TV. Luego, los usuarios pueden usar su dispositivo móvil o el navegador Chrome para computadoras de escritorio como control remoto para la reproducción de contenido multimedia en la TV.
El SDK de Google Cast permite que tu app controle dispositivos compatibles con Google Cast (por ejemplo, una TV o un sistema de sonido). El SDK de Cast te proporciona los componentes de IU necesarios según la lista de tareas de diseño de Google Cast.
Te proporcionamos la lista de tareas de diseño de Google Cast con el fin de que la experiencia del usuario de Cast resulte sencilla y predecible en todas las plataformas compatibles. Obtenga más información aquí.
¿Qué compilaremos?
Cuando completes este codelab, tendrás una app HTML5 que funcionará como tu propia app receptora personalizada capaz de mostrar contenido de video en dispositivos compatibles con Cast.
Qué aprenderás
- Cómo prepararse para el desarrollo de receptores
- Conceptos básicos de un receptor compatible con Cast basado en el framework de la aplicación de Cast
- Cómo recibir un video transmitido
- Cómo integrar el registro de depuración
- Cómo optimizar tu app receptora para pantallas inteligentes
Requisitos
- El navegador más reciente de Google Chrome
- Servicio de hosting HTTPS, como Firebase Hosting o Ngrok
- Un dispositivo Google Cast, como Chromecast o Android TV, que esté configurado con acceso a Internet
- Una TV o un monitor con entrada HDMI
Experiencia
- Deberá tener conocimientos previos sobre desarrollo web.
- También deberás tener experiencia como usuario de TV :)
¿Cómo usarás este instructivo?
¿Cómo calificarías tu experiencia cuando compilas apps web?
¿Cómo calificarías tu experiencia cuando miras TV?
2. Obtén el código de muestra
Puedes descargar el código de muestra completo a tu computadora…
y descomprimir el archivo ZIP que se descargó.
3. Implementa tu receptor de forma local
Para poder usar tu receptor web con un dispositivo de transmisión, debe estar alojado en un lugar donde tu dispositivo de transmisión pueda acceder a él. Si ya tienes un servidor disponible que sea compatible con https, omite las siguientes instrucciones y anota la URL, ya que la necesitarás en la siguiente sección.
Si no tienes un servidor disponible para usar, puedes usar Firebase Hosting o Ngrok.
Ejecuta el servidor
Una vez que hayas configurado el servicio que desees, navega a app-start
e inicia tu servidor.
Toma nota de la URL del receptor alojado. Lo utilizará en la próxima sección.
4. Registra una aplicación en la Consola para desarrolladores de Cast
Debes registrar tu aplicación para poder ejecutar una app receptora personalizada, como las que se compila en este codelab, en dispositivos Chromecast. Una vez que hayas registrado tu aplicación, recibirás un ID de aplicación que tu aplicación emisora debe utilizar para realizar llamadas a la API, por ejemplo, para iniciar una aplicación receptora.
Haz clic en "Agregar aplicación nueva".
Selecciona “Custom Receiver”, que es lo que estamos creando.
Ingresa los detalles del receptor nuevo. Asegúrate de usar la URL final.
en la última sección. Toma nota del ID de aplicación asignado al receptor nuevo.
También debes registrar tu dispositivo Google Cast para que acceda a la aplicación receptora antes de publicarla. Una vez que publiques la aplicación receptora, estará disponible para todos los dispositivos Google Cast. A los fines de este codelab, se recomienda trabajar con una aplicación receptora no publicada.
Haz clic en "Agregar nuevo dispositivo".
Ingresa el número de serie impreso en la parte posterior del dispositivo de transmisión y asígnale un nombre descriptivo. También puedes encontrar el número de serie si transmites la pantalla en Chrome cuando accedes a la Consola para programadores del SDK de Google Cast
El receptor y el dispositivo tardarán entre 5 y 15 minutos en estar listos para la prueba. Después de esperar entre 5 y 15 minutos, debes reiniciar tu dispositivo de transmisión.
5. Ejecuta la app de muestra
Mientras esperamos que nuestra nueva aplicación receptora esté lista para la prueba, veamos cómo se ve una app receptora de muestra completa. La app receptora que compilaremos podrá reproducir contenido multimedia mediante la transmisión de tasa de bits adaptable (utilizaremos contenido de muestra codificado para la Transmisión adaptable y dinámica a través de HTTP [DASH]).
En tu navegador, abre la herramienta de comando y control (CaC).
- Deberías ver nuestra herramienta de CaC.
- Use el ID del receptor de muestra "CC1AD845" predeterminado y haga clic en el botón "Set App ID".
- Haz clic en el botón para transmitir en la parte superior izquierda y selecciona tu dispositivo Google Cast.
- Navega a la pestaña "Load Media" en la parte superior.
- Haz clic en el botón "Load by Content" para reproducir un video de muestra.
- El video comenzará a reproducirse en tu dispositivo Google Cast para mostrar la funcionalidad básica del receptor con el receptor predeterminado.
6. Prepara el proyecto inicial
Debemos agregar compatibilidad con Google Cast a la app inicial que descargaste. A continuación, te mostramos la terminología de Google Cast que usaremos en este codelab:
- una app emisora se ejecuta en un dispositivo móvil o una laptop.
- una app receptora se ejecuta en el dispositivo Google Cast.
Ya puedes compilar sobre el proyecto inicial con tu editor de texto favorito:
- Selecciona el directorio
app-start
del código de muestra descargado. - Abrir
js/receiver.js
yindex.html
Ten en cuenta que, mientras trabajas en este codelab, http-server
debería detectar los cambios que realices. Si no es así, intenta finalizar y reiniciar http-server
.
Diseño de apps
La app receptora inicializa la sesión de transmisión y permanecerá en espera hasta que llegue una solicitud de CARGA (es decir, el comando para reproducir un contenido multimedia) de un remitente.
La app consta de una vista principal, definida en index.html
, y un archivo de JavaScript llamado js/receiver.js
, que contiene toda la lógica para que funcione la app receptora.
index.html
Este archivo html contendrá la IU para nuestra aplicación receptora. Por ahora está vacío, y lo agregaremos a lo largo del codelab.
receptor.js
Esta secuencia de comandos administrará toda la lógica de nuestra app receptora. En este momento, es solo un archivo vacío, pero lo convertiremos en un receptor de Cast completamente funcional con solo unas pocas líneas de código en la próxima sección.
7. Un receptor de transmisiones básico
Un receptor de transmisión básico inicializará la sesión de transmisión al inicio. Esto es necesario para indicarles a todas las aplicaciones emisoras conectadas que se abrió correctamente el receptor. Además, el nuevo SDK viene preconfigurado para controlar medios de transmisión con tasa de bits adaptable (con DASH, HLS y transmisión sin interrupciones) y archivos MP4 sin formato listos para usar. Vamos a intentarlo.
Inicialización
Agrega el siguiente código a index.html
en el encabezado:
<head>
...
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>
Agrega el siguiente código a index.html
<body>
antes de que <footer>
cargue receiver.js,
a fin de proporcionar al SDK el espacio necesario para que aparezca la IU predeterminada del receptor, que se envía con la secuencia de comandos que acabas de agregar.
<cast-media-player></cast-media-player>
Ahora, debemos inicializar el SDK en js/receiver.js
, que consiste en lo siguiente:
- adquirir una referencia a
CastReceiverContext
, tu punto de entrada principal a todo el SDK de la app receptora - almacenar una referencia a
PlayerManager
, el objeto que maneja la reproducción y te proporciona todos los hooks que necesitas para conectar tu propia lógica personalizada - inicializar el SDK llamando a
start()
enCastReceiverContext
Agrega lo siguiente a js/receiver.js
.
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
context.start();
8. Transmisión de contenido de video "básico"
A los fines de este Codelab, usa la herramienta CaC para probar tu receptor nuevo.
Dirige tu navegador web a la herramienta de comando y control (CaC).
Asegúrate de sustituir tu propio ID de la app registrado anteriormente en el campo y haz clic en "Set App ID". Esta acción le indica a la herramienta que use el receptor cuando inicies la sesión de transmisión.
Transmisión de contenido multimedia
En términos generales, para reproducir contenido multimedia en un dispositivo de transmisión, debe ocurrir lo siguiente:
- El remitente crea un objeto
MediaInfo
JSON
a partir del SDK de Cast que modela un elemento multimedia. - El remitente se conecta al dispositivo de transmisión para iniciar la aplicación receptora.
- El receptor carga el objeto
MediaInfo
a través de una solicitudLOAD
para reproducir el contenido. - El receptor monitorea y hace un seguimiento del estado del contenido multimedia.
- El remitente envía comandos de reproducción al receptor para controlar la reproducción en función de las interacciones del usuario con la app emisora.
En este primer intento básico, propagaremos MediaInfo
con una URL del elemento reproducible (almacenada en MediaInfo.contentUrl
).
Un remitente del mundo real usa un identificador multimedia específico de la aplicación en MediaInfo.contentId
. La app receptora usa el contentId
como identificador para realizar llamadas a la API de backend adecuadas a fin de resolver la URL del elemento real y establecerla en MediaInfo.contentUrl.
. La app receptora también se encargará de tareas como la adquisición de licencias de DRM o la inserción de información sobre las pausas publicitarias.
Extenderemos el receptor para que haga algo similar en la siguiente sección. Por ahora, haz clic en el ícono de transmisión y selecciona tu dispositivo para abrir la app receptora.
Ve a la pestaña "Load Media" y haz clic en el botón "Load by Content". Tu receptor debería comenzar a reproducir el contenido de muestra.
Por lo tanto, el SDK de la app receptora está lista para usar lo siguiente:
- Inicializa la sesión de transmisión
- Controlar solicitudes
LOAD
entrantes de remitentes que contienen recursos reproducibles - Proporciona una IU de reproductor básica lista para mostrarse en la pantalla grande.
No dudes en explorar la herramienta de CaC y su código antes de pasar a la siguiente sección, en la que extenderemos nuestro receptor para hablar con una API de muestra simple a fin de completar las solicitudes LOAD
entrantes de los remitentes.
9. Realiza la integración con una API externa
En línea con la forma en que la mayoría de los desarrolladores interactúan con sus receptores de transmisión en aplicaciones del mundo real, modificaremos el receptor para controlar las solicitudes LOAD
que hagan referencia al contenido multimedia previsto mediante su clave de API en lugar de enviar una URL de elemento reproducible.
Las aplicaciones suelen hacerlo porque:
- Es posible que el remitente no conozca la URL de contenido.
- La aplicación de transmisión está diseñada para controlar la autenticación, otra lógica empresarial o llamadas a la API directamente en el receptor.
Esta funcionalidad se implementa principalmente en el método setMessageInterceptor()
de PlayerManager
. Esto te permite interceptar los mensajes entrantes por tipo y modificarlos antes de que lleguen al controlador de mensajes interno del SDK. En esta sección, nos ocuparemos de las solicitudes de LOAD
. Para ello, haremos lo siguiente:
- Lee la solicitud entrante
LOAD
y sucontentId
personalizado. - Realiza una llamada
GET
a nuestra API para buscar el elemento que se puede transmitir por sucontentId
. - Modifica la solicitud
LOAD
con la URL de la transmisión. - Modifica el objeto
MediaInformation
para establecer los parámetros del tipo de transmisión. - Pasa la solicitud al SDK para su reproducción o rechaza el comando si no podemos buscar el contenido multimedia solicitado.
La API de muestra proporcionada presenta los hooks del SDK para personalizar tareas comunes de la app receptora, a la vez que se basa en una experiencia lista para usar.
API de muestra
Dirige tu navegador a https://storage.googleapis.com/cpe-sample-media/content.json y consulta nuestro catálogo de videos de muestra. El contenido incluye URLs de imágenes de póster en formato PNG y transmisiones DASH y HLS. Las transmisiones DASH y HLS apuntan a las fuentes de audio y video desmuestidas que se almacenan en contenedores mp4 fragmentados.
{
"bbb": {
"author": "The Blender Project",
"description": "Grumpy Bunny is grumpy",
"poster": "https://[...]/[...]/BigBuckBunny/images/screenshot1.png",
"stream": {
"dash": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.mpd",
"hls": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.m3u8",
"title": "Big Buck Bunny"
},
"fbb_ad": {
"author": "Google Inc.",
"description": "Introducing Chromecast. The easiest way to enjoy [...]",
"poster": "https://[...]/[...]/ForBiggerBlazes/images/screenshot8.png",
"stream": {
"dash": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.mpd",
"hls": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.m3u8",
"title": "For Bigger Blazes"
},
[...]
}
En el siguiente paso, asignaremos la clave de cada entrada (por ejemplo, bbb, fbb_ad
) a la URL de la transmisión después de que se llame al receptor con una solicitud LOAD
.
Cómo interceptar la solicitud de CARGA
En este paso, crearemos un interceptor de carga con una función que realice una solicitud XHR
al archivo JSON
alojado. Una vez que se obtenga el archivo JSON
, analizaremos el contenido y configuraremos los metadatos. En las siguientes secciones, personalizaremos los parámetros de MediaInformation
para especificar el tipo de contenido.
Agrega el siguiente código a tu archivo js/receiver.js
, justo antes de la llamada a context.start()
.
function makeRequest (method, url) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
// Fetch content repository by requested contentId
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json').then(function (data) {
let item = data[request.media.contentId];
if(!item) {
// Content could not be found in repository
reject();
} else {
// Add metadata
let metadata = new
cast.framework.messages.GenericMediaMetadata();
metadata.title = item.title;
metadata.subtitle = item.author;
request.media.metadata = metadata;
// Resolve request
resolve(request);
}
});
});
});
En la siguiente sección, se describe cómo configurar la propiedad media
de la solicitud de carga para el contenido DASH.
Usa el contenido DASH de la API de muestra
Ahora que preparamos el interceptor de carga, especificaremos el tipo de contenido para el receptor. Esta información proporcionará al receptor la URL de la lista de reproducción principal y el tipo de MIME de transmisión. Agrega el siguiente código al archivo js/receiver.js en la Promise()
del interceptor LOAD
:
...
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
...
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.dash;
request.media.contentType = 'application/dash+xml';
...
}
});
});
});
Una vez que complete este paso, puede probar el contenido DASH. Si quieres probar la carga con contenido HLS, consulta el siguiente paso.
Usa el contenido HLS de la API de muestra
La API de muestra incluye contenido HLS y DASH. Además de configurar contentType
como lo hicimos en el paso anterior, la solicitud de carga necesitará algunas propiedades adicionales para usar las URLs de HLS de la API de muestra. Cuando el receptor está configurado para reproducir transmisiones HLS, el tipo de contenedor predeterminado esperado es el flujo de transporte (TS). Como resultado, el receptor intentará abrir las transmisiones de MP4 de muestra en formato TS solo si se modifica la propiedad contentUrl
. En la solicitud de carga, el objeto MediaInformation
debe modificarse con propiedades adicionales de modo que el receptor sepa que el contenido es del tipo MP4 y no TS. Agrega el siguiente código a tu archivo js/receiver.js en el interceptor de carga para modificar las propiedades contentUrl
y contentType
. Además, agrega las propiedades HlsSegmentFormat
y HlsVideoSegmentFormat
.
...
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
...
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.hls;
request.media.contentType = 'application/x-mpegurl';
request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
...
}
});
});
});
Pruébalo
Vuelve a abrir la herramienta de comando y control (CaC) y establece el ID de app en el ID de app del receptor. Selecciona tu dispositivo con el botón para transmitir.
Ve a la pestaña "Load Media". Esta vez, borra el texto en el campo "Content URL" junto al botón "Load by Content", lo que obligará a nuestra aplicación a enviar una solicitud LOAD
que contenga solo la referencia contentId
a nuestro contenido multimedia.
Suponiendo que todo funcionó bien con las modificaciones que hiciste en el receptor, el interceptor se encargará de darle forma al objeto MediaInfo
de modo que el SDK pueda reproducirlo en la pantalla.
Haz clic en el botón "Load by Content" para ver si el contenido multimedia se reproduce correctamente. Puedes cambiar el ID de contenido por otro en el archivo content.json.
10. Optimización para pantallas inteligentes
Las pantallas inteligentes son dispositivos con funcionalidad táctil que permiten que las aplicaciones receptoras admitan controles táctiles.
En esta sección, se explica cómo optimizar la aplicación receptora cuando se inicia en pantallas inteligentes y cómo personalizar los controles del reproductor.
Accede a los controles de la IU
Se puede acceder al objeto de controles de la IU para pantallas inteligentes mediante cast.framework.ui.Controls.GetInstance()
. Agrega el siguiente código a tu archivo js/receiver.js
arriba de context.start()
:
...
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
context.start();
Si no usas el elemento <cast-media-player>, deberás establecer touchScreenOptimizedApp
en CastReceiverOptions
. En este codelab, usaremos el elemento <cast-media-player>.
context.start({ touchScreenOptimizedApp: true });
Los botones de control predeterminados se asignan a cada ranura en función de MetadataType
y MediaStatus.supportedMediaCommands
.
Controles de video
En el caso de MetadataType.MOVIE
, MetadataType.TV_SHOW
y MetadataType.GENERIC
, se mostrará el objeto de controles de la IU para pantallas inteligentes, como en el siguiente ejemplo.
--playback-logo-image
MediaMetadata.subtitle
MediaMetadata.title
MediaStatus.currentTime
MediaInformation.duration
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.QUEUE_PREV
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.SEEK_BACKWARD_30
PLAY/PAUSE
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.SEEK_FORWARD_30
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.QUEUE_NEXT
Controles de audio
En el caso de MetadataType.MUSIC_TRACK
, el objeto de controles de la IU para pantallas inteligentes se mostrará de la siguiente manera:
--playback-logo-image
MusicTrackMediaMetadata.albumName
MusicTrackMediaMetadata.title
MusicTrackMediaMetadata.albumArtist
MusicTrackMediaMetadata.images[0]
MediaStatus.currentTime
MediaInformation.duration
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.NO_BUTTON
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.QUEUE_PREV
PLAY/PAUSE
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.QUEUE_NEXT
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.NO_BUTTON
Cómo actualizar comandos de contenido multimedia compatibles
El objeto de controles de la IU también determina si se muestra ControlsButton
o no, según MediaStatus.supportedMediaCommands
.
Cuando el valor de supportedMediaCommands
sea igual a ALL_BASIC_MEDIA
, se mostrará el diseño de control predeterminado de la siguiente manera:
Cuando el valor de supportedMediaCommands
sea igual a ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT
, se mostrará el diseño de control predeterminado de la siguiente manera:
Cuando el valor de supportedMediaCommands sea igual a PAUSE | QUEUE_PREV | QUEUE_NEXT
, se mostrará el diseño de control predeterminado de la siguiente manera:
Cuando haya pistas de texto disponibles, el botón de subtítulos se mostrará siempre en SLOT_1
.
Si quieres cambiar dinámicamente el valor de supportedMediaCommands
después de iniciar el contexto de un receptor, puedes llamar a PlayerManager.setSupportedMediaCommands
para anular el valor. Además, puedes agregar un comando nuevo con addSupportedMediaCommands
o quitar uno existente con removeSupportedMediaCommands
.
Personalización de los botones de control
Puedes personalizar los controles mediante PlayerDataBinder
. Agrega el siguiente código a tu archivo js/receiver.js
debajo de touchControls para establecer la primera ranura de tus controles:
...
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
playerDataBinder.addEventListener(
cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
(e) => {
if (!e.value) return;
// Clear default buttons and re-assign
touchControls.clearDefaultSlotAssignments();
touchControls.assignButton(
cast.framework.ui.ControlsSlot.SLOT_PRIMARY_1,
cast.framework.ui.ControlsButton.SEEK_BACKWARD_30
);
});
context.start();
11. Cómo implementar la exploración multimedia en pantallas inteligentes
La exploración multimedia es una función del receptor de CAF que permite a los usuarios explorar contenido adicional en dispositivos táctiles. A fin de implementar esto, usarás PlayerDataBinder
para configurar la IU de BrowseContent
. Luego, puedes propagarlo con BrowseItems
según el contenido que desees mostrar.
Explorar contenido
A continuación, se muestra un ejemplo de la IU de BrowseContent
y sus propiedades:
BrowseContent.title
BrowseContent.items
Relación de aspecto
Utilice targetAspectRatio property
para seleccionar la mejor relación de aspecto para sus elementos de imagen. El SDK de receptor de CAF admite tres relaciones de aspecto: SQUARE_1_TO_1
, PORTRAIT_2_TO_3
y LANDSCAPE_16_TO_9
.
Explorar elemento
Usa BrowseItem
para mostrar el título, los subtítulos, la duración y la imagen de cada elemento:
BrowseItem.image
BrowseItem.duration
BrowseItem.title
BrowseItem.subtitle
Configurar datos de exploración multimedia
Puedes proporcionar una lista de contenido multimedia para la navegación llamando a setBrowseContent
. Agrega el siguiente código a tu archivo js/receiver.js
debajo de playerDataBinder
y al objeto de escucha de eventos MEDIA_CHANGED
para establecer los elementos de navegación con el título "A continuación".
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
...
let browseItems = getBrowseItems();
function getBrowseItems() {
let browseItems = [];
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
.then(function (data) {
for (let key in data) {
let item = new cast.framework.ui.BrowseItem();
item.entity = key;
item.title = data[key].title;
item.subtitle = data[key].description;
item.image = new cast.framework.messages.Image(data[key].poster);
item.imageType = cast.framework.ui.BrowseImageType.MOVIE;
browseItems.push(item);
}
});
return browseItems;
}
let browseContent = new cast.framework.ui.BrowseContent();
browseContent.title = 'Up Next';
browseContent.items = browseItems;
browseContent.targetAspectRatio = cast.framework.ui.BrowseImageAspectRatio.LANDSCAPE_16_TO_9;
playerDataBinder.addEventListener(
cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
(e) => {
if (!e.value) return;
....
// Media browse
touchControls.setBrowseContent(browseContent);
});
Si haces clic en un elemento de navegación multimedia, se activará el interceptor LOAD
. Agrega el siguiente código a tu interceptor LOAD
para asignar request.media.contentId
a request.media.entity
desde el elemento de navegación multimedia:
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
...
// Map contentId to entity
if (request.media && request.media.entity) {
request.media.contentId = request.media.entity;
}
return new Promise((resolve, reject) => {
...
});
});
También puedes establecer el objeto BrowseContent
en null
para quitar la IU de exploración multimedia.
12. Depurar apps receptoras
El SDK de app receptora de transmisión ofrece otra opción para que los desarrolladores depuren fácilmente apps receptora mediante la API CastDebugLogger y una herramienta de comando y control (CaC) complementaria para capturar registros.
Inicialización
Para incorporar la API, agrega la secuencia de comandos de origen CastDebugLogger
en tu archivo index.html. La fuente se debe declarar en la etiqueta <head> después de la declaración del SDK de la app receptora de transmisión.
<head>
...
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
<!-- Cast Debug Logger -->
<script src="//www.gstatic.com/cast/sdk/libs/devtools/debug_layer/caf_receiver_logger.js"></script>
</head>
En js/receiver.js
, en la parte superior del archivo y debajo de playerManager
, agrega el siguiente código para recuperar la instancia CastDebugLogger
y habilitar el registrador:
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MyAPP.LOG';
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
castDebugLogger.setEnabled(true);
}
});
Cuando el registro de depuración está habilitado, se muestra una superposición que muestra DEBUG MODE
en la app receptora.
Eventos de registro del reproductor
Con CastDebugLogger
, puedes registrar fácilmente los eventos de reproductor que activa el SDK de receptor de CAF y usar diferentes niveles de registro para registrar los datos de eventos. La configuración de loggerLevelByEvents
usa cast.framework.events.EventType
y cast.framework.events.category
para especificar qué eventos se registrarán.
Agrega el siguiente código debajo de la declaración castDebugLogger
para registrar cuando se active un evento CORE
del reproductor o se emita un cambio de mediaStatus
:
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
castDebugLogger.setEnabled(true);
}
});
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}
Mensajes de registro y etiquetas personalizadas
La API de CastDebugLogger te permite crear mensajes de registro que aparecen en la superposición de depuración del receptor con diferentes colores. Los siguientes métodos de registro están disponibles, ordenados de mayor a menor prioridad:
castDebugLogger.error(custom_tag, message);
castDebugLogger.warn(custom_tag, message);
castDebugLogger.info(custom_tag, message);
castDebugLogger.debug(custom_tag, message);
Para cada método de registro, el primer parámetro es una etiqueta personalizada. Puede ser cualquier string de identificación que consideres significativa. CastDebugLogger
usa etiquetas para filtrar los registros. El uso de las etiquetas se explica en detalle más adelante. El segundo parámetro es el mensaje de registro.
Para mostrar registros en acción, agrega registros a tu interceptor LOAD
.
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
castDebugLogger.info(LOG_TAG, 'Intercepting LOAD request');
// Map contentId to entity
if (request.media && request.media.entity) {
request.media.contentId = request.media.entity;
}
return new Promise((resolve, reject) => {
// Fetch content repository by requested contentId
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
.then(function (data) {
let item = data[request.media.contentId];
if(!item) {
// Content could not be found in repository
castDebugLogger.error(LOG_TAG, 'Content not found');
reject();
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.dash;
request.media.contentType = 'application/dash+xml';
castDebugLogger.warn(LOG_TAG, 'Playable URL:', request.media.contentUrl);
// Add metadata
let metadata = new cast.framework.messages.MovieMediaMetadata();
metadata.metadataType = cast.framework.messages.MetadataType.MOVIE;
metadata.title = item.title;
metadata.subtitle = item.author;
request.media.metadata = metadata;
// Resolve request
resolve(request);
}
});
});
});
Puedes controlar qué mensajes aparecen en la superposición de depuración configurando el nivel de registro en loggerLevelByTags
para cada etiqueta personalizada. Por ejemplo, si habilitas una etiqueta personalizada con el nivel de registro cast.framework.LoggerLevel.DEBUG
, se mostrarán todos los mensajes que se agregaron con mensajes de error, advertencia, información y depuración. Si habilitas una etiqueta personalizada con el nivel WARNING
, solo se mostrarán mensajes de error y advertencias.
La configuración loggerLevelByTags
es opcional. Si una etiqueta personalizada no está configurada para el nivel de registro, se mostrarán todos los mensajes del registro en la superposición de depuración.
Agrega el siguiente código debajo del registrador de eventos CORE
:
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}
// Set verbosity level for custom tags.
castDebugLogger.loggerLevelByTags = {
[LOG_TAG]: cast.framework.LoggerLevel.DEBUG,
};
Superposición para depurar
Cast Debug Logger proporciona una superposición de depuración en el receptor para mostrar los mensajes de registro personalizados en el dispositivo de transmisión. Usa showDebugLogs
para activar o desactivar la superposición de depuración y clearDebugLogs
para borrar los mensajes del registro en la superposición.
Agrega el siguiente código para obtener una vista previa de la superposición de depuración en la app receptora.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
castDebugLogger.setEnabled(true);
// Show debug overlay
castDebugLogger.showDebugLogs(true);
// Clear log messages on debug overlay
castDebugLogger.clearDebugLogs();
}
});
13. Felicitaciones
Ahora sabes cómo crear una aplicación receptora web personalizada con el SDK de receptor web de Cast.
Para obtener más detalles, consulte la guía para desarrolladores de Receptor web.