Обработка синхронизированных метаданных в линейных потоках DAI.

SDK интерактивной медиарекламы (IMA) для динамической вставки рекламы (DAI) использует информацию метаданных, встроенную в медиасегменты потока (внутриполосные метаданные) или в файл манифеста потоковой передачи (метаданные в манифесте) для отслеживания позиций зрителей и клиентов. -сторонние рекламные мероприятия. Метаданные отправляются в разных форматах, в зависимости от типа воспроизводимого потока.

Видеопроигрыватель получает синхронизированные метаданные пакетами. В зависимости от игрока метаданные могут отображаться в запланированное время или в пакетном режиме. Каждая строка метаданных имеет связанную с ней метку времени представления (PTS), указывающую, когда она должна быть активирована.

Ваше приложение отвечает за сбор метаданных и их пересылку в IMA DAI SDK. SDK предлагает следующие методы передачи этой информации:

onTimedMetadata

Этот метод пересылает строки метаданных, готовые к обработке, в SDK. Требуется один аргумент:

  • metadata : объект, содержащий ключ TXXX со связанным строковым значением с префиксом google_ .
процессМетаданные

Этот метод планирует обработку строк метаданных SDK после указанного PTS. Он принимает следующие аргументы:

  • type : строка, содержащая тип обрабатываемого события. Допустимые значения: ID3 для HLS или urn:google:dai:2018 для DASH.
  • data : либо строковое значение с префиксом google_ , либо массив байтов, который декодирует такую ​​строку.
  • timestamp : отметка времени в секундах, когда данные должны быть обработаны.

Каждый тип потока, поддерживаемый IMA DAI SDK, использует уникальную форму синхронизированных метаданных, как описано в следующих разделах.

HLS MPEG2TS потоки

Линейные потоки DAI HLS, использующие сегменты 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-потоки

Линейные потоки DAI HLS с использованием Common Media Application Framework (CMAF) передают синхронизированные метаданные через внутриполосные блоки eMSGv1 в соответствии со стандартом ID3 через CMAF . Эти блоки eMSG встроены в начало каждого медиасегмента, причем каждый eMSG ID3 содержит PTS относительно последнего разрыва в потоке.

Начиная с версии 1.2.0 HLS.js, оба предлагаемых нами проигрывателя передают 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 передают метаданные как события манифеста в потоке событий с пользовательским значением schemeIdUri urn:google:dai:2018 . Каждое событие в этих потоках содержит текстовую полезную нагрузку и PTS.

DASH.js

Dash.js предоставляет настраиваемые обработчики событий, названные в честь значения SchemaIdUri каждого потока событий. Эти пользовательские обработчики срабатывают пакетно, оставляя вам возможность обработать значение PTS, чтобы правильно рассчитать время события. IMA DAI SDK может справиться с этим за вас с помощью методаstreamManagerprocessMetadata 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 (потоки Live и VOD, проигрыватель HLS.js)

Если вы используете проигрыватель HLS.js , прослушайте событие HLS.js FRAG_PARSING_METADATA , чтобы получить метаданные ID3, и передайте их в SDK с помощью StreamManager.processMetadata() .

Чтобы автоматически воспроизвести видео после того, как все будет загружено и готово, прослушайте событие 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, тип потоков Live и VOD)

Если вы используете проигрыватель DASH.js , вам придется использовать разные строки для прослушивания метаданных ID3 для потоков Live или VOD:

  • Прямые трансляции: 'https://developer.apple.com/streaming/emsg-id3'
  • VOD-трансляции: 'urn:google:dai:2018'

Передайте метаданные ID3 в SDK с помощью StreamManager.processMetadata() .

Чтобы автоматически отображать элементы управления видео после того, как все будет загружено и готово, прослушайте событие 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});
}

Shaka Player с потоками VOD (формат потоков DASH)

Если вы используете проигрыватель Shaka для воспроизведения потока 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);
       }
}