Menangani metadata dengan waktu di streaming DAI linear

Interactive Media Ads (IMA) Dynamic Ad Insertion (DAI) SDK mengandalkan informasi metadata yang disematkan dalam segmen media streaming (metadata dalam band), atau dalam file manifes streaming (metadata dalam manifes) untuk melacak posisi penonton dan peristiwa iklan sisi klien. Metadata dikirim dalam berbagai format, bergantung pada jenis streaming yang diputar.

Pemutar video menerima metadata berwaktu dalam batch. Bergantung pada pemutar, metadata dapat ditampilkan pada waktu yang dijadwalkan, atau dalam batch. Setiap string metadata memiliki stempel waktu presentasi (PTS) terkait untuk waktu saat dipicu.

Aplikasi Anda bertanggung jawab untuk mengambil metadata dan meneruskannya ke IMA DAI SDK. SDK menawarkan metode berikut untuk meneruskan informasi ini:

onTimedMetadata

Metode ini meneruskan string metadata yang siap diproses ke SDK. Fungsi ini memerlukan satu argumen:

  • metadata: objek yang berisi kunci TXXX dengan nilai string terkait yang diawali dengan google_.
processMetadata

Metode ini menjadwalkan string metadata untuk diproses oleh SDK setelah PTS yang ditentukan. Metode ini menggunakan argumen berikut:

  • type: string yang berisi jenis peristiwa yang sedang diproses. Nilai yang diterima adalah ID3 untuk HLS atau urn:google:dai:2018 untuk DASH
  • data: nilai string yang diawali dengan google_ atau array byte yang mengikuti format ID3:u\0004u\000u\000u\0000TXXXu\0004u\000u\000u\0000google_xxxxxxxx ini.
  • timestamp: stempel waktu dalam detik saat data harus diproses.

Setiap jenis streaming yang didukung oleh IMA DAI SDK menggunakan bentuk metadata berwaktu yang unik, seperti yang dijelaskan di bagian berikut.

Streaming MPEG2TS HLS

Streaming HLS DAI linear menggunakan segmen MPEG2TS meneruskan metadata berwaktu ke pemutar video melalui tag ID3 dalam band. Tag ID3 ini disematkan dalam segmen MPEG2TS dan diberi nama kolom TXXX (untuk konten teks kustom yang ditentukan pengguna).

Pemutaran di Safari

Safari memproses tag ID3 secara otomatis, sebagai trek tersembunyi, sehingga peristiwa cuechange diaktifkan pada waktu yang tepat untuk memproses setiap bagian metadata. Anda dapat meneruskan semua metadata ke IMA DAI SDK, terlepas dari konten atau jenisnya. Metadata yang tidak relevan akan difilter secara otomatis.

Berikut contohnya:

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 menyediakan tag ID3 dalam batch melalui peristiwa FRAG_PARSING_METADATA, sebagai array sampel. HLS.js tidak menerjemahkan data ID3 dari array byte ke string dan tidak mengimbangi peristiwa ke PTS yang sesuai. Anda tidak perlu mendekode data sampel dari array byte menjadi string, atau memfilter tag ID3 yang tidak relevan, karena IMA DAI SDK melakukan dekode dan pemfilteran ini secara otomatis.

Berikut contohnya:

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

Streaming CMAF HLS

Streaming HLS DAI linear yang menggunakan Common Media Application Framework (CMAF) meneruskan metadata berwaktu melalui kotak eMSGv1 dalam band mengikuti standar ID3 melalui CMAF. Kotak eMSG ini disematkan di awal setiap segmen media, dengan setiap eMSG ID3 berisi PTS yang relatif terhadap diskontinuitas terakhir dalam streaming.

Mulai rilis HLS.js 1.2.0, kedua pemutar yang kami sarankan meneruskan ID3 melalui CMAF kepada pengguna seolah-olah tag tersebut adalah tag ID3. Karena alasan ini, contoh berikut sama dengan streaming MPEG2TS HLS. Namun, hal ini mungkin tidak berlaku untuk semua pemutar, sehingga menerapkan dukungan untuk streaming HLS CMAF mungkin memerlukan kode unik untuk mengurai ID3 melalui eMSG.

