Манипулятор манифеста для потоков VOD

API обслуживания модулей обеспечивает доступ к модулям видеорекламы с адаптивным битрейтом, подготовленным таким образом, что их можно вставлять непосредственно в пользовательский плейлист мультимедиа HLS или MPEG-DASH.

Это руководство сосредоточено на реализации базового сервера манипуляции манифестами Pod Serving для потоков VOD.

Получение запросов манифеста потока

Ваш манипулятор манифеста должен предоставить конечную точку API для прослушивания запросов манифеста от клиентского приложения видеопроигрывателя. Как минимум, эта конечная точка должна получить идентификатор потока из клиентского приложения проигрывателя. Этот идентификатор потока используется для идентификации сеанса потоковой передачи в Менеджере рекламы в запросах вашего пакета объявлений.

Вам также необходимо собрать некоторую другую информацию для идентификации соответствующего потока контента, например идентификатор контента.

Пример конечной точки запроса манифеста

GET /api/stream_id/{stream_id}/video/{content_id}.{format}
Host: {your_domain}
Параметры пути
stream_id Идентификатор потока Менеджера рекламы из клиентского видеоплеера.
content_id Гипотетический идентификатор, соответствующий видеоконтенту в вашей системе.
format Гипотетический параметр, соответствующий формату потока. Один из следующих вариантов:
mpd Для потоков MPEG-DASH
m3u8 Для HLS-потоков

Получить поток контента

Используйте идентификатор контента, полученный из запроса манифеста, чтобы выбрать поток контента для объединения с рекламой.

Запрос манифестов рекламных пакетов

Чтобы запросить рекламу из Менеджера рекламы, ваш сервер должен отправить POST-запрос к конечной точке модулей объявлений, передав запрошенные профили кодирования, тег объявления и параметры таргетинга. Этот запрос также включает идентификатор потока, который вы собрали на шаге 1.

Взамен вы получаете список объектов рекламных модулей, содержащий файлы манифеста для рекламных модулей, запрошенных рекламным тегом издателя, а также информацию о том, когда и где они должны быть вставлены в ваш контент.

POST /ondemand/pods/api/v1/network/{network_code}/streams/{stream_id}/adpods
Host: dai.google.com
Content-Type: application/json
Параметры пути
network_code Сетевой код Менеджера рекламы 360 издателя.
stream_id Идентификатор потока из клиентского приложения видеоплеера.

Тело JSON

Параметры тела
encoding_profiles Required Список JSON-представлений профилей кодировки, которые вы хотите получать для каждой рекламной паузы. Подробности смотрите ниже

Чтобы сделать воспроизведение максимально плавным, оно должно соответствовать набору профилей кодирования, используемых в вашем потоке контента.

ad_tag Required Рекламный тег для запроса рекламы VMAP.
cuepoints Optional Список ключевых точек в потоке контента, куда будут вставлены рекламные паузы в середине ролика. Метки измеряются в секундах с плавающей запятой.

Требуется только для ответов VMAP, содержащих промежуточные ролики с использованием позиционных смещений времени. Это редкость.

content_duration_seconds Optional Продолжительность контента в секундах.

Требуется только для ответов VMAP, содержащих промежуточные ролики с процентными смещениями по времени. Это редкость.

manifest_type Optional Формат запрашиваемых рекламных потоков: hls или dash . Значение по умолчанию — hls .
dai_options Optional Дополнительные параметры, управляющие аспектами отображения манифестов. Подробности смотрите ниже
Профиль кодирования
profile_name Required Идентификатор этого профиля кодирования. Это значение может быть любой строкой по вашему выбору, но вы не можете иметь несколько профилей кодирования с одним и тем же именем в одном потоке.
type Required Тип кодирования потока, описываемого этим профилем кодирования. Типы контента: media , iframe , subtitles .
container_type Required Формат контейнера, используемый этим профилем кодирования. Форматы контейнеров: mpeg2ts , fmp4cmaf , hls_packed_audio
video_settings Optional Требуется, если тип профиля кодирования — iframe . В противном случае разрешено только в том случае, если тип мультимедиа содержит видео. Подробности смотрите ниже
audio_settings Optional Требуется, если профиль кодирования содержит аудио. Разрешено только в том случае, если тип медиа. Подробности смотрите ниже
subtitle_settings Optional Требуется, если профиль кодирования содержит субтитры. Подробности смотрите ниже
Настройки видео
codec Required Строка кодека RFC6381.

