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

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

Seleccione la solución de DAI que le interesa

DAI de publicación de grupos de anuncios

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 de VOD mediante el SDK de DAI de IMA para HTML5 con un reproductor de video que se basa en hls.js para la reproducción. Si quieres ver o seguir una integración de muestra completa que sea compatible con HLS.js y Safari Playback, consulta el ejemplo de entrega de Pods de HLS. Para obtener asistencia de DASH.js, consulta el ejemplo de entrega de pods de DASH. Puedes descargar estas apps de ejemplo desde la página de versiones de GitHub de la DAI para HTML5.

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

La implementación de la publicación de grupos 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 para los servidores de publicidad de Google. Las solicitudes especifican un código de red, y PodStreamRequest también requiere una clave de recurso personalizada 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 por Internet 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 u otro entorno de desarrollo alojado para usar para pruebas

Cómo configurar un entorno de desarrollo

Dado que el SDK carga las dependencias con el mismo protocolo que la página desde la que se carga, debes usar un servidor web para probar la app. La forma más simple de iniciar un servidor de desarrollo local es usar el servidor integrado de Python.

  1. Con una línea de comandos desde el directorio que contiene el 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.

Cómo crear un reproductor de video simple

Primero, modifica dai.html para crear un elemento de video HTML5 simple y un div para usar en los elementos de la IU del anuncio. Además, 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 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 copia de seguridad en caso de que el proceso de anuncios encuentre un error irrecuperable.

  • STREAM_URL: Solo se usa en transmisiones en vivo. Es la URL de transmisión de video por Internet que proporciona tu manipulador de manifiestos o un socio externo que usa la publicación de grupos de anuncios. Es necesario que insertes el ID de transmisión proporcionado por el SDK de DAI de IMA antes de realizar una solicitud. En este caso, la URL de transmisión incluye un marcador de posición, [[STREAMID]], que se reemplaza por el ID de 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 en transmisiones en vivo. La clave del recurso personalizada que identifica el evento de publicación de tu Pod en Ad Manager 360. Tu manipulador de manifiestos o un socio externo de publicación de Pods puede crearlo.

  • API_KEY: Solo se usa en transmisiones en vivo. Es una clave de API opcional que se puede requerir 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 IMA de DAI

A continuación, agrega el marco de trabajo 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 grupos de anuncios de transmisión en vivo

Para solicitar un conjunto de anuncios, crea un ima.dai.api.StreamManager, que sea responsable de solicitar y administrar 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 los anuncios.

Luego, define una función para solicitar la transmisión en vivo del Pod. Esta función primero crea un PodStreamRequest, lo configura con los parámetros de streamRequest que se proporcionaron 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 VOD

Para solicitar un conjunto de anuncios, crea un ima.dai.api.StreamManager, que sea responsable de solicitar y administrar 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 los anuncios.

Luego, define una función para solicitar el Pod que entrega una transmisión de VOD. Esta función primero crea un PodVodStreamRequest, lo configura con los parámetros de streamRequest que se proporcionaron 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 eventos de transmisión

Publicación de grupos de anuncios de transmisión en vivo

A continuación, implementa objetos de escucha de eventos para los eventos de video principales. En este ejemplo, se usan los eventos STREAM_INITIALIZED, ERROR, AD_BREAK_STARTED y AD_BREAK_ENDED mediante una llamada a una función onStreamEvent(). Esta función controla la carga y los errores de las transmisiones, además de inhabilitar los controles del reproductor mientras se reproduce un anuncio, que es un requisito del 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 VOD

A continuación, implementa objetos de escucha de eventos para los eventos de video principales. En este ejemplo, se usan 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 transmisiones, además de inhabilitar los controles del reproductor mientras se reproduce un anuncio, lo cual es necesario para el SDK.

Además, las transmisiones de entrega de Pods de VOD requieren que se llame 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, se activa un evento LOADED, en el que debes llamar a una función loadStream() con la URL de transmisión para cargar y reproducir la transmisión.

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 la transmisión

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

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

Si usas un reproductor HLS.js, escucha el evento FRAG_PARSING_METADATA de HLS.js para obtener los metadatos de 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 diferentes cadenas para escuchar los metadatos ID3 de las transmisiones en vivo o de VOD:

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

Pasa los metadatos de 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 Shaka Player para la reproducción de transmisiones en vivo, usa la cadena 'emsg' para escuchar eventos de metadatos. Luego, usa los datos del mensaje de evento en la 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});
}

Reproductor Shaka con transmisiones VOD (formato de transmisiones DASH)

Si usas el Shaka Player para la reproducción de transmisiones de VOD, usa la cadena 'timelineregionenter' para escuchar eventos de metadatos. Luego, usa los datos del mensaje de 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);
       }
}

Cómo controlar eventos del reproductor

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';
  }
}

Listo. 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 funciones del SDK más avanzadas, consulta las otras guías o las muestras en GitHub.