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 投放播放