Пример: avc1.4d000c

bitrate Required Целое число, представляющее максимальный битрейт видео этого профиля в байтах в секунду.
frames_per_second Required Частота кадров видео с плавающей запятой.
resolution Required Значение в формате JSON, содержащее ширину и высоту видео в пикселях.

Пример: {"width": 640, "height": 320}

Настройки звука
codec Required Строка кодека RFC6381.

Пример: mp4a.40.5

bitrate Required Целое число, представляющее максимальный битрейт аудио этого профиля в байтах в секунду.

Пример: 300000

channels Required Целое число, представляющее количество аудиоканалов, включая низкочастотные каналы.
sample_rate Required Целое число, представляющее частоту дискретизации звука в герцах.

Пример: 4800

Настройки субтитров
format Required Формат файла, используемый внутриполосными субтитрами. Поддерживаемые значения: webvtt или ttml .
language Optional Язык субтитров в виде языковой строки RFC5646. Если это значение указано, оно используется только для рендеринга DASH.

Пример: en-us

Опции DAI
dash_profile Optional Профиль MPEG-DASH для применения к манифестам рекламных модулей. Этот параметр используется только для манифестов DASH. Допустимые значения — live или on-demand . Значение по умолчанию — on-demand .

Значение live соответствует профилю MPEG-DASH "urn:mpeg:dash:profile:isoff-live:2011" .

Значение on-demand соответствует профилю MPEG-DASH urn:mpeg:dash:profile:isoff-on-demand:2011 .

ad_pod_timeout Optional Максимальное время, затрачиваемое на выбор объявлений и создание рекламных модулей, в секундах с плавающей запятой. По истечении этого времени Менеджер рекламы возвращает все объявления, уже выбранные в ответе ad_pods , и прекращает обработку.
sam_id Optional Указывает альтернативный ключ отладки, который можно использовать для поиска сеансов в мониторе активности потока .

Ответ

Параметры ответа
valid_for Продолжительность действия этих плейлистов рекламных модулей в формате dhms (дни, часы, минуты, секунды).
valid_until Дата и время, до которых эти плейлисты модулей объявлений действительны в виде строки даты и времени ISO8601, в формате yyyy-MM-dd'T'hh:mm:ss.sssssssss[+|-]hh:mm .
ad_pods Список модулей объявлений, выбранных для этого потока.
Рекламный блок
manifest_uris Только для потоков HLS. Сопоставление идентификаторов профилей кодирования с URI манифеста HLS.
mpd_uri Только для потоков DASH. URI DASH MPD.
type Тип рекламного пакета. Типы рекламных блоков: pre , mid и post .
start Только для пакетов объявлений в середине ролика. Позиция в потоке, куда следует вставить этот рекламный блок, в секундах с плавающей запятой.
duration Продолжительность этого рекламного пакета в секундах с плавающей запятой.
midroll_index Только для пакетов объявлений в середине ролика. Индекс текущего рекламного блока в середине ролика. Индексация начинается с 1 .

Пример запроса (cURL)

curl -X POST \
     -d '@request-body.json' \
     -H 'Content-Type: application/json' \
  https://dai.google.com/ondemand/pods/api/v1/network/21775744923/streams/6e69425c-0ac5-43ef-b070-c5143ba68541:CHS/adpods

Пример тела запроса

Это содержимое request-body.json указанное в вызове cURL выше.

{
  "encoding_profiles": [
   {
     "profile_name": "1080p",
     "type": "media",
     "container_type": "mpeg2ts",
     "video_settings": {
       "codec": "avc1.4d000c",
       "bitrate": 5000000,
       "frames_per_second": 30.0,
       "resolution": {
         "width": 1920,
         "height": 1080
       }
     },
     "audio_settings": {
       "codec": "mp4a.40.5",
       "bitrate": 300000,
       "channels": 2,
       "sample_rate": 48000
     }
   },
   {
     "profile_name": "360p",
     "type": "media",
     "container_type": "mpeg2ts",
     "video_settings": {
       "codec": "avc1.4d000d",
       "bitrate": 1000000,
       "frames_per_second": 30.0,
       "resolution": {
         "width": 640,
         "height": 360
       }
     },
     "audio_settings": {
       "codec": "mp4a.40.5",
       "bitrate": 64000,
       "channels": 2,
       "sample_rate": 48000
     }
   },
   {
     "profile_name": "subtitles-webvtt",
     "type": "subtitles",
     "subtitle_settings": {
       "format": "webvtt"
     }
   }
 ],
 "ad_tag": "https://pubads.g.doubleclick.net/gampad/ads?...",
 "manifest_type": "hls"
}

