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_xxxxxxxxtimestamp: การประทับเวลาเป็นวินาทีเมื่อควรประมวลผลข้อมูล
สตรีมแต่ละประเภทที่ 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
สตรีม HLS ของ DAI แบบเชิงเส้นที่ใช้ Common Media Application Framework (CMAF) จะส่งข้อมูลเมตาที่มีการกำหนดเวลาผ่านกล่อง eMSGv1 แบบ In-band ตามมาตรฐาน ID3 ผ่าน CMAF กล่อง eMSG เหล่านี้จะ ฝังอยู่ที่จุดเริ่มต้นของแต่ละกลุ่มสื่อ โดย eMSG ของ ID3 แต่ละรายการจะมี 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 event
เป็นอาร์เรย์ของตัวอย่าง 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
สตรีม DASH ของ DAI เชิงเส้นจะส่งข้อมูลเมตาเป็นเหตุการณ์ในไฟล์ 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 event เนื่องจากรูปแบบไม่เข้ากันกับ 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()
หากต้องการเล่นวิดีโอโดยอัตโนมัติหลังจากโหลดทุกอย่างเสร็จสิ้นและพร้อมใช้งาน ให้ฟังเหตุการณ์ 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);
}
}