Usar el SDK de IMA DAI en Chromecast

Reproducir emisiones de VOD registradas con la API Video Stitcher de Google Cloud

En esta guía se explica cómo usar el SDK de IMA DAI para receptores web de CAF con el fin de solicitar y reproducir una sesión de emisión de vídeo bajo demanda de Google Cloud.

En esta guía se amplía el ejemplo básico de la inserción dinámica de anuncios de servicio completo, añadiendo compatibilidad con las emisiones registradas en la API Google Cloud Video Stitcher.

Antes de continuar, asegúrate de que tu formato de streaming sea compatible con los web receivers de CAF.

Para obtener información sobre cómo integrar otras plataformas o usar los SDKs de IMA del lado del cliente, consulte SDKs de anuncios multimedia interactivos.

Fondo

Antes de usar esta guía, familiarízate con el protocolo Web Receiver del framework de aplicaciones de Chromecast.

En esta guía se da por hecho que tienes un nivel básico de familiarización con los conceptos del receptor de CAF, como los interceptores de mensajes, los objetos MediaInformation y el uso de la herramienta de control y comandos de Cast para emular un remitente de CAF.

Componentes y arquitectura de la aplicación

Para implementar la reproducción de emisiones de VOD con la API Video Stitcher de Google Cloud y el SDK de CAF de IMA para inserción dinámica de anuncios, se necesitan dos componentes principales, tal como se muestra en esta guía:

  • VideoStitcherVodStreamRequest: Objeto que define una solicitud de flujo a los servidores de Google.
  • StreamManager: objeto que gestiona la comunicación entre el flujo de vídeo y el SDK de inserción dinámica de anuncios de IMA, como enviar pings de seguimiento y reenviar eventos de flujo al editor.

Configura un proyecto de Google Cloud.

Introduzca las siguientes variables para usarlas en el SDK de IMA:

  • Ubicación: la región de Google Cloud en la que se creó tu configuración de VOD.

    LOCATION

  • Número de proyecto: número del proyecto de Google Cloud que usa la API Video Stitcher.

    PROJECT_NUMBER

  • Token de OAuth: token de OAuth de corta duración de una cuenta de servicio con el rol de usuario de Video Stitcher. Consulta más información sobre cómo crear credenciales de cuentas de servicio de duración reducida.

    OAUTH_TOKEN

  • Código de red: código de red de Google Ad Manager para solicitar anuncios.

    NETWORK_CODE

  • ID de configuración de VOD: el ID de configuración de VOD de la emisión de VOD.

    VOD_CONFIG_ID

    Consulta más información sobre cómo crear el ID de configuración de VOD en la guía de creación de configuraciones de VOD de Cloud Stitching.

    VOD_URI

Configurar un receptor de emisión personalizado

Para desarrollar un receptor personalizado de Cast, necesitas lo siguiente:

Preparar un remitente para que transfiera datos de la emisión al receptor

Primero, configura tu aplicación emisora para que haga una solicitud de carga a tu receptor web, que contenga los siguientes campos en el objeto MediaInformation de tu plataforma.

Campo Contenido
contentId Identificador único de este elemento multimedia, tal como se define en la documentación de referencia de Cast. Este ID no se debe reutilizar para varios elementos de la misma cola multimedia.

CONTENT_ID

contentUrl URL de emisión de respaldo opcional que se reproducirá si no se puede cargar la emisión de inserción dinámica de anuncios.

BACKUP_STREAM_URL

contentType Tipo MIME opcional de la URL de la emisión de respaldo que se reproducirá si no se puede cargar la emisión de inserción dinámica de anuncios.

BACKUP_STREAM_MIMETYPE

streamType La cadena literal o la constante que se usa para este valor varía según la plataforma del remitente.

VOD

customData

El campo customData contiene un almacén de clave-valor de campos obligatorios adicionales. En este caso, customData contiene los datos de la emisión de inserción dinámica de anuncios que ha recogido.

Campo Contenido
region LOCATION
projectNumber PROJECT_NUMBER
oAuthToken OAUTH_TOKEN
networkCode NETWORK_CODE
vodConfigId VOD_CONFIG_ID

Aquí tienes algunos ejemplos de código para ayudarte a empezar:

Web

Para configurar estos valores en un remitente web de Cast, primero crea un objeto MediaInfo con los datos necesarios y, a continuación, haz una solicitud de carga al receptor web.

// Create mediaInfo object
const mediaInfo = new chrome.cast.media.MediaInfo("CONTENT_ID");
mediaInfo.contentUrl = "BACKUP_STREAM_URL";
mediaInfo.contentType = "BACKUP_STREAM_MIMETYPE";
mediaInfo.streamType = chrome.cast.media.StreamType.VOD;
mediaInfo.customData = {
  region: "LOCATION",
  projectNumber: "PROJECT_NUMBER",
  oAuthToken: "OAUTH_TOKEN",
  networkCode: "NETWORK_CODE",
  vodConfigId: "VOD_CONFIG_ID"
};