Пример ответа

{
  "valid_for": "8h0m0s",
  "valid_until": "2023-03-24T08:30:26.839717986-07:00",
  "ad_pods": [
    {
      "manifest_urls":{
        "1080p": "https://{...}/pod/0/profile/1080p.m3u8",
        "360p": "https://{...}/pod/0/profile.m3u8",
        "subtitles-webvtt": "https://{...}/pod/0/profile/subtitles-en.vtt"
      },
      "type": "pre",
      "duration": 10.0
    },
    {
      "manifest_urls":{
        "1080p": "https://{...}/pod/1/profile/1080p.m3u8",
        "360p": "https://{...}/pod/1/profile.m3u8",
        "subtitles-webvtt": "https://{...}/pod/1/profile/subtitles-en.vtt"
      },
      "type": "mid",
      "start": 15.0,
      "duration": 15.0,
      "midroll_index": 1
    },
    {
      "manifest_urls":{
        ]"1080p": "https://{...}/pod/2/profile/1080p.m3u8",
        "360p": "https://{...}/pod/2/profile.m3u8",
        "subtitles-webvtt": "https://{...}/pod/0/profile/subtitles-en.vtt""
      },
      "type": "post",
      "duration": 10.0
    }
  ]
}

Встраивайте рекламные блоки в контент

Процесс встраивания рекламных модулей в ваши потоки контента зависит от вашей реализации, формата потока и того, какие функции вы выбираете для реализации из спецификаций формата. Следующие рабочие процессы представляют собой предложения по управлению этим процессом. Точные детали вашей реализации могут различаться в зависимости от потребностей вашего бизнеса и потоков контента.

HLS-потоки

Если вы сшиваете поток в формате HLS, ваш поток контента будет представлять собой многовариантный список воспроизведения со ссылками на отдельные манифесты потока, по одному для каждого профиля кодирования. Ваши рекламные модули необходимо вставить в каждый из этих вариантов манифеста. Один из способов сделать это — подготовить все манифесты вариантов и передать их в сеть доставки контента (CDN) для размещения. Итоговый многовариантный плейлист представляет собой набор ссылок на эти манифесты, размещенные в CDN.

Перебирать профили кодирования

Для каждого профиля кодирования соберите все связанные манифесты модулей объявлений из ответа Менеджера рекламы вместе с соответствующим временем начала. Для модулей объявлений в начале ролика установите время начала 0 . Для пост-роллов используйте продолжительность контента в качестве времени начала рекламного блока. Определите вариантный поток в многовариантном списке воспроизведения, который соответствует настройкам аудио и видео каждого профиля кодирования.

Пример массива модулей объявлений
"ad_pods": [
    {
      "manifest_urls":{
        "1080p": "https://{...}/pod/0/profile/1080p.m3u8",
        "360p": "https://{...}/pod/0/profile/360p.m3u8",
        "subtitles-en": "https://{...}/pod/0/profile/subitles-en.vtt"
      },
      "type": "pre",
      "duration": 10.0
    },
    {
      "manifest_urls":{
        "1080p": "https://{...}/pod/1/profile/1080p.m3u8",
        "360p": "https://{...}/pod/1/profile/360p.m3u8",
        "subtitles-en": "https://{...}/pod/1/profile/subitles-en.vtt"
      },
      "type": "mid",
      "start": 15.0,
      "duration": 15.0,
      "midroll_index": 1
    },
    {
      "manifest_urls":{
        "1080p": "https://{...}/pod/2/profile/1080p.m3u8",
        "360p": "https://{...}/pod/2/profile/360p.m3u8",
        "subtitles-en": "https://{...}/pod/2/profile/subitles-en.vtt"
      },
      "type": "post",
      "duration": 10.0
    }
  ]
