양방향 미디어 광고 (IMA) 동적 광고 삽입 (DAI) SDK는 스트림의 미디어 세그먼트 (인밴드 메타데이터) 또는 스트리밍 매니페스트 파일 (인매니페스트 메타데이터)에 삽입된 메타데이터 정보를 사용하여 시청자의 위치와 클라이언트 측 광고 이벤트를 추적합니다. 메타데이터는 재생되는 스트림의 유형에 따라 다른 형식으로 전송됩니다.
동영상 플레이어는 시간 제한 메타데이터를 일괄적으로 수신합니다. 플레이어에 따라 메타데이터가 예약된 시간에 표시되거나 일괄적으로 표시될 수 있습니다. 각 메타데이터 문자열에는 트리거되어야 하는 시점의 연결된 프레젠테이션 타임스탬프 (PTS)가 있습니다.
앱에서 메타데이터를 캡처하여 IMA DAI SDK로 전달해야 합니다. SDK는 이 정보를 전달하는 다음 메서드를 제공합니다.
- onTimedMetadata
이 메서드는 처리할 준비가 된 메타데이터 문자열을 SDK에 전달합니다. 다음과 같은 단일 인수를 사용합니다.
metadata
:google_
로 시작하는 연결된 문자열 값이 있는TXXX
키를 포함하는 객체입니다.
- processMetadata
이 메서드는 지정된 PTS 이후에 SDK에서 처리할 메타데이터 문자열을 예약합니다. 다음 인수를 사용합니다.
type
: 처리 중인 이벤트 유형을 포함하는 문자열입니다. 허용되는 값은 HLS의 경우ID3
, DASH의 경우urn:google:dai:2018
입니다.data
:google_
이 앞에 붙은 문자열 값 또는ID3:u\0004u\000u\000u\0000TXXXu\0004u\000u\000u\0000google_xxxxxxxx
형식을 따르는 바이트 배열입니다.timestamp
: 데이터를 처리해야 하는 시간(초)입니다.
IMA DAI SDK에서 지원하는 각 스트림 유형은 다음 섹션에 설명된 대로 고유한 형태의 시간 제한 메타데이터를 사용합니다.
HLS MPEG2TS 스트림
MPEG2TS 세그먼트를 사용하는 선형 DAI HLS 스트림은 인밴드 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는 FRAG_PARSING_METADATA
이벤트를 통해 ID3 태그를 샘플 배열로 일괄 제공합니다. HLS.js는 바이트 배열의 ID3 데이터를 문자열로 변환하지 않으며 이벤트가 해당 PTS로 오프셋되지 않습니다. IMA DAI SDK가 이 디코딩과 필터링을 자동으로 실행하므로 바이트 배열에서 문자열로 샘플 데이터를 디코딩하거나 관련 없는 ID3 태그를 필터링할 필요가 없습니다.
예를 들면 다음과 같습니다.
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 스트림
Common Media Application Framework (CMAF)를 사용하는 선형 DAI HLS 스트림은 ID3 through CMAF 표준에 따라 인밴드 eMSGv1 상자를 통해 시간 메타데이터를 전달합니다. 이러한 eMSG 상자는 각 미디어 세그먼트의 시작 부분에 삽입되며 각 ID3 eMSG에는 스트림의 마지막 불연속점과 관련된 PTS가 포함됩니다.
HLS.js 1.2.0 출시 이후로 Google에서 추천하는 두 플레이어 모두 ID3 태그인 것처럼 CMAF를 통해 사용자에게 ID3를 전달합니다. 따라서 다음 예는 HLS MPEG2TS 스트림과 동일합니다. 하지만 모든 플레이어에서 이와 같지는 않을 수 있으므로 HLS CMAF 스트림 지원을 구현하려면 eMSG를 통해 ID3를 파싱하는 고유 코드가 필요할 수 있습니다.
Safari에서 재생
Safari는 eMSG 메타데이터를 통한 ID3를 유사 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는 eMSG 메타데이터를 통한 ID3를 의사 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 스트림은 맞춤 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 플레이어를 사용하는 경우 HLS.js FRAG_PARSING_METADATA
이벤트를 수신하여 ID3 메타데이터를 가져오고 StreamManager.processMetadata()
를 사용하여 SDK에 전달합니다.
모든 항목이 로드되고 준비된 후 동영상을 자동으로 재생하려면 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 플레이어를 사용하는 경우 라이브 또는 VOD 스트림의 ID3 메타데이터를 수신 대기하려면 다른 문자열을 사용해야 합니다.
- 라이브 스트림:
'https://developer.apple.com/streaming/emsg-id3'
- VOD 스트림:
'urn:google:dai:2018'
StreamManager.processMetadata()
를 사용하여 ID3 메타데이터를 SDK에 전달합니다.
모든 항목이 로드되고 준비된 후 동영상 컨트롤을 자동으로 표시하려면 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 플레이어를 사용하는 경우 문자열 '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});
}
VOD 스트림 (DASH 스트림 형식)이 있는 Shaka Player
VOD 스트림 재생에 Shaka player를 사용하는 경우 'timelineregionenter'
문자열을 사용하여 메타데이터 이벤트를 수신 대기합니다. 그런 다음 'urn:google:dai:2018'
문자열을 사용하여 StreamManager.processMetadata()
호출에서 이벤트 메시지 데이터를 사용합니다.
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);
}
}