จัดการข้อมูลเมตาที่มีการระบุเวลาในสตรีม DAI ที่ไม่ปรากฏร่วมกับวิดีโอ

SDK ของแทรกโฆษณาแบบไดนามิก (DAI) ของ Interactive Media Ads (IMA) ใช้ข้อมูลเมตาที่ฝังอยู่ในกลุ่มสื่อของสตรีม (ข้อมูลเมตาในแบนด์) หรือในไฟล์ Manifest สตรีมมิง (ข้อมูลเมตาในไฟล์ Manifest) เพื่อติดตามตําแหน่งของผู้ใช้และเหตุการณ์โฆษณาฝั่งไคลเอ็นต์ ระบบจะส่งข้อมูลเมตาในรูปแบบต่างๆ โดยขึ้นอยู่กับประเภทของสตรีมที่เล่น

วิดีโอเพลเยอร์จะได้รับข้อมูลเมตาแบบกำหนดเวลาเป็นกลุ่ม ข้อมูลเมตาจะแสดงตามเวลาที่กำหนดหรือเป็นกลุ่ม ทั้งนี้ขึ้นอยู่กับโปรแกรมเล่น สตริงข้อมูลเมตาแต่ละรายการมีการประทับเวลาของการนำเสนอ (PTS) ที่เกี่ยวข้องสำหรับเวลาที่ควรทริกเกอร์

แอปของคุณมีหน้าที่บันทึกข้อมูลเมตาและส่งต่อไปยัง IMA DAI SDK SDK มีเมธอดต่อไปนี้ในการส่งข้อมูลนี้

onTimedMetadata

วิธีนี้จะส่งต่อสตริงข้อมูลเมตาที่พร้อมประมวลผลไปยัง SDK โดยจะใช้อาร์กิวเมนต์เดียว ดังนี้

  • metadata: ออบเจ็กต์ที่มีคีย์ TXXX ที่มีค่าสตริงที่เชื่อมโยงกันซึ่งขึ้นต้นด้วย google_
processMetadata

เมธอดนี้จะกำหนดเวลาให้ SDK ประมวลผลสตริงข้อมูลเมตาหลังจาก PTS ที่ระบุ โดยจะใช้อาร์กิวเมนต์ต่อไปนี้

  • type: สตริงที่มีประเภทเหตุการณ์ที่ประมวลผล ค่าที่ยอมรับคือ ID3 สำหรับ HLS หรือ urn:google:dai:2018 สำหรับ DASH
  • data: ค่าสตริงที่มี google_ นำหน้า หรืออาร์เรย์ไบต์ที่เป็นไปตามรูปแบบนี้ ID3:u\0004u\000u\000u\0000TXXXu\0004u\000u\000u\0000google_xxxxxxxx
  • timestamp: การประทับเวลาเป็นวินาทีเมื่อควรประมวลผลข้อมูล

สตรีมแต่ละประเภทที่ IMA DAI SDK รองรับจะใช้รูปแบบข้อมูลเมตาแบบกำหนดเวลาที่ไม่ซ้ำกันตามที่อธิบายไว้ในส่วนต่อไปนี้

สตรีม HLS MPEG2TS

สตรีม HLS ของ DAI แบบสดที่ใช้กลุ่ม MPEG2TS จะส่งข้อมูลเมตาแบบกำหนดเวลาไปยังโปรแกรมเล่นวิดีโอผ่านแท็ก ID3 ในแบนด์ แท็ก ID3 เหล่านี้ฝังอยู่ในกลุ่ม MPEG2TS และมีชื่อช่อง TXXX (สำหรับเนื้อหาข้อความที่ผู้ใช้กำหนดเอง)

การเล่นใน Safari

Safari จะประมวลผลแท็ก ID3 โดยอัตโนมัติในรูปแบบแทร็กที่ซ่อนอยู่ เพื่อให้เหตุการณ์ CueChange เริ่มทํางานในเวลาที่เหมาะสมเพื่อประมวลผลข้อมูลเมตาแต่ละรายการ คุณส่งข้อมูลเมตาทั้งหมดไปยัง IMA DAI SDK ได้ ไม่ว่าเนื้อหาหรือประเภทจะเป็นอย่างไรก็ตาม ระบบจะกรองข้อมูลเมตาที่ไม่เกี่ยวข้องออกโดยอัตโนมัติ

