Gestire i metadati a tempo negli stream DAI lineari

L'SDK Interactive Media Ads (IMA) Dynamic Ad Insertion (DAI) si basa su informazioni sui metadati incorporate nei segmenti multimediali dello stream (metadati in banda) o nel file manifest dello streaming (metadati in manifest) per monitorare le posizioni degli spettatori e gli eventi correlati agli annunci lato client. I metadati vengono inviati in diversi formati, a seconda del tipo di stream riprodotto.

Il video player riceve i metadati con temporizzazione in batch. A seconda del player, i metadati possono essere visualizzati all'ora pianificata o in batch. A ogni stringa di metadati è associato un timestamp di presentazione (PTS) che indica quando deve essere attivata.

È responsabilità della tua app acquisire i metadati e inoltrarli all'SDK DAI IMA. L'SDK offre i seguenti metodi per trasmettere queste informazioni:

onTimedMetadata

Questo metodo inoltra le stringhe di metadati pronte per l'elaborazione all'SDK. Richiede un singolo argomento:

  • metadata: un oggetto contenente una chiave TXXX con un valore di stringa associato che ha il prefisso google_.
processMetadata

Questo metodo pianifica l'elaborazione delle stringhe di metadati da parte dell'SDK dopo il PTS specificato. Accetta i seguenti argomenti:

  • type: una stringa contenente il tipo di evento in fase di elaborazione. I valori accettati sono ID3 per HLS o urn:google:dai:2018 per DASH
  • data: un valore di stringa con prefisso google_ o un array di byte che segue questo formatoID3:u\0004u\000u\000u\0000TXXXu\0004u\000u\000u\0000google_xxxxxxxx.
  • timestamp: il timestamp in secondi in cui devono essere elaborati i dati.

Ogni tipo di stream supportato dall'SDK IMA DAI utilizza una forma unica di metadati con temporizzazione, come descritto nelle sezioni seguenti.

Stream MPEG2TS HLS

