Обработка синхронизированных метаданных

Выберите платформу: HTML5 Roku

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

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

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

onTimedMetadata

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

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

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

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

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

Потоки HLS MPEG2TS

Линейные потоки DAI HLS, использующие сегменты MPEG2TS, передают синхронизированные метаданные видеоплееру через внутриполосные теги ID3. Эти теги ID3 встраиваются в сегменты MPEG2TS и получают имя поля TXXX (для пользовательского текстового контента).

Воспроизведение в Safari

Safari обрабатывает теги ID3 автоматически, как скрытые треки, поэтому события cuechange срабатывают в нужное время для обработки каждого элемента метаданных. В SDK IMA 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

HLS.js предоставляет ID3-теги пакетами через событие FRAG_PARSING_METADATA в виде массива сэмплов. HLS.js не преобразует данные ID3 из массивов байтов в строки и не смещает события в соответствующие PTS. Нет необходимости декодировать данные сэмплов из массива байтов в строку или отфильтровывать нерелевантные ID3-теги, поскольку SDK IMA DAI выполняет это декодирование и фильтрацию автоматически.

Вот пример:

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 встраиваются в начало каждого медиасегмента, при этом каждый блок ID3 eMSG содержит PTS относительно последнего разрыва в потоке.

Начиная с версии 1.2.0 HLS.js, оба предлагаемых нами плеера передают ID3 через CMAF пользователю как ID3-теги. По этой причине следующие примеры идентичны примерам для потоков HLS MPEG2TS. Однако это может быть не так для всех плееров, поэтому для реализации поддержки потоков HLS CMAF может потребоваться уникальный код для анализа ID3 через eMSG.

Воспроизведение в Safari

Safari обрабатывает метаданные ID3 через eMSG как псевдо-события ID3, предоставляя их пакетами автоматически в виде скрытого трека, так что события cuechange срабатывают в нужное время для обработки каждого фрагмента метаданных. Допустимо передавать в SDK IMA DAI все метаданные, независимо от того, имеют ли они отношение к синхронизации или нет. Любые метаданные, не связанные с 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. Нет необходимости декодировать данные сэмплов из массива байтов в строку, поскольку SDK IMA DAI выполняет это декодирование автоматически.

Вот пример:

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 для корректного определения времени события. SDK IMA DAI может сделать это за вас с помощью метода 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 event. Из-за несовместимости форматирования с Shaka Player значение метаданных необходимо получать в необработанном виде через свойство detail 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);
  }
});
...

Подача в капсуле

Для обслуживания Pod-ов существуют различные конфигурации передачи временных метаданных в зависимости от следующих критериев:

  • Тип трансляции: прямая трансляция или видео по запросу
  • Формат потока HLS или DASH
  • Тип используемого игрока
  • Тип используемого бэкэнда DAI

Формат потоковой передачи HLS (прямые трансляции и видео по запросу, плеер HLS.js)

Если вы используете плеер HLS.js , отслеживайте событие HLS.js FRAG_PARSING_METADATA , чтобы получить метаданные 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, типы потоков: прямые трансляции и видео по запросу)

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

  • Прямые трансляции: 'https://developer.apple.com/streaming/emsg-id3'
  • VOD streams: '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 streams)

Если вы используете 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 с потоковым видео по запросу (формат DASH).

Если вы используете плеер 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);
       }
}