เช่น

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 จะระบุแท็ก ID3 เป็นกลุ่มผ่านเหตุการณ์ FRAG_PARSING_METADATA โดยเป็นอาร์เรย์ของตัวอย่าง HLS.js จะไม่แปลข้อมูล ID3 จากอาร์เรย์ไบต์เป็นสตริง และไม่เลื่อนเหตุการณ์ไปยัง PTS ที่เกี่ยวข้อง คุณไม่จำเป็นต้องถอดรหัสข้อมูลตัวอย่างจากอาร์เรย์ไบต์เป็นสตริง หรือกรองแท็ก ID3 ที่ไม่เกี่ยวข้องออก เนื่องจาก IMA DAI SDK จะทำการถอดรหัสและกรองโดยอัตโนมัติ

เช่น

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

สตรีม HLS CMAF

สตรีม DAI แบบสดของ HLS ที่ใช้ Common Media Application Framework (CMAF) จะส่งข้อมูลเมตาที่มีการกำหนดเวลาผ่านกล่อง eMSGv1 ในแบนด์ตามมาตรฐาน ID3 ผ่าน CMAF กล่อง eMSG เหล่านี้จะฝังไว้ที่จุดเริ่มต้นของกลุ่มสื่อแต่ละกลุ่ม โดย eMSG ของ ID3 แต่ละรายการจะมี PTS ที่สัมพันธ์กับการหยุดชะงักครั้งล่าสุดในสตรีม

ตั้งแต่รุ่น 1.2.0 ของ HLS.js ทั้ง 2 โปรแกรมเล่นที่แนะนำจะส่งผ่าน ID3 ผ่าน CMAF ไปยังผู้ใช้ราวกับว่าเป็นแท็ก ID3 ด้วยเหตุนี้ ตัวอย่างต่อไปนี้จึงเหมือนกับสตรีม HLS MPEG2TS อย่างไรก็ตาม ผู้เล่นบางรุ่นอาจไม่รองรับวิธีนี้ ดังนั้นการติดตั้งใช้งานการรองรับสตรีม HLS CMAF อาจต้องใช้โค้ดที่ไม่ซ้ำกันเพื่อแยกวิเคราะห์ ID3 ผ่าน eMSG

การเล่นใน Safari

Safari จะถือว่าข้อมูลเมตา ID3 ผ่าน eMSG เป็นเหตุการณ์ ID3 จำลอง โดยจะส่งเป็นกลุ่มโดยอัตโนมัติเป็นแทร็กที่ซ่อนอยู่ เพื่อให้ระบบเรียกเหตุการณ์ cuechange ในเวลาที่เหมาะสมเพื่อประมวลผลข้อมูลเมตาแต่ละรายการ คุณส่งข้อมูลเมตาทั้งหมดไปยัง IMA DAI SDK ได้ ไม่ว่าจะเกี่ยวข้องกับเวลาหรือไม่ก็ตาม ระบบจะกรองข้อมูลเมตาที่ไม่เกี่ยวข้องกับ DAI ออกโดยอัตโนมัติ

เช่น

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

ตั้งแต่เวอร์ชัน 1.2.0 เป็นต้นไป HLS.js จะถือว่าข้อมูลเมตา ID3 ผ่าน eMSG เป็นเหตุการณ์ ID3 เสมือน โดยส่งเป็นกลุ่มผ่านเหตุการณ์ FRAG_PARSING_METADATA เป็นอาร์เรย์ของตัวอย่าง HLS.js จะไม่แปลข้อมูล ID3 จากอาร์เรย์ไบต์เป็นสตริง และไม่ลบล้างเหตุการณ์ไปยัง PTS ที่เกี่ยวข้อง คุณไม่จำเป็นต้องถอดรหัสข้อมูลตัวอย่างจากอาร์เรย์ไบต์เป็นสตริง เนื่องจาก IMA DAI SDK จะถอดรหัสนี้โดยอัตโนมัติ

เช่น

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

สตรีม DASH

