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 Mediensegmente des Streams (In-Band-Metadaten) oder in die Streaming-Manifestdatei (Metadaten im Manifest) eingebettet sind, um die Position der Betrachter und clientseitige Anzeigenereignisse zu verfolgen. Metadaten werden je nach Art des wiedergegebenen Streams in verschiedenen Formaten gesendet.

Der Videoplayer empfängt zeitlich abgestimmte Metadaten in Batches. Je nach Player können Metadaten zur geplanten Zeit oder in Batches angezeigt werden. Jedem Metadatenstring ist ein Präsentationszeitstempel (PTS) zugeordnet, der angibt, wann er ausgelöst werden soll.

Metadaten werden von Ihrer App erfasst und an das IMA DAI SDK weitergeleitet. Das SDK bietet folgende Methoden, um diese Informationen zu übergeben:

onTimedMetadata

Bei dieser Methode werden Metadatenstrings, die zur Verarbeitung bereit sind, an das SDK weitergeleitet. Dafür wird ein einziges Argument benötigt:

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

Mit dieser Methode werden Metadatenstrings geplant, die vom SDK nach dem angegebenen PTS verarbeitet werden. Folgende Argumente werden verwendet:

  • type: Ein String, der die Art 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 Bytearray, das in einen solchen String decodiert wird.
  • timestamp: der Zeitstempel in Sekunden, für den Daten verarbeitet werden sollen.

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

HLS-MPEG2TS-Streams

HLS-Streams der linearen dynamischen Anzeigenbereitstellung mit MPEG2TS-Segmenten übergeben zeitgesteuerte Metadaten über In-Band-ID3-Tags an den Videoplayer. Diese ID3-Tags sind in die MPEG2TS-Segmente eingebettet und erhalten den TXXX-Feldnamen (für benutzerdefinierte Textinhalte).

Wiedergabe in Safari

Safari verarbeitet ID3-Tags automatisch als verborgener Track. Daher werden Cuechange-Ereignisse zur richtigen Zeit ausgelöst, um die einzelnen Metadaten zu verarbeiten. Sie können unabhängig vom Inhalt oder Typ alle Metadaten 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 FRAG_PARSING_METADATA-Ereignis als Array von Beispielen bereit. HLS.js übersetzt die ID3-Daten aus Byte-Arrays nicht in Strings und versetzt Ereignisse nicht in den entsprechenden PTS-Wert. Es ist nicht erforderlich, die Beispieldaten von einem Byte-Array in einen String zu decodieren oder irrelevante ID3-Tags herauszufiltern, da die Decodierung und Filterung durch das IMA DAI SDK automatisch 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);
    });
  }
});
...

HLS CMAF-Streams

HLS-Streams für die lineare dynamische Anzeigenbereitstellung, die das Common Media Application Framework (CMAF) verwenden, übergeben zeitgesteuerte Metadaten über In-Band-eMSGv1-Felder, die dem Standard ID3 bis CMAF folgen. Diese eMSG-Felder sind am Anfang jedes Mediensegments eingebettet, wobei jede ID3-eMSG einen PTS enthält, der sich auf die letzte Diskontinuität im Stream bezieht.

Ab Version 1.2.0 von HLS.js geben beide unserer empfohlenen Spieler ID3 über CMAF an den Nutzer weiter, als wären sie ID3-Tags. 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, sodass für die Implementierung der Unterstützung für HLS CMAF-Streams eindeutiger Code erforderlich ist, um ID3 über eMSG zu parsen.

Wiedergabe in Safari

Safari behandelt ID3 über eMSG-Metadaten als Pseudo-ID3-Ereignisse und stellt sie automatisch in Batches als verborgenen Track bereit, sodass cuechange-Ereignisse zur richtigen Zeit ausgelöst werden, um jedes Metadatenelement zu verarbeiten. Es ist in Ordnung, alle Metadaten an das IMA DAI SDK zu übergeben, unabhängig davon, ob sie für den Zeitpunkt relevant sind oder nicht. Alle Metadaten, die sich nicht auf die dynamische Anzeigenbereitstellung beziehen, 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 versetzt Ereignisse nicht in den entsprechenden PTS. Die Beispieldaten müssen nicht von einem Byte-Array in einen String decodiert werden, da dies vom IMA DAI SDK automatisch 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

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, sodass Sie den PTS-Wert verarbeiten müssen, damit das Ereignis korrekt erfasst wird. Das IMA DAI SDK übernimmt 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 ihres 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 Übergabe zeitgesteuerter Metadaten:

  • Typ des Live- oder VOD-Streams
  • HLS- oder DASH-Stream-Format
  • Der verwendete Playertyp
  • Der verwendete Backend-Typ 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 du einen DASH.js-Player verwendest, musst du verschiedene Strings verwenden, um ID3-Metadaten für Live- oder VOD-Streams zu erfassen:

  • 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 DASH.js-Ereignis MANIFEST_LOADED.

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 für die Livestream-Wiedergabe einen Shaka-Player verwenden, verwenden Sie den String 'emsg', um auf Metadatenereignisse zu warten. Verwenden Sie dann die Daten zu Ereignisnachrichten in Ihrem Aufruf an 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-Streamformat)

Wenn Sie für die Wiedergabe des VOD-Streams den Shaka-Player verwenden, verwenden Sie den String 'timelineregionenter', um auf Metadatenereignisse zu warten. Verwenden Sie dann die Ereignisnachrichtendaten 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);
       }
}