Menangani metadata dengan waktu di streaming DAI linear

Penyisipan Iklan Dinamis (DAI) Interactive Media Ads (IMA) 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, tergantung pada jenis streaming yang sedang diputar.

Pemutar video menerima metadata dengan waktu dalam beberapa batch. Bergantung pada pemutar, metadata dapat ditampilkan pada waktu yang dijadwalkan, atau dalam batch. Setiap string metadata memiliki stempel waktu presentasi (PTS) terkait kapan harus dipicu.

Aplikasi Anda bertanggung jawab untuk merekam 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 nilai string terkait yang diawali dengan google_.
processMetadata

Metode ini menjadwalkan string metadata untuk diproses oleh SDK setelah PTS yang ditentukan. Fungsi 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: baik nilai string yang diawali dengan google_ maupun array byte yang mendekode ke string tersebut.
  • timestamp: stempel waktu dalam detik saat data harus diproses.

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

Streaming MPEG2TS HLS

Streaming HLS DAI linear menggunakan segmen MPEG2TS akan meneruskan metadata dengan waktu ke pemutar video melalui tag ID3 in-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 track tersembunyi, sehingga peristiwa cuechange diaktifkan pada waktu yang tepat untuk memproses setiap bagian metadata. Tidak masalah untuk meneruskan semua metadata ke IMA DAI SDK, apa pun konten atau jenisnya. {i>Metadata<i} 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 contoh. HLS.js tidak menerjemahkan data ID3 dari array byte ke string dan tidak melakukan offset peristiwa ke PTS yang sesuai. Anda tidak perlu mendekode data contoh dari array byte ke string, atau memfilter tag ID3 yang tidak relevan, karena IMA DAI SDK melakukan 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 linear menggunakan Common Media Application Framework (CMAF) meneruskan metadata yang telah dijadwalkan melalui kotak eMSGv1 in-band dengan mengikuti standar ID3 hingga CMAF. Kotak eMSG ini disematkan di awal setiap segmen media, dengan setiap eMSG ID3 yang berisi PTS yang terkait dengan diskon terakhir dalam aliran data.

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

Pemutaran di Safari

Safari memperlakukan ID3 melalui metadata eMSG sebagai peristiwa ID3 pseudo, memberikannya dalam batch, secara otomatis, sebagai jalur 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. Setiap metadata yang tidak terkait DAI 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 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 melakukan offset peristiwa ke PTS yang sesuai. Tidak perlu mendekode data contoh dari array byte ke string, karena IMA DAI SDK melakukan decoding 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 DASH

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

DASH.js

Dash.js menyediakan pengendali peristiwa kustom yang diberi nama berdasarkan nilai schemeIdUri setiap aliran peristiwa. Pengendali kustom ini diaktifkan dalam batch, sehingga Anda bebas memproses nilai PTS untuk menetapkan 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);
});
...

Pemain Shaka

Shaka Player menampilkan acara sebagai bagian dari acara timelineregionenter. Karena inkompatibilitas format dengan Shaka Player, nilai metadata harus diambil secara 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 berwaktu, bergantung pada kriteria berikut:

  • Jenis streaming VOD atau live stream
  • 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, proses 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 VOD dan Live)

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

  • Live stream: '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, proses 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. Selanjutnya, 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);
       }
}