Пример плейлиста с многовариантным контентом
#EXTM3U
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs0",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="https://{...}/subitles-en.vtt"
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.4d000c,mp4a.40.5"
https://{...}/1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.4d000d,mp4a.40.5"
https://{...}/360p.m3u8
Пример собранных данных о вариантах
Encoding profile: "1080p"
Profile settings: {...}
Content manifest: https://{...}/1080p.m3u8
Ad pods (start time -> manifest):
    0 -> https://{...}/pod/0/profile/1080p.m3u8
   15 -> https://{...}/pod/1/profile/1080p.m3u8
  600 -> https://{...}/pod/2/profile/1080p.m3u8

Вставьте рекламу в каждый вариант манифеста.

Для каждого потока вариантов просмотрите сегменты манифеста контента, сохраняя общее количество затраченного времени контента. Когда вы дойдете до начальной позиции рекламного модуля, извлеките список сегментов из манифеста рекламного модуля, оберните список сегментов двумя тегами #EXT-X-DISCONTINUITY и вставьте список в текущее место в манифесте контента. . Продолжайте этот процесс, пока не будут обработаны все блоки объявлений и варианты потоков.

Полученные манифесты должны соответствовать стандарту HLS. Таким образом, в зависимости от того, какие функции спецификации включает в себя ваш манифест контента, вам может потребоваться выполнить окончательный просмотр объединенного манифеста, чтобы исправить порядковые номера мультимедиа, продолжительность контента, порядковые номера разрывов и любые другие теги, которые необходимо обновить, чтобы принять учитывать новые рекламные сегменты. После устранения любых несоответствий со стандартом отправьте манифест каждого конкретного пользовательского варианта в свою CDN для хостинга.

Если ваш манифест контента зашифрован, вам необходимо сохранить последний ключ шифрования, найденный перед запуском текущего рекламного модуля, в теге #EXT-X-KEY . Затем вам нужно добавить тег #EXT-X-KEY:METHOD=NONE чтобы удалить шифрование перед первым сегментом каждого рекламного модуля. Наконец, вы должны добавить копию сохраненного тега #EXT-X-KEY перед первым сегментом контента после каждого рекламного модуля, чтобы восстановить шифрование контента.

Пример собранных данных о вариантах
Encoding profile: "1080p"
Content manifest: https://{...}/1080p.m3u8
Ad pods (start time -> manifest):
    0 -> https://dai.google.com/{...}pod/0/profile/1080p.m3u8
   15 -> https://dai.google.com/{...}pod/1/profile/1080p.m3u8
  600 -> https://dai.google.com/{...}pod/2/profile/1080p.m3u8
Пример манифеста контента

Это содержимое манифеста https://{...}/1080p.m3u8 указанного в собранных данных вариантов.

#EXTM3U
{...}
#EXTINF:5.000,
https://{...}/1080p/content-segment-0.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-1.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-2.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-3.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-4.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-5.ts
{...}
Пример манифеста рекламного блока

Это содержимое манифеста https://dai.google.com/{...}/pod/1/profile/1080p.m3u8 , указанного в собранных данных о вариантах.

#EXTM3U
{...}
#EXTINF:5.000,
https://dai.google.com/{...}/0.ts
#EXTINF:5.000,
https://dai.google.com/{...}/1.ts
#EXTINF:5.000,
https://dai.google.com/{...}/2.ts
Пример манифеста сшитого варианта

Это будет итоговый сшитый вариант манифеста, переданный в CDN и размещенный по адресу https://cdn.{...}/{userid}/1080p.m3u8 .

#EXTM3U
{...}
#EXTINF:5.000,
https://{...}/1080p/content-segment-0.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-1.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-2.ts
#EXT-X-DISCONTINUITY
#EXTINF:5.000,
https://dai.google.com/{...}/0.ts
#EXTINF:5.000,
https://dai.google.com/{...}/1.ts
#EXTINF:5.000,
https://dai.google.com/{...}/2.ts
#EXT-X-DISCONTINUITY
#EXTINF:5.000,
https://{...}/1080p/content-segment-3.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-4.ts
#EXTINF:5.000,
https://{...}/1080p/content-segment-5.ts
{...}

