Cómo comenzar a usar el SDK de IMA de DAI

Los SDKs de IMA facilitan la integración de anuncios multimedia en tus sitios web y apps. Los SDKs de IMA pueden solicitar anuncios de cualquier servidor de anuncios que cumpla con VAST y administrar la reproducción de anuncios en tus apps. Con los SDKs de DAI de IMA, las apps realizan una solicitud de transmisión de anuncios y videos de contenido, ya sea VOD o contenido en vivo. Luego, el SDK muestra una transmisión de video combinada para que no tengas que administrar el cambio entre el video de anuncios y el de contenido dentro de tu app.

Selecciona la solución de DAI que te interesa

Publicación de grupos de anuncios de DAI

En esta guía, se muestra cómo reproducir una transmisión de Publicación de grupos de anuncios de DAI para contenido en vivo o VOD, con el SDK de DAI de IMA para HTML5 con un reproductor de video que depende de hls.js para la reproducción. Para ver o seguir una integración de muestra completa, con compatibilidad con HLS.js y la reproducción de Safari, consulta el ejemplo de entrega de grupos de HLS. Para obtener compatibilidad con DASH.js, consulta el ejemplo de publicación de pods de DASH. Puedes descargar estas apps de ejemplo desde la página de lanzamiento de GitHub de los DAI HTML5.

Descripción general de la Publicación de grupos de anuncios de DAI

La implementación de la publicación de grupos de anuncios con el SDK de DAI de IMA implica dos componentes principales, que se muestran en esta guía:

  • PodStreamRequest / PodVodStreamRequest: Es un objeto que define una solicitud de transmisión a los servidores de publicidad de Google. Las solicitudes especifican un código de red y PodStreamRequest también requiere una clave de activo personalizado y una clave de API opcional. Ambos incluyen otros parámetros opcionales.

  • StreamManager: Es un objeto que controla la comunicación entre la transmisión de video y el SDK de DAI de IMA, como activar pings de seguimiento y reenviar eventos de transmisión al publicador.

Requisitos previos

Antes de comenzar, necesitas lo siguiente:

  • Tres archivos vacíos:

    • dai.html
    • dai.css
    • dai.js
  • Python instalado en tu computadora, un servidor web o cualquier otro entorno de desarrollo alojado para usar en las pruebas

Configura un entorno de desarrollo

Dado que el SDK carga dependencias con el mismo protocolo que la página desde la que se carga, debes usar un servidor web para probar tu app. Una forma rápida de iniciar un servidor de desarrollo local es usar el servidor integrado de Python.

  1. En una línea de comandos, desde el directorio que contiene tu archivo index.html, ejecuta lo siguiente:

    python -m http.server 8000
  2. En un navegador web, ve a http://localhost:8000/.

    También puedes usar cualquier otro entorno de desarrollo alojado o servidor web, como el servidor HTTP de Apache.

Crea un reproductor de video

Primero, modifica dai.html para crear un elemento de video HTML5 y un div que se use para los elementos de la IU del anuncio. También agrega las etiquetas necesarias para cargar los archivos dai.css y dai.js, así como para importar el reproductor de video hls.js.

Luego, modifica dai.css para especificar el tamaño y la posición de los elementos de la página. Por último, en dai.js, define variables para contener la información de la solicitud de transmisión y una función initPlayer() para ejecutar cuando se cargue la página.

Las constantes de solicitud de transmisión son las siguientes:

  • BACKUP_STREAM: Es una URL para que se reproduzca una transmisión de respaldo en caso de que el proceso de anuncios encuentre un error irrecuperable.

  • STREAM_URL: Solo se usa para transmisiones en vivo. La URL del flujo de video que proporciona el manipulador de manifiestos o el socio externo que usa la Publicación de grupos de anuncios. Debería requerir que insertes el ID de transmisión que proporciona el SDK de IMA DAI antes de realizar una solicitud. En este caso, la URL de la transmisión incluye un marcador de posición, [[STREAMID]], que se reemplaza por el ID de la transmisión antes de realizar una solicitud.

  • NETWORK_CODE: Es el código de red de tu cuenta de Ad Manager 360.

  • CUSTOM_ASSET_KEY: Solo se usa para transmisiones en vivo. La clave del recurso personalizado que identifica tu evento de publicación de grupos de anuncios en Ad Manager 360. Tu manipulador de manifiestos o tu socio externo de Publicación de grupos de anuncios pueden crearlo.

  • API_KEY: Solo se usa para transmisiones en vivo. Es una clave de API opcional que puede ser necesaria para recuperar un ID de transmisión desde el SDK de DAI de IMA.

dai.html

<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <script src="dai.js"></script>
  <link rel="stylesheet" href="dai.css" type="text/css">
