Administra metadatos temporizados

Selecciona la plataforma: HTML5 Roku

El SDK de inserción de anuncios dinámicos (DAI) de los SDKs de anuncios multimedia interactivos (IMA) se basa en la información de metadatos incorporada en los segmentos de medios de la transmisión (metadatos integrados) o en el archivo de manifiesto de la transmisión (metadatos del manifiesto) para hacer un seguimiento de las posiciones de los usuarios y los eventos de anuncios del cliente. Los metadatos se envían en diferentes formatos, según el tipo de transmisión que se reproduzca.

El reproductor de video recibe metadatos cronometrados en lotes. Según el reproductor, los metadatos pueden aparecer en el horario programado o en lotes. Cada cadena de metadatos tiene una marca de tiempo de presentación (PTS) asociada para el momento en que debe activarse.

Tu app es responsable de capturar los metadatos y reenviarlos al SDK de DAI de IMA. El SDK ofrece los siguientes métodos para pasar esta información:

onTimedMetadata

Este método reenvía al SDK las cadenas de metadatos que están listas para procesarse. Toma un solo argumento:

  • metadata: Es un objeto que contiene una clave de TXXX con un valor de cadena asociado que tiene el prefijo google_.
processMetadata

Este método programa cadenas de metadatos para que el SDK las procese después del PTS especificado. Toma los siguientes argumentos:

  • type: Es una cadena que contiene el tipo de evento que se procesa. Los valores aceptados son ID3 para HLS o urn:google:dai:2018 para DASH.
  • data: Puede ser un valor de cadena con el prefijo google_ o un array de bytes que sigue este formato ID3:u\0004u\000u\000u\0000TXXXu\0004u\000u\000u\0000google_xxxxxxxx.
  • timestamp: Es la marca de tiempo en segundos en la que se deben procesar los datos.

Cada tipo de transmisión compatible con el SDK de DAI de IMA usa una forma única de metadatos cronometrados, como se describe en las siguientes secciones.

Transmisiones MPEG2TS de HLS

Las transmisiones HLS de DAI lineal que usan segmentos MPEG2TS pasan metadatos cronometrados al reproductor de video a través de etiquetas ID3 integradas. Estas etiquetas ID3 están incorporadas en los segmentos MPEG2TS y se les asigna el nombre de campo TXXX (para contenido de texto personalizado definido por el usuario).

Reproducción en Safari

Safari procesa las etiquetas ID3 automáticamente, como una pista oculta, de modo que los eventos de cuechange se activan en el momento correcto para procesar cada fragmento de metadatos. Está bien pasar todos los metadatos al SDK de IMA de DAI, independientemente del contenido o el tipo. Los metadatos irrelevantes se filtran automáticamente.

Por ejemplo:

videoElement.textTracks.addEventListener('addtrack', (e) => {
  const track = e.track;
  if (track.kind === 'metadata') {
    track.mode = 'hidden';
    track.addEventListener('cuechange', () => {
      for (const cue of track.activeCues) {
        const metadata = {};
        metadata[cue.value.key] = cue.value.data;
        streamManager.onTimedMetadata(metadata);
      }
    });
  }
});
...

HLS.js

HLS.js proporciona etiquetas ID3 en lotes a través del evento FRAG_PARSING_METADATA, como un array de muestras. HLS.js no traduce los datos de ID3 de arrays de bytes a cadenas ni desplaza los eventos a sus PTS correspondientes. No es necesario decodificar los datos de muestra de un array de bytes a una cadena ni filtrar las etiquetas ID3 irrelevantes, ya que el SDK de DAI de IMA realiza esta decodificación y filtrado automáticamente.

Por ejemplo:

hls.on(Hls.Events.FRAG_PARSING_METADATA, (e, data) => {
  if (streamManager && data) {
    data.samples.forEach((sample) => {
      streamManager.processMetadata('ID3', sample.data, sample.pts);
    });
  }
});
...

Transmisiones CMAF de HLS

Las transmisiones HLS de DAI lineal que usan el marco de trabajo de Common Media Application Format (CMAF) pasan metadatos cronometrados a través de casillas eMSGv1 integradas según el estándar ID3 a través de CMAF. Estos cuadros eMSG se incorporan al principio de cada segmento de medios, y cada eMSG de ID3 contiene un PTS relativo a la última discontinuidad en el flujo.

