Cómo controlar metadatos temporizados en transmisiones de DAI lineales

El SDK de inserción de anuncios dinámicos (DAI) de anuncios multimedia interactivos (IMA) se basa información de metadatos incorporada en los segmentos de medios de la transmisión (metadatos en banda), o en el archivo de manifiesto de transmisión (metadatos en manifiesto) para rastrear posiciones y eventos de anuncios del cliente. Los metadatos se envían en diferentes formatos, según el tipo de transmisión que se esté reproduciendo.

El reproductor de video recibe metadatos temporizados en lotes. Según el jugador, los metadatos pueden aparecer en el momento programado o por lotes. Cada metadato tiene una marca de tiempo de presentación asociada (PTS) para cuándo activa.

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

onTimedMetadata

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

  • metadata: Un objeto que contiene una clave de TXXX con una cadena asociada con el prefijo google_.
processMetadata

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

  • type: Es una cadena que contiene el tipo de evento que se procesa. Aceptado los valores son ID3 para HLS o urn:google:dai:2018 para DASH
  • data: un valor de cadena con el prefijo google_ o un array de bytes que se decodifica en este tipo de cadena.
  • timestamp: Es la marca de tiempo, en segundos, de cuando se deben procesar los datos.

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

Transmisiones HLS MPEG2TS

Las transmisiones HLS de DAI lineales que usan los segmentos MPEG2TS pasan los metadatos temporizados al de video mediante etiquetas ID3 dentro de la banda. Estas etiquetas ID3 están incorporadas MPEG2TS y se les asigna el nombre de campo TXXX (para texto personalizado definido por el usuario contenido).

Reproducción en Safari

Safari procesa las etiquetas ID3 automáticamente, como pistas ocultas, por lo que los eventos de cuechange se activan en el momento correcto para procesar cada metadato. Está bien pasar todos los metadatos al SDK de IMA de DAI, independientemente de su contenido o tipo. Irrelevante los metadatos se filtra 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 del ID3 de los arrays de bytes a las cadenas y no desplaza los eventos a sus PTS correspondientes. No es necesario para decodificar los datos de muestra de un array de bytes a una cadena, o para filtrar etiquetas ID3 irrelevantes, ya que el SDK de IMA de DAI 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 HLS CMAF

Transmisiones HLS de DAI lineales con el pase de Common Media Application Framework (CMAF) metadatos temporizados a través de cuadros eMSGv1 en banda después de ID3 hasta estándar de CMAF. Estos cuadros de eMSG incorporados al comienzo de cada segmento de medios, y cada eMSG ID3 contiene un PTS en relación con la última discontinuidad de la transmisión.

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

Reproducción en Safari

Safari trata a ID3 mediante metadatos de eMSG como eventos de seudo ID3, y los proporciona lotes, automáticamente, como un segmento oculto, de modo que los eventos de cambio de posición se se activan en el momento correcto para procesar cada parte de los metadatos. Está bien Pasen todos los metadatos al SDK de IMA de DAI, ya sea que sean relevantes para el tiempo o no. Cualquiera los 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 al ID3 mediante los metadatos de eMSG como seudoID3. eventos y proporcionarlos por lotes a través del evento FRAG_PARSING_METADATA como un array de muestras. HLS.js no traduce los datos de ID3 de los arrays de bytes a cadenas y no desplaza eventos a sus PTS correspondientes. No es necesario para decodificar los datos de muestra de un array de bytes a una cadena, ya que el SDK de IMA de DAI realiza la 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 DASH

Las transmisiones lineales de DAI DASH pasan metadatos como eventos de manifiesto en una transmisión de eventos con el valor personalizado de schemeIdUri (urn:google:dai:2018). Cada evento de estas contiene una carga útil de texto y la PTS.

DASH.js

Dash.js proporciona controladores de eventos personalizados con el nombre del valor schemeIdUri de cada uno flujo de eventos. Estos controladores personalizados se activan por lotes y tú debes procesar el valor PTS para cronometrar adecuadamente el evento. El SDK de IMA de 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);
});
...

Reproductor de shaka

Shaka Player muestra eventos como parte de su evento timelineregionenter. Venc. a una incompatibilidad de formato con Shaka Player, el valor de los metadatos debe ser recuperado sin procesar, a través de la propiedad de detalles eventElement.attributes['messageData'].value

Por ejemplo:

player.addEventListener('timelineregionenter', function(event) {
  const detail = event.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;
    streamManager.processMetadata("urn:google:dai:2018", mediaId, pts);
  }
});
...

Publicación de grupos de anuncios

En la entrega de Pods, hay diferentes parámetros de configuración para pasar metadatos en función de los siguientes criterios:

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

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 cuando 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 los metadatos de ID3 para transmisiones en vivo o VOD transmisiones:

  • 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 cuando todo está cargado y listo, haz lo siguiente: 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 de Shaka para transmisión 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 de Shaka para Reproducción de transmisión de VOD, usa la cadena 'timelineregionenter' para escuchar los eventos de metadatos. Luego, usa los datos del mensaje del evento en tu llamada para 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);
       }
}