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 les informations de métadonnées intégrées aux segments multimédias du flux (métadonnées intrabandes) ou au fichier manifeste de streaming (métadonnées dans le fichier manifeste) pour suivre la position des utilisateurs 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 au moment planifié ou par lots. Chaque chaîne de métadonnées est associée à un code temporel de présentation (PTS) correspondant au moment où elle doit être déclenchée.

Votre application se charge 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 comporte un seul argument:

  • metadata: objet contenant une clé de TXXX et 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 le PTS spécifié. 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 décode en une telle chaîne.
  • timestamp: code temporel, en secondes, auquel les données doivent être traitées.

Chaque type de flux compatible avec le SDK IMA pour l'insertion dynamique d'annonce 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 minutées au lecteur vidéo via des tags ID3 intra-bande. Ces tags ID3 sont intégrés dans les segments MPEG2TS et reçoivent le nom du 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 cuechange se déclenchent au bon moment pour traiter chaque métadonnée. Vous pouvez transmettre toutes les métadonnées au SDK IMA DAI, quel que soit 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 en fonction des valeurs PTS correspondantes. 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 pour l'insertion dynamique d'annonce 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 pour l'insertion dynamique d'annonces linéaires qui utilisent le framework CMAF (Common Media Application Framework) transmettent des métadonnées temporisées via des cadres eMSGv1 in-bandes, conformément à la norme ID3 via 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 l'ID3 à l'utilisateur via CMAF comme s'il s'agissait de tags ID3. Pour cette raison, les exemples suivants sont identiques à ceux des flux MPEG2TS HLS. Cependant, il est possible que cela ne soit pas le cas avec tous les joueurs. Par conséquent, la mise en œuvre de la prise en charge des flux CMAF HLS peut nécessiter un code unique pour analyser l'ID3 via l'eMSG.

Lecture dans Safari

Safari traite les métadonnées ID3 à eMSG comme des événements pseudo ID3 et les fournit automatiquement par lots comme des pistes masquées, de sorte que les événements cuechange soient déclenchés au bon moment pour traiter chaque métadonnée. Vous pouvez transmettre toutes les métadonnées au SDK IMA DAI, qu'elles soient pertinentes ou non. Toutes les métadonnées non 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

Depuis 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 lots, via l'événement FRAG_PARSING_METADATA, comme 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 en fonction des valeurs PTS correspondantes. 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 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 "schemaIdUri" de chaque flux d'événements. Ces gestionnaires personnalisés se déclenchent par lots, ce qui vous laisse le soin de traiter la valeur PTS pour chronométrer correctement l'événement. Le SDK IMA DAI peut gérer cela pour vous, à l'aide de 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 des événements dans le cadre de son événement timelineregionenter. En raison d'une incompatibilité de format avec Shaka Player, la valeur des métadonnées doit être récupérée à l'état brut, 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 à la demande
  • Format de flux HLS ou DASH
  • Le type de lecteur utilisé
  • Le type de backend d'insertion dynamique d'annonce utilisé

Format de flux HLS (flux en direct et de vidéo à la demande, 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 de vidéo à la demande)

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 à la demande:

  • Diffusions en direct: 'https://developer.apple.com/streaming/emsg-id3'
  • Flux de vidéo à la demande: '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. 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 de vidéo à la demande (format de flux DASH)

Si vous utilisez le lecteur Shaka pour la lecture de flux de vidéo à la demande, 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);
       }
}