// Make load request to cast web receiver
const castSession = cast.framework.CastContext.getInstance().getCurrentSession();
const request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
  () => { console.log('Load succeed'); },
  (errorCode) => { console.log('Error code: ' + errorCode); });

Android

Para configurar estos valores en un remitente web de Cast, primero crea un objeto MediaInfo con los datos necesarios y, a continuación, haz una solicitud de carga al receptor web.

JSONObject customData = new JSONObject()
  .put("region", "LOCATION")
  .put("projectNumber", "PROJECT_NUMBER")
  .put("oAuthToken", "OAUTH_TOKEN")
  .put("networkCode", "NETWORK_CODE")
  .put("vodConfigId", "VOD_CONFIG_ID");

MediaInfo mediaInfo = MediaInfo.Builder("CONTENT_ID")
  .setContentUrl("BACKUP_STREAM_URL")
  .setContentType("BACKUP_STREAM_MIMETYPE")
  .setStreamType(MediaInfo.STREAM_TYPE_VOD)
  .setCustomData(customData)
  .build();

RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
remoteMediaClient.load(new MediaLoadRequestData.Builder().setMediaInfo(mediaInfo).build());

iOS (Obj-C)

Para configurar estos valores en un remitente web de Cast, primero crea un objeto GCKMediaInformation con los datos necesarios y, a continuación, haz una solicitud de carga al receptor web.

NSURL url = [NSURL URLWithString:@"BACKUP_STREAM_URL"];
NSDictionary *customData = @{
  @"region": @"LOCATION",
  @"projectNumber": @"PROJECT_NUMBER",
  @"oAuthToken": @"OAUTH_TOKEN",
  @"networkCode": @"NETWORK_CODE",
  @"vodConfigId": @"VOD_CONFIG_ID"
};

GCKMediaInformationBuilder *mediaInfoBuilder =
  [[GCKMediaInformationBuilder alloc] initWithContentID: @"CONTENT_ID"];
mediaInfoBuilder.contentURL = url;
mediaInfoBuilder.contentType = @"BACKUP_STREAM_MIMETYPE";
mediaInfoBuilder.streamType = GCKMediaStreamTypeNone;
mediaInfoBuilder.customData = customData;
self.mediaInformation = [mediaInfoBuilder build];

GCKRequest *request = [self.sessionManager.currentSession.remoteMediaClient loadMedia:self.mediaInformation];
if (request != nil) {
  request.delegate = self;
}

iOS (Swift)

Para configurar estos valores en un remitente web de Cast, primero crea un objeto GCKMediaInformation con los datos necesarios y, a continuación, haz una solicitud de carga al receptor web.

let url = URL.init(string: "BACKUP_STREAM_URL")
guard let mediaURL = url else {
  print("invalid mediaURL")
  return
}

let customData = [
  "region": "LOCATION",
  "projectNumber": "PROJECT_NUMBER",
  "oAuthToken": "OAUTH_TOKEN",
  "networkCode": "NETWORK_CODE",
  "vodConfigId": "VOD_CONFIG_ID"
]

let mediaInfoBuilder = GCKMediaInformationBuilder.init(contentId: "CONTENT_ID")
mediaInfoBuilder.contentURL = mediaUrl
mediaInfoBuilder.contentType = "BACKUP_STREAM_MIMETYPE"
mediaInfoBuilder.streamType = GCKMediaStreamType.none
mediaInfoBuilder.customData = customData
mediaInformation = mediaInfoBuilder.build()

guard let mediaInfo = mediaInformation else {
  print("invalid mediaInformation")
  return
}

if let request = sessionManager.currentSession?.remoteMediaClient?.loadMedia(mediaInfo) {
  request.delegate = self
}

Herramienta CAC

Para configurar estos valores en la herramienta de control por voz de Cast, haz clic en la pestaña Cargar contenido multimedia y define el tipo de solicitud de carga personalizada como LOAD. A continuación, sustituye los datos JSON del área de texto por este JSON:

{
  "media": {
    "contentId": "CONTENT_ID",
    "contentUrl": "BACKUP_STREAM_URL",
    "contentType": "BACKUP_STREAM_MIMETYPE",
    "streamType": "VOD",
    "customData": {
      "region": "LOCATION",
      "projectNumber": "PROJECT_NUMBER",
      "oAuthToken": "OAUTH_TOKEN",
      "networkCode": "NETWORK_CODE",
      "vodConfigId": "VOD_CONFIG_ID"
    }
  }
}

Esta solicitud de carga personalizada se puede enviar al receptor para probar el resto de los pasos.

Crear un receptor web CAF personalizado

Crea un receptor web personalizado, como se indica en la guía del receptor web personalizado del SDK de CAF.

El código del receptor debería tener el siguiente aspecto:

