Xử lý siêu dữ liệu đã hẹn giờ trong luồng DAI tuyến tính

SDK Quảng cáo trên phương tiện truyền thông tương tác (IMA) sử dụng tính năng Chèn quảng cáo động (DAI) thông tin siêu dữ liệu được nhúng trong các phân đoạn nội dung đa phương tiện của luồng (siêu dữ liệu trong băng tần), hoặc trong tệp kê khai phát trực tuyến (siêu dữ liệu trong tệp kê khai) để theo dõi lượt xem vị trí và sự kiện quảng cáo phía máy khách. Siêu dữ liệu được gửi ở nhiều định dạng, tuỳ thuộc vào loại luồng đang được phát.

Trình phát video nhận được siêu dữ liệu được tính giờ theo lô. Tuỳ thuộc vào người chơi, siêu dữ liệu có thể xuất hiện tại thời điểm đã lên lịch hoặc theo lô. Từng siêu dữ liệu chuỗi có dấu thời gian trình bày được liên kết (PTS) để cho biết thời điểm cần đã kích hoạt.

Ứng dụng của bạn chịu trách nhiệm ghi lại siêu dữ liệu và chuyển tiếp siêu dữ liệu đó đến SDK IMA DAI. SDK cung cấp các phương thức sau để chuyển thông tin này:

onTimedMetadata

Phương thức này sẽ chuyển tiếp các chuỗi siêu dữ liệu đã sẵn sàng để xử lý đến SDK. Hàm này chỉ nhận một đối số:

  • metadata: một đối tượng chứa khoá của TXXX kèm theo một chuỗi liên kết có tiền tố google_.
processMetadata

Phương thức này lên lịch để SDK xử lý các chuỗi siêu dữ liệu sau PTS được chỉ định. Hàm này nhận các đối số sau:

  • type: một chuỗi chứa loại sự kiện đang được xử lý. Đã chấp nhận các giá trị là ID3 cho HLS hoặc urn:google:dai:2018 cho DASH
  • data: là một giá trị chuỗi có tiền tố google_ hoặc một mảng byte giải mã thành một chuỗi như vậy.
  • timestamp: dấu thời gian tính bằng giây khi dữ liệu được xử lý.

Mỗi loại luồng được SDK IMA DAI hỗ trợ sử dụng một hình thức duy nhất của thời gian như được mô tả trong các phần sau.

Luồng MPEG2TS HLS

Luồng HLS (Chèn quảng cáo động) tuyến tính bằng cách sử dụng phân đoạn MPEG2TS sẽ truyền siêu dữ liệu được định thời gian đến trình phát video thông qua thẻ ID3 trong băng tần. Các thẻ ID3 này được nhúng trong Phân đoạn MPEG2TS và được cung cấp tên trường TXXX (dành cho văn bản do người dùng xác định tuỳ chỉnh nội dung).

Phát trong Safari

Safari tự động xử lý các thẻ ID3, dưới dạng kênh ẩn, do đó, các sự kiện thay đổi tín hiệu kích hoạt vào đúng thời điểm để xử lý từng phần siêu dữ liệu. Bạn có thể vượt qua tất cả siêu dữ liệu cho SDK IMA DAI, bất kể nội dung hay loại. Không liên quan thì siêu dữ liệu sẽ được lọc tự động.

Ví dụ:

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 cung cấp các thẻ ID3 theo đợt thông qua sự kiện FRAG_PARSING_METADATA, dưới dạng một mảng mẫu. HLS.js không dịch dữ liệu ID3 từ các mảng byte vào chuỗi và không bù trừ các sự kiện cho PTS tương ứng. Không phải để giải mã dữ liệu mẫu từ mảng byte thành chuỗi hoặc lọc ra thẻ ID3 không liên quan, vì SDK IMA DAI thực hiện việc giải mã và lọc này tự động.

Ví dụ:

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

Luồng CMAF HLS

Luồng HLS cho DAI tuyến tính bằng cách sử dụng thẻ Khung ứng dụng đa phương tiện chung (CMAF) siêu dữ liệu được định thời gian thông qua các hộp eMSGv1 trong băng tần theo sau ID3 đến CMAF. Các hộp eMSG này được nhúng ở đầu mỗi phân đoạn nội dung đa phương tiện, với mỗi eMSG ID3 có chứa một PTS liên quan đến điểm gián đoạn gần đây nhất trong luồng.

Kể từ bản phát hành 1.2.0 của HLS.js, cả hai trình phát được đề xuất của chúng tôi đều vượt qua ID3 thông qua CMAF đến người dùng như thể họ là thẻ ID3. Vì lý do này, các ví dụ sau cũng giống như đối với luồng MPEG2TS HLS. Tuy nhiên, việc này có thể không áp dụng với tất cả trình phát, vì vậy, việc triển khai việc hỗ trợ cho HLS CMAF luồng có thể yêu cầu mã duy nhất để phân tích cú pháp ID3 thông qua eMSG.