สตรีม DAI DASH แบบสดจะส่งข้อมูลเมตาเป็นเหตุการณ์ไฟล์ Manifest ในสตรีมเหตุการณ์ที่มีschemeIdUriค่าurn:google:dai:2018ที่กำหนดเอง แต่ละเหตุการณ์ในสตรีมเหล่านี้จะมีเพย์โหลดข้อความและ PTS

DASH.js

Dash.js มีตัวแฮนเดิลเหตุการณ์ที่กําหนดเองซึ่งตั้งชื่อตามค่า schemeIdUri ของสตรีมเหตุการณ์แต่ละรายการ แฮนเดิลที่กําหนดเองเหล่านี้จะทํางานเป็นกลุ่ม โดยคุณจะต้องประมวลผลค่า PTS เพื่อกําหนดเวลาเหตุการณ์อย่างเหมาะสม IMA DAI SDK สามารถจัดการเรื่องนี้ให้คุณได้โดยใช้เมธอด streamManager processMetadata()

เช่น

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 จะแสดงเหตุการณ์เป็นส่วนหนึ่งของเหตุการณ์ timelineregionenter เนื่องจากรูปแบบไม่เข้ากันได้กับ Shaka Player คุณจึงต้องดึงข้อมูลค่าข้อมูลเมตาในรูปแบบไฟล์ดิบผ่านพร็อพเพอร์ตี้รายละเอียด eventNode.attributes['messageData']

เช่น

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

การแสดงพ็อด

สำหรับการแสดงพ็อด จะมีการกําหนดค่าที่แตกต่างกันสำหรับการส่งข้อมูลเมตาแบบกำหนดเวลา ทั้งนี้ขึ้นอยู่กับเกณฑ์ต่อไปนี้

  • ประเภทสตรีมแบบสดหรือ VOD
  • รูปแบบสตรีม HLS หรือ DASH
  • ประเภทของโปรแกรมเล่นที่ใช้
  • ประเภทแบ็กเอนด์ DAI ที่ใช้

รูปแบบสตรีม HLS (สตรีมแบบสดและ VOD, โปรแกรมเล่น HLS.js)

หากคุณใช้โปรแกรมเล่น HLS.js ให้ฟังเหตุการณ์ FRAG_PARSING_METADATA ของ HLS.js เพื่อรับข้อมูลเมตา ID3 และส่งไปยัง SDK ด้วย StreamManager.processMetadata()

หากต้องการเล่นวิดีโอโดยอัตโนมัติหลังจากที่โหลดทุกอย่างและพร้อมใช้งานแล้ว ให้ฟังเหตุการณ์ HLS.js MANIFEST_PARSED เพื่อทริกเกอร์การเล่น

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 (รูปแบบสตรีม DASH, ประเภทสตรีมแบบสดและ VOD)

หากใช้โปรแกรมเล่น DASH.js คุณต้องใช้สตริงอื่นเพื่อฟังข้อมูลเมตา ID3 สำหรับสตรีมแบบสดหรือ VOD ดังนี้

  • สตรีมแบบสด: 'https://developer.apple.com/streaming/emsg-id3'
  • สตรีม VOD: 'urn:google:dai:2018'

ส่งข้อมูลเมตา ID3 ไปยัง SDK ด้วย StreamManager.processMetadata()

หากต้องการแสดงตัวควบคุมวิดีโอโดยอัตโนมัติหลังจากที่โหลดทุกอย่างและพร้อมใช้งานแล้ว ให้ฟังเหตุการณ์ DASH.js MANIFEST_LOADED

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 ที่มีสตรีมแบบสด (รูปแบบสตรีม DASH)

หากคุณใช้ Shaka Player เพื่อเล่นสตรีมแบบสด ให้ใช้สตริง 'emsg' เพื่อรอเหตุการณ์ข้อมูลเมตา จากนั้นใช้ข้อมูลข้อความเหตุการณ์ในการเรียกใช้ 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 ที่มีสตรีม VOD (รูปแบบสตรีม DASH)

หากคุณใช้ Shaka Player เพื่อเล่นสตรีม VOD ให้ใช้สตริง 'timelineregionenter' เพื่อรอเหตุการณ์ข้อมูลเมตา จากนั้นใช้ข้อมูลข้อความเหตุการณ์ในการเรียกใช้ StreamManager.processMetadata() ด้วยสตริง '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);
       }
}