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

Das IMA SDK (Interactive Media Ads) für die dynamische Anzeigenbereitstellung (Dynamic Ad Insertion, DAI) verwendet Metadaten, die in den Mediensegmenten des Streams (In-Band-Metadaten) oder in der Streaming-Manifestdatei (In-Manifest-Metadaten) eingebettet sind, um die Positionen der Zuschauer und clientseitige Anzeigenereignisse zu erfassen. Metadaten werden je nach Art des wiedergegebenen Streams in verschiedenen Formaten gesendet.

Der Videoplayer empfängt getaktete Metadaten in Batches. Je nach Wiedergabegerät werden Metadaten zum geplanten Zeitpunkt oder in Batches angezeigt. Jedem Metadatenstring ist ein Präsentationszeitstempel (PTS) 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, um diese Informationen zu übergeben:

onTimedMetadata

Mit dieser Methode werden Metadatenstrings, die zur Verarbeitung bereit sind, an das SDK weitergeleitet. Sie nimmt ein einziges Argument entgegen:

  • metadata: ein Objekt mit dem Schlüssel TXXX und einem zugehörigen Stringwert, der mit google_ vorangestellt ist.
processMetadata

Mit dieser Methode werden Metadatenstrings nach dem angegebenen PTS vom SDK verarbeitet. Sie akzeptiert die folgenden Argumente:

  • type: Ein String, der den Typ des verarbeiteten Ereignisses enthält. 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 Byte-Array im Format ID3:u\0004u\000u\000u\0000TXXXu\0004u\000u\000u\0000google_xxxxxxxx.
  • timestamp: Der Zeitstempel in Sekunden, zu dem die Daten verarbeitet werden sollen.

Für jeden vom IMA DAI SDK unterstützten Streamtyp wird eine eindeutige Form von zeitbezogenen Metadaten verwendet, wie in den folgenden Abschnitten beschrieben.

HLS MPEG2TS-Streams

Bei linearen DAI-HLS-Streams mit MPEG2TS-Segmenten werden getaktete Metadaten über In-Band-ID3-Tags an den Videoplayer übergeben. Diese ID3-Tags sind in die MPEG2TS-Segmente eingebettet und erhalten den Feldnamen „TXXX“ (für benutzerdefinierte Textinhalte).

Wiedergabe in Safari

Safari verarbeitet ID3-Tags automatisch als ausgeblendeten Titel, damit Cue-Change-Ereignisse zur richtigen Zeit ausgelöst werden, um alle Metadaten zu verarbeiten. Es ist in Ordnung, alle Metadaten an das IMA DAI SDK zu übergeben, unabhängig von Inhalt oder Typ. 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 Samples bereit. HLS.js übersetzt die ID3-Daten nicht aus Byte-Arrays in Strings und verschiebt Ereignisse nicht auf ihre entsprechenden PTS. Es ist nicht erforderlich, die Sample-Daten aus dem Byte-Array in einen String zu decodieren oder irrelevante ID3-Tags herauszufiltern, da das IMA DAI SDK diese Dekodierung 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

Bei linearen DAI-HLS-Streams mit dem Common Media Application Framework (CMAF) werden getaktete Metadaten über In-Band-eMSGv1-Boxen gemäß dem ID3-bis-CMAF-Standard übergeben. Diese eMSG-Boxen sind am Anfang jedes Mediensegments eingebettet. Jede ID3-eMSG enthält einen PTS relativ zur letzten Unterbrechung im Stream.

Seit der Version 1.2.0 von HLS.js geben beide unserer vorgeschlagenen Player ID3-Tags über CMAF an den Nutzer weiter, als wären es ID3-Tags. Aus diesem Grund sind die folgenden Beispiele mit denen für HLS-MPEG2TS-Streams identisch. Dies ist jedoch möglicherweise nicht bei allen Playern der Fall. Daher kann die Implementierung der Unterstützung für HLS-CMAF-Streams einen eindeutigen Code erfordern, um ID3 über eMSG zu parsen.

