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

Le SDK IMA (Interactive Media Ads) d'insertion dynamique d'annonce s'appuie sur les informations de métadonnées intégrées aux segments multimédias du flux (métadonnées dans la bande) ou au fichier manifeste de streaming (métadonnées dans le fichier manifeste) pour suivre la position des internautes 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 en cours de lecture.

Le lecteur vidéo reçoit les métadonnées temporisées par lots. Selon le joueur, les métadonnées peuvent être affichées à l'heure programmée ou par lots. Chaque chaîne de métadonnées est associée à un code temporel de présentation (PTS) indiquant le moment où 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 transmet les chaînes de métadonnées prêtes à être traitées au SDK. Elle n'accepte qu'un seul argument:

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

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

  • type: chaîne contenant le type d'événement en cours de traitement. 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 qui est décodé en une telle chaîne.
  • timestamp: code temporel, en secondes, de la date à laquelle 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 minutées, comme décrit dans les sections suivantes.

Flux HLS MPEG2TS

Les flux HLS pour l'insertion dynamique d'annonce linéaire qui utilisent les segments MPEG2TS transmettent des métadonnées temporisées au lecteur vidéo via des tags ID3 dans la bande. Ces tags ID3 sont intégrés dans les 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. Par conséquent, les événements de cuechange se déclenchent au bon moment pour traiter chaque élément de métadonnées. Vous pouvez transmettre toutes les métadonnées au SDK IMA DAI, quels que soient leur contenu ou leur type. Les métadonnées non pertinentes sont automatiquement filtrées.

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'exemples. 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 les PTS correspondants. Vous n'avez pas besoin de décoder les échantillons de données du tableau d'octets en chaîne ni de filtrer les tags ID3 non pertinents, 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 CMAF HLS

Les flux HLS pour l'insertion dynamique d'annonce linéaires qui utilisent le framework d'application de médias communs (CMAF) transmettent des métadonnées minutées via des cadres eMSGv1 dans la bande, conformément à la norme ID3 à CMAF. Ces boîtes eMSG sont intégrées au début de chaque segment multimédia, et chaque eMSG ID3 contient un PTS relatif à la dernière discontinuité du flux.

Depuis la version 1.2.0 de HLS.js, nos deux joueurs suggérés transmettent les identifiants 3 via CMAF à l'utilisateur comme s'il s'agissait de tags ID3. Pour cette raison, les exemples suivants sont identiques à ceux des flux HLS MPEG2TS. Toutefois, ce n'est peut-être pas le cas avec tous les joueurs. Par conséquent, l'implémentation de la prise en charge des flux CMAF HLS peut nécessiter un code unique pour analyser l'ID3 via eMSG.

Lecture dans Safari

Safari traite les métadonnées ID3 à eMSG comme des événements pseudo ID3, et les envoie automatiquement par lots 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, qu'elles soient pertinentes ou non. Toutes les métadonnées qui ne sont pas liées à l'insertion dynamique d'annonce sont automatiquement filtrées.

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 ID3 via les métadonnées eMSG comme des événements pseudo-ID3, qui sont fournis par lots via l'événement FRAG_PARSING_METADATA comme 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 les PTS correspondants. Il n'est pas nécessaire de décoder les échantillons de données du 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 linéaires pour l'insertion dynamique d'annonce transmettent des métadonnées en tant qu'événements manifestes 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 de texte et le PTS.

DASH.js

Dash.js fournit des gestionnaires d'événements personnalisés nommés d'après la valeur "schemaIdUri" de chaque flux d'événements. Ces gestionnaires personnalisés se déclenchent par lots, vous laissant ainsi le soin de traiter la valeur PTS afin de chronométrer correctement l'événement. Le SDK IMA DAI peut s'en charger pour vous, grâce à 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);
});
...

Lecteur Shaka

Shaka Player affiche des événements dans le cadre de son événement timelineregionenter. En raison d'une incompatibilité de mise en forme avec Shaka Player, la valeur des métadonnées doit être récupérée brute, via la propriété de détail eventElement.attributes['messageData'].value.

Exemple :

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

Diffusion de séries d'annonces

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

  • Type de flux en direct ou VOD
  • Format de flux HLS ou DASH
  • Le type de lecteur utilisé
  • Type de backend d'insertion dynamique d'annonce utilisé

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

Si vous utilisez un lecteur HLS.js, écoutez l'événement HLS.js FRAG_PARSING_METADATA pour obtenir les métadonnées ID3 et transmettez-les 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 vous servez d'un lecteur DASH.js, vous devez utiliser des chaînes différentes pour écouter les métadonnées ID3 pour les diffusions en direct ou de VOD:

  • Diffusions en direct: 'https://developer.apple.com/streaming/emsg-id3'
  • Flux de 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 de flux en direct, utilisez la chaîne 'emsg' pour écouter les événements de métadonnées. Ensuite, utilisez 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 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);
       }
}