Integra el SDK de Cast en tu app de remitente web

En esta guía para desarrolladores, se describe cómo agregar la compatibilidad con Google Cast a tu app de Web Sender con el SDK de Cast.

Terminología

El dispositivo móvil o navegador es el remitente, que controla la reproducción. El dispositivo Google Cast es el receptor, que muestra el contenido en pantalla para su reproducción.

El SDK de Web Sender consta de dos partes: la API de framework (cast.framework) y la API de base (chrome.cast). En general, se realizan llamadas en la API de framework más simple y de nivel superior, que luego procesa la API de nivel inferior.

El marco de trabajo del remitente se refiere a la API de marco de trabajo, el módulo y los recursos asociados que proporcionan un wrapper alrededor de la funcionalidad de nivel inferior. La app de remitente o la app de Google Cast para Chrome se refiere a una app web (HTML/JavaScript) que se ejecuta dentro de un navegador Chrome en un dispositivo emisor. Una app receptora web hace referencia a una app HTML/JavaScript que se ejecuta en Chromecast o un dispositivo Google Cast.

El framework del remitente usa un diseño de devolución de llamada asíncrono para informar a la app emisora de los eventos y realizar la transición entre varios estados del ciclo de vida de la app de Cast.

Cómo cargar la biblioteca

Para que tu app implemente las funciones de Google Cast, debe conocer la ubicación del SDK de Google Cast Web Sender, como se muestra a continuación. Agrega el parámetro de búsqueda de URL loadCastFramework para cargar la API de Web Sender Framework. Todas las páginas de tu app deben hacer referencia a la biblioteca de la siguiente manera:

<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

Framework

El SDK de Web Sender utiliza el espacio de nombres cast.framework.*. El espacio de nombres representa lo siguiente:

  • Métodos o funciones que invocan operaciones en la API
  • Objetos de escucha de eventos para funciones de objetos de escucha en la API

El framework consta de estos componentes principales:

  • El CastContext es un objeto singleton que proporciona información sobre el estado actual de Cast y activa eventos para los cambios de estado de la transmisión y el estado de la sesión.
  • El objeto CastSession administra la sesión, ya que proporciona información de estado y activa eventos, como cambios en el volumen del dispositivo, el estado de silencio y los metadatos de la app.
  • El elemento del botón para transmitir, que es un elemento personalizado HTML sencillo que extiende el botón HTML Si el botón para transmitir proporcionado no es suficiente, puedes usar el estado para implementar uno.
  • RemotePlayerController proporciona la vinculación de datos para simplificar la implementación del reproductor remoto.

Revisa la referencia de la API de Google Cast Web Sender para obtener una descripción completa del espacio de nombres.

Botón para transmitir

El framework controla el componente del botón para transmitir de tu app. Esto incluye la administración de la visibilidad, así como el manejo de eventos de clic.

<google-cast-launcher></google-cast-launcher>

También puedes crear el botón de manera programática:

document.createElement("google-cast-launcher");

Puedes aplicar cualquier estilo adicional, como tamaño o posicionamiento, al elemento según sea necesario. Usa el atributo --connected-color a fin de elegir el color para el estado del receptor web conectado y --disconnected-color para el estado desconectado.

Inicialización

Después de cargar la API de framework, la app llamará al controlador window.__onGCastApiAvailable. Debes asegurarte de que la app configure este controlador en el window antes de cargar la biblioteca de remitentes.

Dentro de este controlador, debes inicializar la interacción con Cast llamando al método setOptions(options) de CastContext.

Por ejemplo:

<script>
window['__onGCastApiAvailable'] = function(isAvailable) {
  if (isAvailable) {
    initializeCastApi();
  }
};
</script>

Luego, inicializa la API de la siguiente manera:

initializeCastApi = function() {
  cast.framework.CastContext.getInstance().setOptions({
    receiverApplicationId: applicationId,
    autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
  });
};

Primero, la app recupera la instancia singleton del objeto CastContext que proporciona el framework. Luego, usa setOptions(options) con un objeto CastOptions para establecer applicationID.

Si usas el receptor multimedia predeterminado, que no requiere registro, usarás una constante predefinida por el SDK de Web Sender, como se muestra a continuación, en lugar de applicationID:

cast.framework.CastContext.getInstance().setOptions({
  receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
});

Control multimedia

Una vez que se inicializa CastContext, la app puede recuperar el CastSession actual en cualquier momento mediante getCurrentSession().

var castSession = cast.framework.CastContext.getInstance().getCurrentSession();

Se puede usar CastSession para cargar contenido multimedia al dispositivo de transmisión conectado mediante loadMedia(loadRequest). Primero, crea un MediaInfo con contentId y contentType, así como cualquier otra información relacionada con el contenido. Luego, crea un LoadRequest a partir de él y configura toda la información relevante para la solicitud. Por último, llama a loadMedia(loadRequest) en tu CastSession.

var mediaInfo = new chrome.cast.media.MediaInfo(currentMediaURL, contentType);
var request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
  function() { console.log('Load succeed'); },
  function(errorCode) { console.log('Error code: ' + errorCode); });

El método loadMedia mostrará una Promesa que se puede usar a fin de realizar cualquier operación necesaria para obtener un resultado exitoso. Si se rechaza la promesa, el argumento de la función será chrome.cast.ErrorCode.