Wiedergabe in Safari

Safari behandelt ID3-Metadaten über eMSG als Pseudo-ID3-Ereignisse und stellt sie automatisch in Batches als ausgeblendeten Titel bereit, damit Cue-Change-Ereignisse zur richtigen Zeit ausgelöst werden, um die einzelnen Metadaten zu verarbeiten. Es ist in Ordnung, alle Metadaten an das IMA DAI SDK weiterzugeben, unabhängig davon, ob sie für die Auslieferung relevant sind oder nicht. Alle nicht DAI-bezogenen 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-Metadaten über eMSG als Pseudo-ID3-Ereignisse und stellt sie in Batches über das FRAG_PARSING_METADATA-Ereignis als Array von Samples bereit. HLS.js übersetzt die ID3-Daten nicht aus Byte-Arrays in Strings und verschiebt Ereignisse nicht auf ihren entsprechenden PTS. Es ist nicht erforderlich, die Beispieldaten aus dem Byte-Array in einen String zu decodieren, da diese Dekodierung automatisch vom IMA DAI SDK durchgeführt 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

Bei linearen dynamischen Anzeigenbereitstellung (DAI) werden in DASH-Streams Metadaten als Manifestereignisse in einem Ereignisstream mit dem benutzerdefinierten schemeIdUri-Wert urn:google:dai:2018 übergeben. Jedes Ereignis in diesen Streams enthält eine Textnutzlast und die PTS.

DASH.js

Dash.js bietet benutzerdefinierte Ereignishandler, die nach dem Wert „schemeIdUri“ jedes Ereignisstreams benannt sind. Diese benutzerdefinierten Handler werden in Batches ausgelöst. Sie müssen den PTS-Wert selbst verarbeiten, um das Ereignis richtig zu zeitlich zu steuern. Das IMA DAI SDK kann das für dich mit der streamManager-Methode processMetadata() erledigen.

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 Player

Shaka Player gibt Ereignisse im Rahmen des Ereignisses timelineregionenter an. Aufgrund einer Inkompatibilität der Formatierung mit dem Shaka Player muss der Metadatenwert über das Detailattribut eventNode.attributes['messageData'] im Rohformat abgerufen werden.

Beispiel:

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

Pod-Auslieferung

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

  • Art des Livestreams (Live oder VOD)
  • HLS- oder DASH-Streamformat
  • Der verwendete Playertyp
  • Der verwendete DAI-Back-End-Typ

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

Wenn du einen HLS.js-Player verwendest, warte auf das HLS.js-Ereignis FRAG_PARSING_METADATA, um ID3-Metadaten zu erhalten und sie mit StreamManager.processMetadata() an das SDK weiterzuleiten.

Wenn das Video automatisch abgespielt werden soll, nachdem alle Inhalte geladen und bereit sind, warte 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-Streams-Format, Livestream- und VOD-Streamtyp)

Wenn du einen DASH.js-Player verwendest, musst du unterschiedliche Strings verwenden, um nach ID3-Metadaten für Live- oder VOD-Streams zu suchen:

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

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

Wenn die Videosteuerung automatisch angezeigt werden soll, nachdem alles geladen und bereit ist, musst du das DASH.js-Ereignis MANIFEST_LOADED überwachen.

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-Streams)

Wenn du für die Livestreamwiedergabe den Shaka-Player verwendest, verwende den String 'emsg', um auf Metadatenereignisse zu warten. Verwende dann die Daten der Ereignisnachricht in deinem Aufruf von 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 mit VOD-Streams (DASH-Streams-Format)

Wenn du den Shaka-Player für die Wiedergabe von VOD-Streams verwendest, verwende den String 'timelineregionenter', um auf Metadatenereignisse zu warten. Verwenden Sie dann die Daten der Ereignisnachricht 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);
       }
}