Phát trong Safari

Safari coi ID3 thông qua siêu dữ liệu eMSG là các sự kiện ID3 giả, cung cấp chúng trong các lô, tự động, dưới dạng kênh ẩn, sao cho sự kiện cuechange được được kích hoạt vào thời điểm chính xác để xử lý từng phần siêu dữ liệu. OK truyền tất cả siêu dữ liệu đến SDK IMA DAI, cho dù có liên quan đến thời gian hay không. Bất kỳ hạng nào Siêu dữ liệu không liên quan đến DAI được tự động lọc ra.

Ví dụ:

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

Kể từ phiên bản 1.2.0, HLS.js coi ID3 thông qua siêu dữ liệu eMSG là ID3 giả các sự kiện, cung cấp chúng theo lô, thông qua sự kiện FRAG_PARSING_METADATA, dưới dạng một mảng mẫu. HLS.js không dịch dữ liệu ID3 từ các mảng byte vào chuỗi và không bù trừ các sự kiện cho PTS tương ứng. Không phải cần thiết để giải mã dữ liệu mẫu từ mảng byte thành chuỗi, vì SDK IMA DAI thực hiện việc giải mã này tự động.

Ví dụ:

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

Luồng DASH

Luồng DAI DASH tuyến tính truyền siêu dữ liệu dưới dạng các sự kiện tệp kê khai trong luồng sự kiện với giá trị schemeIdUri tuỳ chỉnh urn:google:dai:2018. Mỗi sự kiện trong luồng chứa tải trọng văn bản và PTS.

DASH.js

Dash.js cung cấp trình xử lý sự kiện tuỳ chỉnh được đặt tên theo giá trị lập trình idUri của mỗi trình xử lý sự kiện luồng sự kiện. Các trình xử lý tuỳ chỉnh này kích hoạt hàng loạt, do đó bạn có toàn quyền quyết định xử lý giá trị PTS để định thời gian cho sự kiện đúng cách. SDK IMA DAI có thể xử lý thực hiện việc này cho bạn bằng phương thức StreamManager, processMetadata().

Ví dụ:

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

Trình phát Shaka

Shaka Player hiển thị các sự kiện trong sự kiện timelineregionenter của họ. Hạn không tương thích về định dạng với Shaka Player, thì giá trị siêu dữ liệu phải là truy xuất dữ liệu thô, thông qua thuộc tính chi tiết eventElement.attributes['messageData'].value.

Ví dụ:

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

Phân phát nhóm

Đối với tính năng Phân phát nhóm, có nhiều cấu hình để truyền theo thời gian tuỳ thuộc vào các tiêu chí sau:

  • Loại sự kiện phát trực tiếp hoặc video theo yêu cầu
  • Định dạng luồng HLS hoặc DASH
  • Loại trình phát đang được sử dụng
  • Loại phần phụ trợ DAI đang được sử dụng

Định dạng luồng HLS (luồng trực tiếp và VOD, trình phát HLS.js)

Nếu bạn đang sử dụng trình phát HLS.js, hãy nghe sự kiện FRAG_PARSING_METADATA HLS.js để nhận siêu dữ liệu ID3 và truyền siêu dữ liệu đó đến SDK với StreamManager.processMetadata().

Để tự động phát video sau khi mọi thứ đã được tải và sẵn sàng, hãy nghe sự kiện MANIFEST_PARSED HLS.js để kích hoạt phát lại.

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 (định dạng luồng DASH, loại luồng trực tiếp và VOD)

Nếu bạn đang sử dụng trình phát DASH.js, bạn phải sử dụng các chuỗi khác nhau để nghe siêu dữ liệu ID3 cho Nội dung phát trực tiếp hoặc VOD luồng:

  • Sự kiện phát trực tiếp: 'https://developer.apple.com/streaming/emsg-id3'
  • Luồng video theo yêu cầu: 'urn:google:dai:2018'

Truyền siêu dữ liệu ID3 đến SDK bằng StreamManager.processMetadata().

Cách tự động hiển thị các nút điều khiển video sau khi mọi thứ đã được tải và sẵn sàng: theo dõi sự kiện 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 với sự kiện phát trực tiếp (định dạng luồng DASH)

Nếu bạn đang sử dụng trình phát Shaaka cho phát trực tiếp, hãy sử dụng chuỗi 'emsg' để nghe các sự kiện siêu dữ liệu. Sau đó, sử dụng dữ liệu tin nhắn sự kiện trong cuộc gọi của bạn đến 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});
}

Trình phát Shaka với luồng VOD (định dạng luồng DASH)

Nếu bạn đang sử dụng trình phát Shaaka cho Phát luồng VOD, sử dụng chuỗi 'timelineregionenter' để nghe sự kiện siêu dữ liệu. Sau đó, hãy sử dụng dữ liệu tin nhắn sự kiện trong cuộc gọi của bạn để StreamManager.processMetadata() bằng chuỗi '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);
       }
}