Puedes acceder a las variables de estado del jugador en RemotePlayer. Todas las interacciones con RemotePlayer, incluidos los comandos y las devoluciones de llamada de eventos multimedia, se controlan con RemotePlayerController.

var player = new cast.framework.RemotePlayer();
var playerController = new cast.framework.RemotePlayerController(player);

RemotePlayerController le da a la app el control multimedia completo de PLAY, PAUSA, DETENER y BUSCAR en el contenido multimedia cargado.

  • REPRODUCIR/PAUSA: playerController.playOrPause();
  • DETENER: playerController.stop();
  • SOLICITAR: playerController.seek();

RemotePlayer y RemotePlayerController se pueden usar con frameworks de vinculación de datos, como Polymer o Angular, para implementar un reproductor remoto.

Este es un fragmento de código para Angular:

<button id="playPauseButton" class="playerButton"
  ng-disabled="!player.canPause"
  ng-click="controller.playOrPause()">
    {{player.isPaused ? 'Play' : 'Pause'}}
</button>
<script>
var player = new cast.framework.RemotePlayer();
var controller = new cast.framework.RemotePlayerController(player);
// Listen to any player update, and trigger angular data binding
update.controller.addEventListener(
  cast.framework.RemotePlayerEventType.ANY_CHANGE,
  function(event) {
    if (!$scope.$$phase) $scope.$apply();
  });
</script>

Estado del contenido multimedia

Durante la reproducción de contenido multimedia, se producen varios eventos que se pueden capturar si configuras objetos de escucha para varios eventos cast.framework.RemotePlayerEventType en el objeto RemotePlayerController.

Para obtener la información del estado del contenido multimedia, usa el evento cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, que se activa cuando cambia la reproducción y cuando cambia CastSession.getMediaSession().media.

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.MEDIA_INFO_CHANGED, function() {
    // Use the current session to get an up to date media status.
    let session = cast.framework.CastContext.getInstance().getCurrentSession();

    if (!session) {
        return;
    }

    // Contains information about the playing media including currentTime.
    let mediaStatus = session.getMediaSession();
    if (!mediaStatus) {
        return;
    }

    // mediaStatus also contains the mediaInfo containing metadata and other
    // information about the in progress content.
    let mediaInfo = mediaStatus.media;
  });

Cuando ocurran eventos, como pausar, reproducir, reanudar o buscar, la app deberá realizar acciones en ellos y sincronizarse entre sí y con la app de recepción web en el dispositivo de transmisión. Consulta Actualizaciones de estado para obtener más información.

Cómo funciona la administración de sesiones

El SDK de Cast presenta el concepto de una sesión de transmisión, cuyo establecimiento combina los pasos para conectarse a un dispositivo, iniciar (o unirse) una app receptora web, conectarse a esa app e inicializar un canal de control de contenido multimedia. Consulta la guía del ciclo de vida de la aplicación del receptor web para obtener más información sobre las sesiones de transmisión y el ciclo de vida del receptor web.

La clase CastContext administra la sesión, que la app puede recuperar mediante cast.framework.CastContext.getInstance(). Las sesiones individuales se representan con subclases de la clase Session. Por ejemplo, CastSession representa sesiones con dispositivos de transmisión. La app puede acceder a la sesión de transmisión activa en ese momento mediante CastContext.getCurrentSession().

A fin de supervisar el estado de la sesión, agrega un objeto de escucha en CastContext para el tipo de evento CastContextEventType.SESSION_STATE_CHANGED.

var context = cast.framework.CastContext.getInstance();
context.addEventListener(
  cast.framework.CastContextEventType.SESSION_STATE_CHANGED,
  function(event) {
    switch (event.sessionState) {
      case cast.framework.SessionState.SESSION_STARTED:
      case cast.framework.SessionState.SESSION_RESUMED:
        break;
      case cast.framework.SessionState.SESSION_ENDED:
        console.log('CastContext: CastSession disconnected');
        // Update locally as necessary
        break;
    }
  })

Para la desconexión, como cuando el usuario hace clic en el botón "detener transmisión" del diálogo de transmisión, puedes agregar un objeto de escucha para el tipo de evento RemotePlayerEventType.IS_CONNECTED_CHANGED en tu objeto de escucha. En tu objeto de escucha, verifica si RemotePlayer está desconectado. Si es así, actualiza el estado del reproductor local según sea necesario. Por ejemplo:

playerController.addEventListener(
  cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED, function() {
    if (!player.isConnected) {
      console.log('RemotePlayerController: Player disconnected');
      // Update local player to disconnected state
    }
  });

Si bien el usuario puede controlar directamente la finalización de la transmisión a través del botón para transmitir el framework, el remitente puede dejar de transmitir con el objeto CastSession actual.

function stopCasting() {
  var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
  // End the session and pass 'true' to indicate
  // that Web Receiver app should be stopped.
  castSession.endSession(true);
}

Transferencia de transmisión

Preservar el 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 mediante 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 de transmisión con el firmware más reciente puede funcionar como fuentes o destinos en una transferencia de transmisión.

Para obtener el dispositivo de destino nuevo durante la transferencia de transmisión, llama a CastSession#getCastDevice() cuando se llame al evento cast.framework.SessionState.SESSION_RESUMED.

Consulta Transferencia de transmisión en el receptor web para obtener más información.