Gérer les métadonnées planifiées dans les flux linéaires d'insertion dynamique d'annonce

Le SDK IMA (Interactive Media Ads) pour l'insertion dynamique d'annonces s'appuie sur des informations de métadonnées intégrées aux segments multimédias du flux (métadonnées en bande) ou au fichier manifeste de streaming (métadonnées dans le fichier manifeste) pour suivre les positions des spectateurs et les événements d'annonces côté client. Les métadonnées sont envoyées dans différents formats, en fonction du type de flux lu.

Le lecteur vidéo reçoit les métadonnées temporelles par lots. Selon le lecteur, les métadonnées peuvent s'afficher à l'heure planifiée ou par lots. Chaque chaîne de métadonnées est associée à un code temporel de présentation (PTS) indiquant quand elle doit être déclenchée.

Votre application est chargée de capturer les métadonnées et de les transmettre au SDK IMA DAI. Le SDK propose les méthodes suivantes pour transmettre ces informations:

onTimedMetadata

Cette méthode transfère les chaînes de métadonnées prêtes à être traitées au SDK. Il ne nécessite qu'un seul argument:

  • metadata: objet contenant une clé TXXX avec une valeur de chaîne associée préfixée par google_.
processMetadata

Cette méthode planifie le traitement des chaînes de métadonnées par le SDK après le PTS spécifié. Elle utilise les arguments suivants:

  • type: chaîne contenant le type d'événement traité. Les valeurs acceptées sont ID3 pour HLS ou urn:google:dai:2018 pour DASH.
  • data: valeur de chaîne précédée de google_ ou tableau d'octets suivant ce format ID3:u\0004u\000u\000u\0000TXXXu\0004u\000u\000u\0000google_xxxxxxxx.
  • timestamp: code temporel en secondes auquel les données doivent être traitées.

Chaque type de flux compatible avec le SDK IMA DAI utilise une forme unique de métadonnées temporelles, comme décrit dans les sections suivantes.

Flux HLS MPEG2TS