</head>
<body onLoad="initPlayer()">
  <h2>IMA DAI SDK Demo (HLS.JS)</h2>
    <video id="video"></video>
    <div id="ad-ui"></div>
</body>
</html>

dai.css

#video,
#ad-ui {
  width: 640px;
  height: 360px;
  position: absolute;
  top: 35px;
  left: 0;
}

#ad-ui {
  cursor: pointer;
}

dai.js

var BACKUP_STREAM =
    'https://storage.googleapis.com/interactive-media-ads/media/bbb.m3u8'

// Stream Config.
const STREAM_URL = "https://encodersim.sandbox.google.com/masterPlaylist/...&stream_id=[[STREAMID]]";
const NETWORK_CODE = "51636543";
const CUSTOM_ASSET_KEY = "google-sample";
const API_KEY = "";

var hls = new Hls(); // hls.js video player
var videoElement;
var adUiElement;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
}

Carga el SDK de DAI de IMA

A continuación, agrega el framework de DAI con una etiqueta de secuencia de comandos en dai.html, antes de la etiqueta para dai.js.

dai.html

<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
  <script type="text/javascript" src="//imasdk.googleapis.com/js/sdkloader/ima3_dai.js"></script>
  <script src="dai.js"></script>
  <link rel="stylesheet" href="dai.css" type="text/css">
</head>
...

Inicializa StreamManager y realiza una solicitud de transmisión en vivo o de VOD

Publicación de pods de transmisión en vivo

Para solicitar un conjunto de anuncios, crea un ima.dai.api.StreamManager, que es responsable de solicitar y administrar las transmisiones de DAI. El constructor toma un elemento de video y la instancia resultante toma un elemento de la IU del anuncio para controlar las interacciones con el anuncio.

Luego, define una función para solicitar la transmisión en vivo de la publicación de pods. Esta función primero crea un PodStreamRequest, lo configura con los parámetros de streamRequest proporcionados en el paso 2 y, luego, llama a streamManager.requestStream() con ese objeto de solicitud.

dai.js

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)

  requestLivePodStream(NETWORK_CODE, CUSTOM_ASSET_KEY, API_KEY);
}

function requestLivePodStream(networkCode, customAssetKey, apiKey) {
  // clear HLS.js instance, if in use
  if (hls) {
    hls.destroy();
  }

  // Generate a Pod Serving live Stream Request
  const streamRequest = new google.ima.dai.api.PodStreamRequest();
  streamRequest.networkCode = networkCode;
  streamRequest.customAssetKey = customAssetKey;
  streamRequest.apiKey = apiKey;
  streamRequest.format = 'hls';
  streamManager.requestStream(streamRequest);
}

Publicación de grupos de anuncios de VOD

Para solicitar un conjunto de anuncios, crea un ima.dai.api.StreamManager, que es responsable de solicitar y administrar las transmisiones de DAI. El constructor toma un elemento de video y la instancia resultante toma un elemento de la IU del anuncio para controlar las interacciones con el anuncio.

Luego, define una función para solicitar la transmisión de VOD de la entrega de pods. Esta función primero crea un PodVodStreamRequest, lo configura con los parámetros de streamRequest proporcionados en el paso 2 y, luego, llama a streamManager.requestStream() con ese objeto de solicitud.

dai.js

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement)

  requestVodPodStream(NETWORK_CODE);
}

function requestVodPodStream(networkCode) {
  // clear HLS.js instance, if in use
  if (hls) {
    hls.destroy();
  }

  // Generate a Pod Serving VOD Stream Request
  const streamRequest = new google.ima.dai.api.PodVodStreamRequest();
  streamRequest.networkCode = networkCode;
  streamRequest.format = 'hls';
  streamManager.requestStream(streamRequest);
}

Controla los eventos de transmisión

Publicación de pods de transmisión en vivo

A continuación, implementa objetos de escucha de eventos para los eventos de video principales. En este ejemplo, se controlan los eventos STREAM_INITIALIZED, ERROR, AD_BREAK_STARTED y AD_BREAK_ENDED llamando a una función onStreamEvent(). Esta función controla la carga y los errores de la transmisión, así como inhabilita los controles del reproductor mientras se reproduce un anuncio, lo que requiere el SDK. Cuando se carga la transmisión, el reproductor de video carga y reproduce la URL proporcionada con una función loadStream().

dai.js