A partir de la versión 1.2.0 de HLS.js, ambos reproductores sugeridos pasan ID3 a través de CMAF al usuario como si fueran etiquetas ID3. Por este motivo, los siguientes ejemplos son los mismos que para las transmisiones MPEG2TS de HLS. Sin embargo, es posible que no sea el caso con todos los reproductores, por lo que implementar la compatibilidad con transmisiones CMAF de HLS podría requerir un código único para analizar ID3 a través de eMSG.

Reproducción en Safari

Safari trata los ID3 a través de los metadatos de eMSG como pseudoeventos de ID3, y los proporciona en lotes, automáticamente, como una pista oculta, de modo que los eventos cuechange se activen en el momento correcto para procesar cada fragmento de metadatos. Está bien pasar todos los metadatos al SDK de DAI de IMA, ya sean relevantes para la sincronización o no. Todos los metadatos que no estén relacionados con la DAI se filtran automáticamente.

Por ejemplo:

videoElement.textTracks.addEventListener('addtrack', (e) => {
  const track = e.track;
  if (track.kind === 'metadata') {
    track.mode = 'hidden';
    track.addEventListener('cuechange', () => {
      for (const cue of track.activeCues) {
        const metadata = {};
        metadata[cue.value.key] = cue.value.data;
        streamManager.onTimedMetadata(metadata);
      }
    });
  }
});
...

HLS.js

A partir de la versión 1.2.0, HLS.js trata los metadatos de ID3 a través de eMSG como pseudoeventos de ID3, que se proporcionan en lotes, a través del evento FRAG_PARSING_METADATA, como un array de muestras. HLS.js no traduce los datos de ID3 de arrays de bytes a cadenas ni desplaza los eventos a sus PTS correspondientes. No es necesario decodificar los datos de muestra de un array de bytes a una cadena, ya que el SDK de DAI de IMA realiza esta decodificación automáticamente.

Por ejemplo:

hls.on(Hls.Events.FRAG_PARSING_METADATA, (e, data) => {
  if (streamManager && data) {
    data.samples.forEach((sample) => {
      streamManager.processMetadata('ID3', sample.data, sample.pts);
    });
  }
});
...

Transmisiones de DASH

Los flujos de DASH de DAI lineal pasan metadatos como eventos de manifiesto en un flujo de eventos con el valor personalizado schemeIdUri urn:google:dai:2018. Cada evento de estos flujos contiene una carga útil de texto y el PTS.

DASH.js

Dash.js proporciona controladores de eventos personalizados con el nombre del valor schemeIdUri de cada transmisión de eventos. Estos controladores personalizados se activan en lotes, por lo que depende de ti procesar el valor de PTS para cronometrar correctamente el evento. El SDK de IMA DAI puede controlar esto por ti con el método streamManager, processMetadata().

Por ejemplo:

const dash = dashjs.MediaPlayer().create();
dash.on('urn:google:dai:2018', (payload) => {
  const mediaId = payload.event.messageData;
  const pts = payload.event.calculatedPresentationTime;
  streamManager.processMetadata('urn:google:dai:2018', mediaId, pts);
});
...

Shaka Player

Shaka Player muestra eventos como parte de su evento timelineregionenter. Debido a una incompatibilidad de formato con Shaka Player, el valor de metadatos debe recuperarse sin procesar, a través de la propiedad de detalle eventNode.attributes['messageData'].

Por ejemplo:

player.addEventListener('timelineregionenter', function(event) {
  const detail = event.detail;
  if ( detail.eventNode.attributes &&
       detail.eventNode.attributes['messageData']) {
    const mediaId = detail.eventNode.attributes['messageData'];
    const pts = detail.startTime;
    streamManager.processMetadata("urn:google:dai:2018", mediaId, pts);
  }
});
...

Publicación de grupos de anuncios

En el caso de la publicación de Pods, existen diferentes configuraciones para pasar metadatos cronometrados según los siguientes criterios:

  • Tipo de transmisión en vivo o de VOD
  • Formato de transmisión HLS o DASH
  • El tipo de reproductor que se usa
  • Tipo de backend de DAI que se usa

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 metadatos ID3 y pasarlos al SDK con StreamManager.processMetadata().

Para reproducir automáticamente el video después de que todo se haya cargado y esté 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 detectar 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 se haya cargado y esté 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 los 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 Shaka Player para la reproducción de transmisiones de VOD, usa la cadena 'timelineregionenter' para escuchar los 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);
       }
}