Les flux HLS DAI linéaires utilisant les segments MPEG2TS transmettent des métadonnées temporelles au lecteur vidéo via des tags ID3 en bande. Ces balises ID3 sont intégrées aux segments MPEG2TS et reçoivent le nom de champ TXXX (pour le contenu textuel personnalisé défini par l'utilisateur).

Lecture dans Safari

Safari traite automatiquement les balises ID3 en tant que piste masquée. Les événements cuechange se déclenchent donc au bon moment pour traiter chaque élément de métadonnées. Vous pouvez transmettre toutes les métadonnées au SDK DAI IMA, quel que soit le contenu ou le type. Les métadonnées non pertinentes sont filtrées automatiquement.

Exemple :

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 fournit des balises ID3 par lots via l'événement FRAG_PARSING_METADATA, sous la forme d'un tableau d'échantillons. HLS.js ne traduit pas les données ID3 des tableaux d'octets en chaînes et ne décale pas les événements vers leur PTS correspondant. Il n'est pas nécessaire de décoder les données d'exemple du tableau d'octets en chaîne, ni de filtrer les balises ID3 non pertinentes, car le SDK IMA DAI effectue ce décodage et ce filtrage automatiquement.

Exemple :

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

Flux HLS CMAF

Les flux HLS DAI linéaires utilisant le format CMAF (Common Media Application Framework) transmettent des métadonnées temporelles via des boîtes eMSGv1 en bande suivant la norme ID3 via CMAF. Ces blocs eMSG sont intégrés au début de chaque segment multimédia, chaque eMSG ID3 contenant un PTS par rapport à la dernière discontinuité du flux.

Depuis la version 1.2.0 de HLS.js, nos deux lecteurs suggérés transfèrent l'ID3 via CMAF à l'utilisateur comme s'il s'agissait de balises ID3. Pour cette raison, les exemples suivants sont les mêmes que pour les flux MPEG2TS HLS. Toutefois, ce n'est peut-être pas le cas pour tous les lecteurs. L'implémentation de la compatibilité avec les flux HLS CMAF peut donc nécessiter un code unique pour analyser l'ID3 via eMSG.

Lecture dans Safari

Safari traite les métadonnées ID3 via eMSG comme des événements pseudo-ID3, en les fournissant par lot, automatiquement, en tant que piste masquée, de sorte que les événements cuechange soient déclenchés au bon moment pour traiter chaque élément de métadonnées. Vous pouvez transmettre toutes les métadonnées au SDK IMA DAI, que ce soit pertinent pour le calendrier ou non. Toutes les métadonnées non liées à la DAI sont filtrées automatiquement.

Exemple :

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

À partir de la version 1.2.0, HLS.js traite les métadonnées ID3 via eMSG comme des événements pseudo-ID3, en les fournissant par lot, via l'événement FRAG_PARSING_METADATA, sous la forme d'un tableau d'échantillons. HLS.js ne traduit pas les données ID3 des tableaux d'octets en chaînes et ne décale pas les événements par rapport à leur PTS correspondant. Il n'est pas nécessaire de décoder les données d'exemple de tableau d'octets en chaîne, car le SDK IMA DAI effectue ce décodage automatiquement.

Exemple :

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

Flux DASH

Les flux DASH DAI linéaires transmettent les métadonnées en tant qu'événements de fichier manifeste dans un flux d'événements avec la valeur schemeIdUri personnalisée urn:google:dai:2018. Chaque événement de ces flux contient une charge utile textuelle et le PTS.

DASH.js

Dash.js fournit des gestionnaires d'événements personnalisés nommés d'après la valeur schemeIdUri de chaque flux d'événements. Ces gestionnaires personnalisés se déclenchent par lots. Il vous appartient de traiter la valeur PTS pour chronométrer correctement l'événement. Le SDK IMA DAI peut s'en charger pour vous, avec la méthode streamManager, processMetadata().

Exemple :

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 affiche les événements dans son événement timelineregionenter. En raison d'une incompatibilité de formatage avec Shaka Player, la valeur des métadonnées doit être récupérée brute, via la propriété de détail eventNode.attributes['messageData'].

Exemple :

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

Diffusion de séries d'annonces

Pour la diffusion de pod, il existe différentes configurations pour transmettre des métadonnées temporelles en fonction des critères suivants:

  • Type de flux en direct ou VOD
  • Format de flux HLS ou DASH
  • Type de lecteur utilisé
  • Type de backend DAI utilisé

Format de flux HLS (flux en direct et VOD, lecteur HLS.js)

Si vous utilisez un lecteur HLS.js, écoutez l'événement FRAG_PARSING_METADATA HLS.js pour obtenir les métadonnées ID3 et les transmettre au SDK avec StreamManager.processMetadata().

Pour lire automatiquement la vidéo une fois que tout est chargé et prêt, écoutez l'événement MANIFEST_PARSED HLS.js pour déclencher la lecture.

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 (format de flux DASH, type de flux en direct et VOD)

Si vous utilisez un lecteur DASH.js, vous devez utiliser des chaînes différentes pour écouter les métadonnées ID3 pour les flux en direct ou VOD:

  • Diffusions en direct: 'https://developer.apple.com/streaming/emsg-id3'
  • Flux VOD: 'urn:google:dai:2018'

Transmettez les métadonnées ID3 au SDK avec StreamManager.processMetadata().

Pour afficher automatiquement les commandes vidéo une fois que tout est chargé et prêt, écoutez l'événement MANIFEST_LOADED 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 avec diffusions en direct (format de flux DASH)

Si vous utilisez le lecteur Shaka pour la lecture en direct, utilisez la chaîne 'emsg' pour écouter les événements de métadonnées. Utilisez ensuite les données du message d'événement dans votre appel à 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 avec des flux VOD (format de flux DASH)

Si vous utilisez le lecteur Shaka pour la lecture de flux VOD, utilisez la chaîne 'timelineregionenter' pour écouter les événements de métadonnées. Utilisez ensuite les données du message d'événement dans votre appel à StreamManager.processMetadata() avec la chaîne '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);
       }
}