var isAdBreak;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
  
  streamManager.addEventListener(
    [google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
    google.ima.dai.api.StreamEvent.Type.ERROR,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
    onStreamEvent,
    false);
...
function onStreamEvent(e) {
  switch (e.type) {
    case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
      console.log('Stream initialized');
      loadStream(e.getStreamData().streamId);
      break;
    case google.ima.dai.api.StreamEvent.Type.ERROR:
      console.log('Error loading stream, playing backup stream.' + e);
      loadStream('');
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
      console.log('Ad Break Started');
      isAdBreak = true;
      videoElement.controls = false;
      adUiElement.style.display = 'block';
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
      console.log('Ad Break Ended');
      isAdBreak = false;
      videoElement.controls = true;
      adUiElement.style.display = 'none';
      break;
    default:
      break;
  }
}

function loadStream(streamID) {
  var url;
  if(streamID) {
    url = STREAM_URL.replace('[[STREAMID]]', streamID);
  } else {
    console.log('Stream Initialization Failed');
    url = BACKUP_STREAM;
  }
  console.log('Loading:' + url);
  hls.loadSource(url);
  hls.attachMedia(videoElement);
}

Publicación de grupos de anuncios de VOD

A continuación, implementa objetos de escucha de eventos para los eventos de video principales. En este ejemplo, se controlan los eventos STREAM_INITIALIZED, LOADED, ERROR, AD_BREAK_STARTED y AD_BREAK_ENDED llamando a una función onStreamEvent(). Esta función controla la carga y los errores de la transmisión, así como inhabilita los controles del reproductor mientras se reproduce un anuncio, lo que requiere el SDK.

Además, las transmisiones de entrega de pods de VOD requieren llamar a StreamManager.loadStreamMetadata() en respuesta al evento STREAM_INITIALIZED. También debes solicitar una URL de transmisión a tu socio de tecnología de video (VTP). Una vez que la llamada a loadStreamMetadata() se realiza correctamente, activa un evento LOADED, en el que debes llamar a una función loadStream() con la URL de la transmisión para cargarla y reproducirla.

var isAdBreak;

function initPlayer() {
  videoElement = document.getElementById('video');
  adUiElement = document.getElementById('adUi');
  streamManager = new google.ima.dai.api.StreamManager(videoElement, adUiElement);
  
  streamManager.addEventListener(
    [google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED,
    google.ima.dai.api.StreamEvent.Type.ERROR,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED,
    google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED],
    onStreamEvent,
    false);
...
function onStreamEvent(e) {
  switch (e.type) {
    case google.ima.dai.api.StreamEvent.Type.STREAM_INITIALIZED:
      const streamId = e.getStreamData().streamId;
      // 'vtpInterface' is a place holder for your own video technology
      //  partner (VTP) API calls.
      vtpInterface.requestStreamURL({
        'streamId': streamId,
      })
      .then( (vtpStreamUrl) => {
        streamUrl = vtpStreamUrl;
        streamManager.loadStreamMetadata();
      }, (error) => {
        // Handle the error.
      });
      break;
    case google.ima.dai.api.StreamEvent.Type.LOADED:
      loadStream(streamUrl);
      break;
    case google.ima.dai.api.StreamEvent.Type.ERROR:
      console.log('Error loading stream, playing backup stream.' + e);
      loadStream();
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_STARTED:
      console.log('Ad Break Started');
      isAdBreak = true;
      videoElement.controls = false;
      adUiElement.style.display = 'block';
      break;
    case google.ima.dai.api.StreamEvent.Type.AD_BREAK_ENDED:
      console.log('Ad Break Ended');
      isAdBreak = false;
      videoElement.controls = true;
      adUiElement.style.display = 'none';
      break;
    default:
      break;
  }
}

function loadStream(url) {
  if(url) {
    console.log('Loading:' + url);
    hls.loadSource(url);
  } else {
    console.log('Stream Initialization Failed');
    hls.loadSource(BACKUP_STREAM);
  }
  hls.attachMedia(videoElement);
}

Controla los metadatos de transmisiones

En este paso, implementarás objetos de escucha de eventos para que los metadatos notifiquen al SDK cuando ocurran eventos de anuncios. La detección de eventos de metadatos en la transmisión puede variar según el formato de transmisión (HLS o DASH), el tipo de transmisión (transmisión en vivo o VOD), el tipo de reproductor y el tipo de backend de DAI que se use. Consulta nuestra guía de metadatos programados para obtener más información.

Formato de transmisión HLS (transmisiones en vivo y de VOD, reproductor HLS.js)

Si usas un reproductor HLS.js, escucha el evento FRAG_PARSING_METADATA de HLS.js para obtener metadatos ID3 y pasarlos al SDK con StreamManager.processMetadata().

Para reproducir el video automáticamente después de que todo esté cargado y listo, escucha el evento MANIFEST_PARSED de HLS.js para activar la reproducción.

function loadStream(streamID) {
  hls.loadSource(url);
  hls.attachMedia(videoElement);
  
  // Timed metadata is passed HLS stream events to the streamManager.
  hls.on(Hls.Events.FRAG_PARSING_METADATA, parseID3Events);
  hls.on(Hls.Events.MANIFEST_PARSED, startPlayback);
}

function parseID3Events(event, data) {
  if (streamManager && data) {
    // For each ID3 tag in the metadata, pass in the type - ID3, the
    // tag data (a byte array), and the presentation timestamp (PTS).
    data.samples.forEach((sample) => {
      streamManager.processMetadata('ID3', sample.data, sample.pts);
    });
  }
}

function startPlayback() {
  console.log('Video Play');
  videoElement.play();
}

DASH.js (formato de transmisiones DASH, tipo de transmisión en vivo y VOD)

Si usas un reproductor DASH.js, debes usar cadenas diferentes para escuchar metadatos ID3 para transmisiones en vivo o VOD:

  • Transmisiones en vivo: 'https://developer.apple.com/streaming/emsg-id3'
  • Transmisiones de VOD: 'urn:google:dai:2018'

Pasa los metadatos ID3 al SDK con StreamManager.processMetadata().

Para mostrar automáticamente los controles de video después de que todo esté cargado y listo, escucha el evento MANIFEST_LOADED de DASH.js.

const googleLiveSchema = 'https://developer.apple.com/streaming/emsg-id3';
const googleVodSchema = 'urn:google:dai:2018';
dashPlayer.on(googleLiveSchema, processMetadata);
dashPlayer.on(googleVodSchema, processMetadata);
dashPlayer.on(dashjs.MediaPlayer.events.MANIFEST_LOADED, loadlistener);

function processMetadata(metadataEvent) {
  const messageData = metadataEvent.event.messageData;
  const timestamp = metadataEvent.event.calculatedPresentationTime;

  // Use StreamManager.processMetadata() if your video player provides raw
  // ID3 tags, as with dash.js.
  streamManager.processMetadata('ID3', messageData, timestamp);
}

function loadlistener() {
  showControls();

  // This listener must be removed, otherwise it triggers as addional
  // manifests are loaded. The manifest is loaded once for the content,
  // but additional manifests are loaded for upcoming ad breaks.
  dashPlayer.off(dashjs.MediaPlayer.events.MANIFEST_LOADED, loadlistener);
}

Shaka Player con transmisiones en vivo (formato de transmisiones DASH)

Si usas el reproductor Shaka para la reproducción de transmisiones en vivo, usa la cadena 'emsg' para escuchar eventos de metadatos. Luego, usa los datos del mensaje del evento en tu llamada a StreamManager.onTimedMetadata().

shakaPlayer.addEventListener('emsg', (event) => onEmsgEvent(event));

function onEmsgEvent(metadataEvent) {
  // Use StreamManager.onTimedMetadata() if your video player provides
  // processed metadata, as with Shaka player livestreams.
  streamManager.onTimedMetadata({'TXXX': metadataEvent.detail.messageData});
}

Shaka Player con transmisiones de VOD (formato de transmisiones DASH)

Si usas el reproductor Shaka para la reproducción de transmisiones de VOD, usa la cadena 'timelineregionenter' para escuchar eventos de metadatos. Luego, usa los datos del mensaje del evento en tu llamada a StreamManager.processMetadata() con la cadena 'urn:google:dai:2018'.

shakaPlayer.addEventListener('timelineregionenter', (event) => onTimelineEvent(event));

function onTimelineEvent(metadataEvent) {
  const detail = metadataEvent.detail;
  if ( detail.eventElement.attributes &&
       detail.eventElement.attributes['messageData'] &&
       detail.eventElement.attributes['messageData'].value ) {
        const mediaId = detail.eventElement.attributes['messageData'].value;
        const pts = detail.startTime;
        // Use StreamManager.processMetadata() if your video player provides raw
        // ID3 tags, as with Shaka player VOD streams.
        streamManager.processMetadata('urn:google:dai:2018', mediaId, pts);
       }
}

Controla eventos del jugador

Agrega objetos de escucha de eventos a los eventos pause y start del elemento de video para permitir que el usuario reanude la reproducción cuando el SDK se detenga durante las pausas publicitarias.

function loadStream(streamUrl) {
  ...
  
  videoElement.addEventListener('pause', onStreamPause);
  videoElement.addEventListener('play', onStreamPlay);
}

function onStreamPause() {
  console.log('paused');
  if (isAdBreak) {
    videoElement.controls = true;
    adUiElement.style.display = 'none';
  }
}

function onStreamPlay() {
  console.log('played');
  if (isAdBreak) {
    videoElement.controls = false;
    adUiElement.style.display = 'block';
  }
}

Eso es todo. Ahora solicitas y muestras anuncios en una transmisión de Publicación de grupos de anuncios con el SDK de DAI de IMA para HTML5. Para obtener información sobre las funciones más avanzadas del SDK, consulta las otras guías o los ejemplos en GitHub.