Zeitgesteuerte Metadaten in linearen Streams für die dynamische Anzeigenbereitstellung verarbeiten

Das Interactive Media Ads (IMA) Dynamic Ad Inserting (DAI) SDK stützt sich auf Metadateninformationen, die in die Mediasegmente des Streams (In-Band-Metadaten) oder in die Streaming-Manifestdatei (in Manifest-Metadaten) eingebettet sind, um die Position der Betrachter und clientseitige Anzeigenereignisse zu erfassen. Metadaten werden je nach Art des wiedergegebenen Streams in verschiedenen Formaten gesendet.

Der Videoplayer empfängt Metadaten mit Zeitstempeln gestaffelt. Abhängig vom Player können Metadaten zur geplanten Zeit oder in Batches angezeigt werden. Jedem Metadatenstring ist ein PTS (Präsentationszeitstempel) zugeordnet, der angibt, wann er ausgelöst werden soll.

Ihre App ist dafür verantwortlich, Metadaten zu erfassen und an das IMA DAI SDK weiterzuleiten. Das SDK bietet die folgenden Methoden zur Weitergabe dieser Informationen:

onTimedMetadata

Diese Methode leitet Metadatenstrings, die zur Verarbeitung bereit sind, an das SDK weiter. Dafür wird ein einziges Argument verwendet:

  • metadata: ein Objekt, das den Schlüssel TXXX mit einem verknüpften Stringwert enthält, dem google_ vorangestellt ist.
processMetadata

Mit dieser Methode wird die Verarbeitung von Metadatenstrings durch das SDK nach dem angegebenen PTS geplant. Folgende Argumente werden verwendet:

  • type: ein String mit dem Typ des zu verarbeitenden Ereignisses. Zulässige Werte sind ID3 für HLS oder urn:google:dai:2018 für DASH
  • data: entweder ein Stringwert mit dem Präfix google_ oder ein Bytearray, das in einen solchen String decodiert wird.
  • timestamp: der Zeitstempel in Sekunden, zu dem Daten verarbeitet werden sollen.

Für jeden Streamtyp, der vom IMA DAI SDK unterstützt wird, wird eine spezifische Form von zeitgesteuerten Metadaten verwendet, wie in den folgenden Abschnitten beschrieben.

HLS MPEG2TS-Streams

HLS-Streams bei der linearen dynamischen Anzeigenbereitstellung, die MPEG2TS-Segmente verwenden, geben zeitgesteuerte Metadaten über In-Band-ID3-Tags an den Videoplayer weiter. Diese ID3-Tags sind in die MPEG2TS-Segmente eingebettet und erhalten den Feldnamen TXXX (für benutzerdefinierten Textinhalt).

Wiedergabe in Safari

Safari verarbeitet ID3-Tags automatisch als verborgenen Track. Daher werden Cuechange-Ereignisse zur richtigen Zeit ausgelöst, um die einzelnen Metadaten zu verarbeiten. Sie können alle Metadaten unabhängig von Inhalt oder Typ an das IMA DAI SDK übergeben. Irrelevante Metadaten werden automatisch herausgefiltert.

Beispiel:

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 stellt ID3-Tags in Batches über das Ereignis FRAG_PARSING_METADATA als Array von Beispielen bereit. HLS.js übersetzt die ID3-Daten nicht aus Bytearrays in Strings und verschiebt Ereignisse nicht auf ihren entsprechenden PTS-Wert. Es ist nicht erforderlich, die Beispieldaten von Bytearray in String zu decodieren oder irrelevante ID3-Tags herauszufiltern, da das IMA DAI SDK diese Decodierung und Filterung automatisch durchführt.

Beispiel:

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

HLS-CMAF-Streams

HLS-Streams der linearen dynamischen Anzeigenbereitstellung, die das Common Media Application Framework (CMAF) verwenden, übergeben zeitgesteuerte Metadaten gemäß dem Standard ID3 bis CMAF über In-Band-eMSGv1-Felder. Diese eMSG-Felder sind am Anfang jedes Mediensegments eingebettet, wobei jede ID3-eMSG einen PTS relativ zur letzten Unterbrechung im Stream enthält.

Ab Version 1.2.0 von HLS.js übergeben beide unserer vorgeschlagenen Spieler ID3 wie ID3-Tags über CMAF an den Nutzer. Aus diesem Grund sind die folgenden Beispiele dieselben wie für HLS MPEG2TS-Streams. Dies ist jedoch möglicherweise nicht bei allen Spielern der Fall. Für die Implementierung der Unterstützung für HLS-CMAF-Streams kann also ein eindeutiger Code zum Parsen von ID3 über eMSG erforderlich sein.

Wiedergabe in Safari