Pemutaran di Safari

Safari memperlakukan metadata ID3 melalui eMSG sebagai peristiwa ID3 pseudo, yang menyediakannya dalam batch, secara otomatis, sebagai trek tersembunyi, sehingga peristiwa cuechange diaktifkan pada waktu yang tepat untuk memproses setiap bagian metadata. Anda dapat meneruskan semua metadata ke IMA DAI SDK, baik yang relevan dengan pengaturan waktu maupun tidak. Semua metadata non-DAI akan difilter secara otomatis.

Berikut contohnya:

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

Mulai versi 1.2.0, HLS.js memperlakukan metadata ID3 melalui eMSG sebagai peristiwa ID3 pseudo, yang menyediakannya dalam batch, melalui peristiwa FRAG_PARSING_METADATA, sebagai array sampel. HLS.js tidak menerjemahkan data ID3 dari array byte ke string dan tidak mengimbangi peristiwa ke PTS yang sesuai. Anda tidak perlu mendekode data sampel dari array byte menjadi string, karena IMA DAI SDK melakukan dekode ini secara otomatis.

Berikut contohnya:

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

Streaming DASH

Streaming DAI DASH linear meneruskan metadata sebagai peristiwa manifes dalam streaming peristiwa dengan nilai schemeIdUri kustom urn:google:dai:2018. Setiap peristiwa dalam streaming ini berisi payload teks, dan PTS.

DASH.js

Dash.js menyediakan pengendali peristiwa kustom yang diberi nama berdasarkan nilai schemeIdUri dari setiap streaming peristiwa. Pengendali kustom ini diaktifkan secara massal, sehingga Anda dapat memproses nilai PTS untuk mengatur waktu peristiwa dengan benar. IMA DAI SDK dapat menangani hal ini untuk Anda, dengan metode streamManager, processMetadata().

Berikut contohnya:

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 menampilkan peristiwa sebagai bagian dari peristiwa timelineregionenter. Karena inkompatibelitas pemformatan dengan Shaka Player, nilai metadata harus diambil dalam bentuk mentah, melalui properti detail eventNode.attributes['messageData'].

Berikut contohnya:

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

Penayangan pod

Untuk penayangan Pod, ada berbagai konfigurasi untuk meneruskan metadata berjangka waktu, bergantung pada kriteria berikut:

  • Jenis streaming Live atau VOD
  • Format streaming HLS atau DASH
  • Jenis pemutar yang digunakan
  • Jenis backend DAI yang digunakan

Format streaming HLS (Streaming live dan VOD, pemutar HLS.js)

Jika Anda menggunakan pemutar HLS.js, proses peristiwa FRAG_PARSING_METADATA HLS.js untuk mendapatkan metadata ID3 dan teruskan ke SDK dengan StreamManager.processMetadata().

Untuk memutar video secara otomatis setelah semuanya dimuat dan siap, dengarkan peristiwa MANIFEST_PARSED HLS.js untuk memicu pemutaran.

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 streaming DASH, jenis streaming Live dan VOD)

Jika menggunakan pemutar DASH.js, Anda harus menggunakan string yang berbeda untuk memproses metadata ID3 untuk streaming Live atau VOD:

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

Teruskan metadata ID3 ke SDK dengan StreamManager.processMetadata().

Untuk menampilkan kontrol video secara otomatis setelah semuanya dimuat dan siap, simak peristiwa 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 dengan live stream (format streaming DASH)

Jika Anda menggunakan pemutar Shaka untuk pemutaran live stream, gunakan string 'emsg' untuk memproses peristiwa metadata. Kemudian, gunakan data pesan peristiwa dalam panggilan Anda ke 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 dengan streaming VOD (format streaming DASH)

Jika Anda menggunakan pemutar Shaka untuk pemutaran streaming VOD, gunakan string 'timelineregionenter' untuk memproses peristiwa metadata. Kemudian, gunakan data pesan peristiwa dalam panggilan Anda ke StreamManager.processMetadata() dengan 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);
       }
}