Pod Serving API 提供对自适应比特率视频广告连播的访问权限,这些广告连播以特定方式准备,可直接拼接到面向用户的 HLS 或 MPEG-DASH 媒体播放列表中。
本指南将重点介绍如何为 VOD 串流实现基本 Pod 服务清单操作服务器。
接收直播清单请求
您的清单操作程序必须提供一个 API 端点来监听来自视频播放器客户端应用的清单请求。此端点至少必须从客户端播放器应用收集一个串流 ID。此串流 ID 用于在广告连播请求中向 Ad Manager 标识串流会话。
您还需要收集一些其他信息,以便识别适当的内容串流,例如内容 ID。
清单请求端点示例
GET /api/stream_id/{stream_id}/video/{content_id}.{format}
Host: {your_domain}
| 路径参数 | |||||
|---|---|---|---|---|---|
| stream_id | 客户端视频播放器应用中的 Ad Manager 串流 ID。 | ||||
| content_id | 与您系统中的内容视频对应的假设 ID。 | ||||
| format | 与数据流格式对应的假设参数。以下任一项: 
 | ||||
检索内容流
使用从清单请求收集的内容 ID 选择要与广告拼接的内容串流。
请求广告连播清单
如需向 Ad Manager 请求广告,您的服务器必须向广告连播端点发出 POST 请求,并传递请求的编码配置文件和广告代码。此请求还包含您在第 1 步中收集的串流 ID。
作为回报,您会收到一个广告连播对象列表,其中包含发布商广告代码请求的广告连播的清单文件,以及应在何时何地将这些广告连播插入到您的内容中的信息。
POST /ondemand/pods/api/v1/network/{network_code}/streams/{stream_id}/adpods
Host: dai.google.com
Content-Type: application/json
| 路径参数 | |
|---|---|
| network_code | 发布商的 Ad Manager 360 广告资源网代码。 | 
| stream_id | 客户端视频播放器应用中的数据流 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 编解码器字符串。 
   示例: | 
| bitrate | Required | 一个整数,表示此配置文件的视频码率上限(以字节/秒为单位)。 | 
| frames_per_second | Required | 视频的浮点 FPS。 | 
| resolution | Required | 一个 JSON 编码值,包含视频的“宽度”和“高度”(以像素为单位)。 
   示例: | 
| 音频设置 | ||
| codec | Required | RFC6381 编解码器字符串。 
   示例: | 
| bitrate | Required | 一个整数,表示此配置文件的最大音频比特率(以每秒字节为单位)。 
   示例: | 
| channels | Required | 一个整数,表示音频声道数量(包括低频声道)。 | 
| sample_rate | Required | 一个整数,表示音频采样率(以赫兹为单位)。 
   示例: | 
| 字幕设置 | ||
| format | Required | 带内字幕使用的文件格式。支持的值为 webvtt或ttml。 | 
| language | Optional | 字幕语言,采用 RFC5646 语言字符串。如果提供,此值仅用于 DASH 渲染。 
   示例: | 
| DAI 选项 | ||
| dash_profile | Optional | 要应用于广告连播清单的 MPEG-DASH 配置文件。此设置仅适用于 DASH 清单。允许的值为 live或on-demand。默认值为on-demand。
   值  
   值  | 
| ad_pod_timeout | Optional | 选择广告和制作广告连播的最长时间(以浮点秒为单位)。在该时间过后,Ad Manager 会在 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 串流。编码配置 ID 与 HLS 清单 URI 的映射。 | 
| mpd_uri | 仅适用于 DASH 串流。DASH MPD 的 URI。 | 
| type | 广告连播的类型。广告连播类型包括: pre、mid或post。 | 
| start | 仅适用于中贴片广告连播。应将此广告连播插入直播中的位置(以浮点秒为单位)。 | 
| duration | 此广告连播的时长(以浮点秒为单位)。 | 
| midroll_index | 仅适用于中贴片广告连播。当前中贴片广告连播的索引。编入索引以 1开头。 | 
请求示例 (c网址)
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请求正文示例
这是上述 c网址 调用中引用的 request-body.json 的内容。
{
  "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 托管的清单的一组链接。
迭代编码配置文件
对于每个编码配置文件,从 Ad Manager 的响应中收集所有关联的广告连播清单以及其关联的开始时间。对于前贴片广告连播,请将开始时间设置为 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 格式的串流,则只需生成一个文件。与 HLS 相比,这可以让 DASH 串流更易于拼接。
正确准备的 MPEG DASH 媒体演示说明 (MPD) 文件应包含多个时段,每个时段包含多个表示法。每个表示法都应与您的某个编码配置文件相匹配。从 Ad Manager 返回的每个广告连播也是一个 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 示例
这是上方广告连播 JSON 中的 mpd_uri 内容。
<?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>
其他资源
- 使用 IMA SDK 投放播放广告连播:
- 使用 DAI API 实现 Pod 投放播放