Создайте многовариантный плейлист

Соберите адреса CDN для каждого заполненного вариантного манифеста, а также соответствующие сведения о профиле кодирования и соберите результаты в новый многовариантный манифест. Этот пользовательский манифест возвращается как ответ на запрос манифеста, полученный на шаге 1.

Пример итогового многовариантного плейлиста
#EXTM3U
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs0",LANGUAGE="en",NAME="English",AUTOSELECT=YES,DEFAULT=YES,URI="https://cdn.{...}-subitles-en.vtt"
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.4d000c,mp4a.40.5"
https://cdn.{...}/{userid}/1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.4d000d,mp4a.40.5"
https://cdn.{...}/{userid}/360p.m3u8

Потоки MPEG DASH

Если вы объединяете поток в формате MPEG DASH, вам нужно создать только один файл. Это может упростить объединение потоков DASH, чем HLS.

Правильно подготовленный файл описания медиапрезентации (MPD) MPEG DASH должен состоять из нескольких периодов, каждый из которых содержит несколько представлений. Каждое представление должно соответствовать одному из ваших профилей кодирования. Каждый модуль объявлений, возвращаемый из Менеджера рекламы, также представляет собой файл MPD, содержащий последовательность периодов с совпадающими представлениями.

Чтобы объединить эти файлы MPD, начните с запоминания времени начала каждого рекламного модуля. Для предварительной рекламы вставьте периоды модуля объявлений в начале ролика перед любым периодом контента. Для построллов вставляйте периоды рекламных блоков после всех периодов контента. Перебирайте периоды в MPD контента, отслеживая прошедшее время воспроизведения для всех периодов обработанного контента. Когда вы достигнете границы между периодами, которая соответствует времени начала рекламного блока, вставьте периоды из MPD-файла соответствующего рекламного блока в середине ролика на эту границу.

Окончательный сшитый файл MPD должен полностью соответствовать спецификациям MPEG_DASH, поэтому вам, возможно, придется перебрать окончательный файл еще раз, корректируя время начала периода, фиксируя продолжительность мультимедийного представления с учетом вновь вставленных рекламных периодов и разрешая любые другие конфликты, которые могли возникнуть в процессе сшивания.

Пример содержания MPD

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500000S" type="static" mediaPresentationDuration="PT0H10M00.000S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
  <ProgramInformation moreInformationURL="http://.../info">
    <Title>Example Stream</Title>
  </ProgramInformation>
  <Period duration="PT0H0M15.000S" id="content-period-1">
    ...
  </Period>
  <Period duration="PT0H0M15.000S" id="content-period-2">
    ...
  </Period>
  <Period duration="PT0H0M15.000S" id="content-period-3">
    ...
  </Period>
  ...
</MPD>

Пример рекламного блока в формате JSON

[{
  "mpd_uri": "https://{...}pod/1.mpd",
  "type": "mid",
  "start": 15.0,
  "duration": 15.0,
  "midroll_index": 1
}]

Пример рекламного блока MPD

Это содержимое mpd_uri из JSON рекламного модуля выше.

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500000S" type="static" mediaPresentationDuration="PT0H0M15.000S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
  <ProgramInformation moreInformationURL="http://.../info">
    <Title>Ad Pod 1</Title>
  </ProgramInformation>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-1">
    ...
  </Period>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-2">
    ...
  </Period>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-3">
    ...
  </Period>
  ...
</MPD>

Пример сшитого MPD

Используйте это как ответ на первоначальный запрос манифеста потока.

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" minBufferTime="PT1.500000S" type="static" mediaPresentationDuration="PT0H10M15.000S" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011">
  <ProgramInformation moreInformationURL="http://.../info">
    <Title>Example Stream</Title>
  </ProgramInformation>
  <Period duration="PT0H0M15.000S" id="content-period-1">
    ...
  </Period>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-1">
    ...
  </Period>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-2">
    ...
  </Period>
  <Period duration="PT0H0M5.000S" id="ad-pod-1-period-3">
    ...
  </Period>
  <Period duration="PT0H0M15.000S" id="content-period-2">
    ...
  </Period>
  <Period duration="PT0H0M15.000S" id="content-period-3">
    ...
  </Period>
  ...
</MPD>

Дополнительные ресурсы