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
สำหรับ DASHdata
: ค่าสตริงที่ขึ้นต้นด้วยgoogle_
หรืออาร์เรย์ไบต์ที่ เป็นไปตามรูปแบบนี้ID3:u\0004u\000u\000u\0000TXXXu\0004u\000u\000u\0000google_xxxxxxxx
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);
}
}