Menangani metadata dengan waktu di streaming DAI linear

SDK Penyisipan Iklan Dinamis (DAI) Iklan Media Interaktif (IMA) bergantung pada informasi metadata yang disematkan dalam segmen media streaming (metadata in-band), atau di file manifes streaming (metadata dalam manifes) untuk melacak posisi dan peristiwa iklan sisi klien. Metadata dikirim dalam format yang berbeda, bergantung pada jenis streaming yang diputar.

Pemutar video menerima metadata dengan waktu dalam batch. Tergantung pada pemainnya, metadata dapat dimunculkan pada waktu yang dijadwalkan, atau dalam batch. Setiap metadata string memiliki stempel waktu presentasi (PTS) terkait saat dipicu.

Aplikasi Anda bertanggung jawab menangkap 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. Dibutuhkan satu argumen:

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

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

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

Setiap jenis streaming yang didukung oleh IMA DAI SDK menggunakan format waktu yang unik seperti yang dijelaskan di bagian berikut.

Streaming MPEG2TS HLS

Streaming HLS DAI linear menggunakan segmen MPEG2TS meneruskan metadata berjangka waktu ke pemutar video melalui tag in-band ID3. Tag ID3 ini disematkan dalam Segmen MPEG2TS dan diberi nama kolom TXXX (untuk teks kustom buatan pengguna Google).

Pemutaran di Safari

Safari memproses tag ID3 secara otomatis, sebagai trek tersembunyi, jadi peristiwa cuechange diaktifkan pada waktu yang tepat untuk memproses setiap bagian {i>metadata.<i} Tidak apa-apa untuk melewati semua metadata ke IMA DAI SDK, apa pun konten atau jenisnya. Tidak relevan {i>metadata<i} 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 meng-offset peristiwa ke PTS yang sesuai. Tidak untuk mendekode data sampel dari array byte ke string, atau tag ID3 yang tidak relevan, karena IMA DAI SDK menjalankan decoding 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 linier menggunakan penerusan Common Media Application Framework (CMAF) metadata berwaktu melalui kotak eMSGv1 in-band setelah ID3 hingga CMAF. Kotak eMSG ini disematkan di awal setiap segmen media, dengan setiap ID3 eMSG berisi PTS relatif terhadap diskontinuitas terakhir dalam aliran data.

Mulai rilis HLS.js 1.2.0, kedua saran pemain yang lulus ID3 melalui CMAF ke pengguna seolah-olah mereka adalah tag ID3. Karena alasan ini, contoh berikut sama seperti untuk streaming HLS MPEG2TS. Namun, hal ini mungkin tidak terjadi pada semua pemutar, jadi menerapkan dukungan untuk CMAF HLS aliran data dapat memerlukan kode unik untuk mengurai ID3 melalui eMSG.

Pemutaran di Safari

Safari memperlakukan ID3 melalui metadata eMSG sebagai peristiwa ID3 semu, menyediakannya di mengelompokkan secara otomatis sebagai trek tersembunyi, sehingga peristiwa cuechange diaktifkan pada waktu yang tepat untuk memproses setiap bagian {i>metadata.<i} Tidak apa-apa untuk meneruskan semua metadata ke IMA DAI SDK, baik terkait dengan waktu maupun tidak. Apa saja metadata yang tidak terkait 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 ID3 melalui metadata eMSG sebagai ID3 semu peristiwa, 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 meng-offset peristiwa ke PTS yang sesuai. Tidak untuk mendekode data sampel dari array byte ke string, karena IMA DAI SDK menjalankan 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);
    });
  }
});
...

Aliran data DASH

Streaming DASH DAI linear meneruskan metadata sebagai peristiwa manifes dalam aliran peristiwa dengan nilai schemeIdUri kustom urn:google:dai:2018. Setiap peristiwa di {i>stream<i} berisi {i>payload<i} teks, dan PTS.

DASH.js

Dash.js menyediakan pengendali peristiwa kustom yang diberi nama berdasarkan nilai schemaIdUri masing-masing aliran data peristiwa. Pengendali khusus ini diaktifkan secara berkelompok, sehingga Anda dapat memproses nilai PTS untuk mengatur waktu peristiwa dengan benar. IMA DAI SDK dapat menangani 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);
});
...

Pemutar Shaka

Shaka Player menampilkan acara sebagai bagian dari peristiwa timelineregionenter mereka. Tenggat ketidaksesuaian format dengan Shaka Player, nilai metadata harus diambil mentah, melalui properti detail eventElement.attributes['messageData'].value.

Berikut contohnya:

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

Penayangan pod

Untuk penayangan Pod, terdapat berbagai konfigurasi untuk meneruskan metadata bergantung pada kriteria berikut:

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

Format streaming HLS (streaming VOD dan Live, pemutar HLS.js)

Jika Anda menggunakan pemutar HLS.js, dengarkan peristiwa FRAG_PARSING_METADATA HLS.js untuk mendapatkan metadata ID3 dan meneruskannya 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 Anda menggunakan pemutar DASH.js, Anda harus menggunakan string yang berbeda untuk memproses metadata ID3 untuk Live atau VOD feed:

  • 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, 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 livestream (format streaming DASH)

Jika Anda menggunakan pemutar Shaka untuk pemutaran livestream, 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 untuk 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);
       }
}