Safari behandelt ID3- bis eMSG-Metadaten wie Pseudo-ID3-Ereignisse und stellt sie automatisch in Batches als versteckten Track bereit, sodass cuechange-Ereignisse zur richtigen Zeit ausgelöst werden, um jedes Metadatenelement zu verarbeiten. Sie können alle Metadaten an das IMA DAI SDK übergeben, unabhängig davon, ob sie für den zeitlichen Ablauf relevant sind oder nicht. Alle nicht mit der dynamischen Anzeigenbereitstellung zusammenhängenden Metadaten werden automatisch herausgefiltert.

Beispiel:

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

Ab Version 1.2.0 behandelt HLS.js ID3- bis eMSG-Metadaten als Pseudo-ID3-Ereignisse und stellt sie in Batches über das Ereignis FRAG_PARSING_METADATA als Array von Beispielen bereit. HLS.js übersetzt die ID3-Daten nicht aus Bytearrays in Strings und verschiebt Ereignisse nicht auf ihren entsprechenden PTS-Wert. Die Decodierung der Beispieldaten von Byte-Array zu String ist nicht erforderlich, da das IMA DAI SDK automatisch decodiert wird.

Beispiel:

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

DASH-Streams

DASH-Streams für die lineare dynamische Anzeigenbereitstellung übergeben Metadaten als Manifestereignisse in einem Ereignisstream mit dem benutzerdefinierten schemeIdUri-Wert urn:google:dai:2018. Jedes Ereignis in diesen Streams enthält eine Textnutzlast und den PTS.

DASH.js

Dash.js bietet benutzerdefinierte Event-Handler, die nach dem schemaIdUri-Wert jedes Ereignisstreams benannt sind. Diese benutzerdefinierten Handler werden in Batches ausgelöst. Sie müssen dann den PTS-Wert verarbeiten, damit das Ereignis korrekt erfasst wird. Das IMA DAI SDK übernimmt dies über die streamManager-Methode processMetadata().

Beispiel:

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-Spieler

Shaka Player zeigt Ereignisse als Teil seines timelineregionenter-Ereignisses an. Aufgrund einer Formatierungsinkompatibilität mit Shaka Player muss der Metadatenwert im Rohformat über das Detailattribut eventElement.attributes['messageData'].value abgerufen werden.

Beispiel:

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

Pod-Auslieferung

Für die Pod-Bereitstellung gibt es je nach den folgenden Kriterien unterschiedliche Konfigurationen für die Weitergabe von zeitgesteuerten Metadaten:

  • Live- oder VOD-Streamtyp
  • HLS- oder DASH-Stream-Format
  • Der verwendete Playertyp
  • Der Typ des verwendeten Back-Ends für die dynamische Anzeigenbereitstellung

HLS-Streamformat (Live- und VOD-Streams, HLS.js-Player)

Wenn Sie einen HLS.js verwenden, warten Sie auf das HLS.js-Ereignis FRAG_PARSING_METADATA, um ID3-Metadaten abzurufen und sie mit StreamManager.processMetadata() an das SDK zu übergeben.

Wenn das Video automatisch wiedergegeben werden soll, nachdem alles geladen wurde und bereit ist, warten Sie auf das HLS.js-Ereignis MANIFEST_PARSED, um die Wiedergabe auszulösen.

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 (DASH-Streamformat, Live- und VOD-Streamtyp)

Wenn Sie einen DASH.js-Player verwenden, müssen Sie verschiedene Strings verwenden, um ID3-Metadaten für Live- oder VOD-Streams zu überwachen:

  • Livestreams: 'https://developer.apple.com/streaming/emsg-id3'
  • VOD-Streams: 'urn:google:dai:2018'

Übergeben Sie die ID3-Metadaten mit StreamManager.processMetadata() an das SDK.

Wenn die Videosteuerelemente automatisch angezeigt werden sollen, nachdem alles geladen wurde und bereit ist, warten Sie auf das MANIFEST_LOADED-Ereignis von 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 mit Livestreams (DASH-Stream-Format)

Wenn Sie den Shaka-Player für die Livestreamwiedergabe verwenden, verwenden Sie den String 'emsg', um auf Metadatenereignisse zu warten. Verwenden Sie dann die Daten zu Ereignisnachrichten in Ihrem StreamManager.onTimedMetadata()-Anruf.

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 mit VOD-Streams (DASH-Stream-Format)

Wenn Sie den Shaka-Player für die VOD-Streamwiedergabe verwenden, verwenden Sie den String 'timelineregionenter', um auf Metadatenereignisse zu warten. Verwenden Sie dann die Daten zu Ereignisnachrichten in Ihrem Aufruf von StreamManager.processMetadata() mit dem String '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);
       }
}