Gli stream HLS DAI lineari che utilizzano i segmenti MPEG2TS trasmettono i metadati a tempo al video player tramite i tag ID3 in banda. Questi tag ID3 sono incorporati nei segmenti MPEG2TS e hanno il nome del campo TXXX (per i contenuti di testo personalizzati definiti dall'utente).

Riproduzione in Safari

Safari elabora automaticamente i tag ID3 come traccia nascosta, quindi gli eventi cuechange vengono attivati al momento giusto per elaborare ogni metadato. È consentito trasmettere tutti i metadati all'SDK IMA DAI, indipendentemente dal tipo di contenuti. I metadati irrilevanti vengono filtrati automaticamente.

Ecco un esempio:

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 fornisce i tag ID3 in batch tramite l'evento FRAG_PARSING_METADATA, come array di sample. HLS.js non traduce i dati ID3 da array di byte a stringhe e non compensa gli eventi con i relativi PTS corrispondenti. Non è necessario decodificare i dati di esempio dall'array di byte alla stringa o filtrare i tag ID3 irrilevanti, poiché l'SDK IMA DAI esegue questa decodifica e questo filtraggio automaticamente.

Ecco un esempio:

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

Stream CMAF HLS

Gli stream HLS DAI lineari che utilizzano il Common Media Application Framework (CMAF) trasmettono i metadati temporizzati tramite caselle eMSGv1 in banda seguendo lo standard ID3 tramite CMAF. Queste caselle eMSG sono incorporate all'inizio di ogni segmento multimediale e ogni eMSG ID3 contiene un PTS relativo all'ultima discontinuità nello stream.

A partire dalla versione 1.2.0 di HLS.js, entrambi i player suggeriti trasmettono l'ID3 tramite CMAF all'utente come se fossero tag ID3. Per questo motivo, i seguenti esempi sono gli stessi degli stream MPEG2TS HLS. Tuttavia, questo potrebbe non essere il caso di tutti i player, pertanto l'implementazione del supporto per gli stream HLS CMAF potrebbe richiedere un codice univoco per analizzare l'ID3 tramite eMSG.

Riproduzione in Safari

Safari tratta i metadati ID3 tramite eMSG come eventi pseudo ID3, fornendoli in batch, automaticamente, come traccia nascosta, in modo che gli eventi cuechange vengano attivati al momento giusto per elaborare ogni parte di metadati. È consentito trasmettere tutti i metadati all'SDK DAI IMA, indipendentemente dal fatto che siano pertinenti ai tempi o meno. Eventuali metadati non correlati ai DAI vengono filtrati automaticamente.

Ecco un esempio:

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 partire dalla versione 1.2.0, HLS.js tratta i metadati ID3 tramite eMSG come eventi pseudo ID3, fornendoli in batch tramite l'evento FRAG_PARSING_METADATA come array di sample. HLS.js non traduce i dati ID3 da array di byte a stringhe e non compensa gli eventi con i relativi PTS corrispondenti. Non è necessario decodificare i dati di esempio dall'array di byte alla stringa, poiché l'SDK IMA DAI esegue questa decodifica automaticamente.

Ecco un esempio:

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

Stream DASH

Gli stream DAI DASH lineari trasmettono i metadati come eventi manifest in uno stream di eventi con il valore personalizzato schemeIdUri urn:google:dai:2018. Ogni evento in questi flussi contiene un payload di testo e il PTS.

DASH.js

Dash.js fornisce gestori eventi personalizzati denominati in base al valore schemeIdUri di ogni stream di eventi. Questi gestori personalizzati vengono attivati in batch, quindi sta a te elaborare il valore PTS per impostare correttamente la data e l'ora dell'evento. L'SDK IMA DAI può gestire questo compito per te, con il metodo streamManager, processMetadata().

Ecco un esempio:

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 mostra gli eventi come parte dell'evento timelineregionenter. A causa di un'incompatibilità di formattazione con Shaka Player, il valore dei metadati deve essere recuperato in formato non elaborato tramite la proprietà detaileventNode.attributes['messageData'].

Ecco un esempio:

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);
  }
});
...

Pubblicazione dei pod

Per la pubblicazione di podcast, esistono diverse configurazioni per il passaggio dei metadati con temporizzazione in base ai seguenti criteri:

  • Tipo di stream live o VOD
  • Formato dello stream HLS o DASH
  • Il tipo di player utilizzato
  • Il tipo di backend DAI utilizzato

Formato dello stream HLS (live streaming e VOD, player HLS.js)

Se utilizzi un player HLS.js, ascolta l'evento FRAG_PARSING_METADATA HLS.js per ottenere i metadati ID3 e trasmetterli all'SDK con StreamManager.processMetadata().

Per riprodurre automaticamente il video dopo che tutto è stato caricato e pronto, ascolta l'evento MANIFEST_PARSED di HLS.js per attivare la riproduzione.

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 degli stream DASH, tipo di stream live e VOD)

Se utilizzi un player DASH.js, devi utilizzare stringhe diverse per ascoltare i metadati ID3 per gli stream live o VOD:

  • Live streaming: 'https://developer.apple.com/streaming/emsg-id3'
  • Stream di VOD: 'urn:google:dai:2018'

Passa i metadati ID3 all'SDK con StreamManager.processMetadata().

Per mostrare automaticamente i controlli video dopo che tutto è stato caricato e reso disponibile, ascolta l'evento MANIFEST_LOADED di 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 live streaming (formato stream DASH)

Se utilizzi Shaka Player per la riproduzione di live streaming, utilizza la stringa 'emsg' per ascoltare gli eventi relativi ai metadati. Poi, utilizza i dati del messaggio dell'evento nella chiamata 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 stream VOD (formato stream DASH)

Se utilizzi Shaka Player per la riproduzione di stream VOD, utilizza la stringa 'timelineregionenter' per ascoltare gli eventi dei metadati. Poi, utilizza i dati del messaggio dell'evento nella chiamata a StreamManager.processMetadata() con la stringa '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);
       }
}