<html>
<head>
  <script
      src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js">
  </script>
</head>
<body>
  <cast-media-player></cast-media-player>
  <script>
    const castContext = cast.framework.CastReceiverContext.getInstance()
    castContext.start();
  </script>
</body>
</html>

Importar el SDK de IMA DAI y obtener el gestor de reproductores

Añada una etiqueta <script> para importar el SDK de IMA DAI para CAF a su receptor web, justo después de cargar el script de CAF. A continuación, en la etiqueta de secuencia de comandos que sigue, almacena el contexto del receptor y el gestor de reproductores como constantes antes de iniciar el receptor.

<html>
<head>
  <script
      src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
  <script src="//imasdk.googleapis.com/js/sdkloader/cast_dai.js"></script>
</head>
<body>
  <cast-media-player></cast-media-player>
  <script>
    const castContext = cast.framework.CastReceiverContext.getInstance();
    const playerManager = castContext.getPlayerManager();

    castContext.start();
  </script>
</body>
</html>

Inicializar el gestor de emisiones de IMA

Inicializa el gestor de emisiones de IMA.

<html>
<head>
  <script type="text/javascript"
      src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
  <script src="//imasdk.googleapis.com/js/sdkloader/cast_dai.js"></script>
</head>
<body>
  <cast-media-player></cast-media-player>
  <script>
    const castContext = cast.framework.CastReceiverContext.getInstance();
    const playerManager = castContext.getPlayerManager();
    const streamManager = new google.ima.cast.dai.api.StreamManager();

    castContext.start();
  </script>
</body>
</html>

Crear el interceptor de carga de Stream Manager

Antes de que tus elementos multimedia se transfieran a CAF, crea tu solicitud de emisión en un interceptor de mensajes LOAD.

    const castContext = cast.framework.CastReceiverContext.getInstance();
    const playerManager = castContext.getPlayerManager();
    const streamManager = new google.ima.cast.dai.api.StreamManager();

    /**
     * Creates a VOD stream request object for the Video Stitcher API.
     * @param {!LoadRequestData} castRequest The request object from the cast sender
     * @return {StreamRequest} an IMA stream request
     */
    const createStreamRequest = (castRequest) => { /* ... */};

    /**
     * Initates a DAI stream request for the final stream manifest.
     * @param {!LoadRequestData} castRequest The request object from the cast sender
     * @return {Promise<LoadRequestData>} a promise that resolves to an updated castRequest, containing the DAI stream manifest
     */
    const createDAICastRequest = (castRequest) => {
        return streamManager.requestStream(castRequest, createStreamRequest(castRequest))
          .then((castRequestWithStreamData) => {
            console.log('Successfully made DAI stream request.');
            return castRequestWithStreamData;
          })
          .catch((error) => {
            console.log('Failed to make DAI stream request.');
            // CAF will automatically fallback to the content URL
            // that it can read from the castRequest object.
            return castRequest;
          });
    };

    playerManager.setMessageInterceptor(
        cast.framework.messages.MessageType.LOAD, createDAICastRequest);

    castContext.start();

Crear la solicitud de flujo

Completa la función createStreamRequest para crear una solicitud de emisión de VOD de la API Video Stitcher basada en la solicitud de carga de CAF.

    /**
     * Creates a VOD stream request object for the Video Stitcher API.
     * @param {!LoadRequestData} castRequest The request object from the cast sender
     * @return {StreamRequest} an IMA stream request
     */
    const createStreamRequest = (castRequest) => {
      const streamRequest = new google.ima.cast.dai.api.VideoStitcherVodStreamRequest();
      const customData = castRequest.media.customData;

      streamRequest.region = customData.region;
      streamRequest.projectNumber = customData.projectNumber;
      streamRequest.oAuthToken = customData.oAuthToken;
      streamRequest.networkCode = customData.networkCode;
      streamRequest.vodConfigId = customData.vodConfigId;
      streamRequest.videoStitcherSessionOptions = {};

      return streamRequest;
    };

(Opcional) Añadir opciones de sesión de streaming

Personaliza tu solicitud de emisión añadiendo opciones de sesión para anular la configuración predeterminada de la API Cloud Video Stitcher mediante VideoStitcherVodStreamRequest.videoStitcherSessionOptions. Si proporcionas una opción no reconocida, la API Cloud Video Stitcher responderá con un error HTTP 400. Consulta la guía de solución de problemas para obtener ayuda.

Por ejemplo, puedes anular las opciones del manifiesto con el siguiente fragmento de código, que solicita dos manifiestos de emisión con representaciones ordenadas de menor a mayor tasa de bits.

...

// The following session options are examples. Use session options
// that are compatible with your video stream.
streamRequest.videoStitcherSessionOptions = {
  "manifestOptions": {
    "bitrateOrder": "ascending"
  }
};

streamManager.requestStream(streamRequest);