선형 DAI 스트림의 시간이 지정된 메타데이터 처리

양방향 미디어 광고 (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_가 접두사로 지정된 문자열 값 또는 이러한 문자열로 디코딩되는 바이트 배열입니다.
  • 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 스트림

CMAF (Common Media Application Framework)를 사용하는 선형 DAI HLS 스트림은 ID3~CMAF 표준에 따라 대역 내 eMSGv1 박스를 통해 시간 지정된 메타데이터를 전달합니다. 이러한 eMSG 박스가 각 미디어 세그먼트의 시작 부분에 삽입되고 각 ID3 eMSG에는 스트림의 마지막 불연속성에 대한 PTS가 포함됩니다.

HLS.js 1.2.0 출시에서는 두 가지 추천 플레이어가 모두 마치 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는 ID3을 통한 eMSG 메타데이터를 의사 ID3 이벤트로 취급하여 FRAG_PARSING_METADATA 이벤트를 통해 ID3을 샘플 배열로 일괄 제공합니다. 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 스트림은 맞춤 schemeIdUriurn: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는 timelineregionenter 이벤트의 일부로 이벤트를 표시합니다. Shaka Player와의 형식 비호환성으로 인해 메타데이터 값은 세부정보 속성 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 플레이어를 사용하는 경우 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 스트림이 포함된 Shaka Player (DASH 스트림 형식)

VOD 스트림 재생에 Shaka 플레이어를 사용하는 경우 '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);
       }
}