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

SDK โฆษณาสื่ออินเทอร์แอกทีฟ (IMA) ของการแทรกโฆษณาแบบไดนามิก (DAI) ต้องใช้ ข้อมูลเมตาที่ฝังในกลุ่มสื่อของสตรีม (ข้อมูลเมตาในวง) หรือในไฟล์ 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_ หรืออาร์เรย์ไบต์ที่ ถอดรหัสเป็นสตริงดังกล่าว
  • timestamp: การประทับเวลาในหน่วยวินาทีที่ควรประมวลผลข้อมูล

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

สตรีม HLS MPEG2TS

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

การเล่นใน Safari

Safari จะประมวลผลแท็ก ID3 โดยอัตโนมัติ เป็นแทร็กที่ซ่อนอยู่ ดังนั้นเหตุการณ์การเปลี่ยนคิว เริ่มทำงานในเวลาที่เหมาะสมเพื่อประมวลผลข้อมูลเมตาแต่ละส่วน ก็ผ่านได้เลย ข้อมูลเมตาทั้งหมดไปยัง 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 รหัส 3 แต่ละกลุ่มมี PTS ที่สัมพันธ์กับความไม่ต่อเนื่องครั้งล่าสุดในสตรีม

จาก HLS.js เวอร์ชัน 1.2.0 โปรแกรมเล่นที่แนะนำของเราทั้งสองส่ง 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

Shaka Player แสดงกิจกรรมต่างๆ โดยเป็นส่วนหนึ่งของกิจกรรม timelineregionenter ครบกำหนด สำหรับรูปแบบเข้ากันไม่ได้กับ Shaka Player ค่าของข้อมูลเมตาต้องเป็น ดึงไฟล์ข้อมูล RAW ผ่านพร็อพเพอร์ตี้แบบละเอียด eventElement.attributes['messageData'].value

เช่น

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

การแสดงในพ็อด

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

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

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

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

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

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()

หากต้องการแสดงตัวควบคุมวิดีโอโดยอัตโนมัติหลังจากโหลดทุกอย่างพร้อมแล้ว ฟังเหตุการณ์ 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 ที่มีสตรีมแบบสด (รูปแบบสตรีม 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);
       }
}