The Pod Serving API provides access to encoded and conditioned ad segments, prepared in such a way that they can be stitched directly into a user-facing HLS or MPEG-DASH media playlist. For MPEG-DASH, the Pod Serving API also provides a manifest template to provide additional information and context for these ad segments.
This guide is focused on implementing a basic Pod Serving manifest manipulation server for live streams.
Prerequisite: Configure livestream events in Google Ad Manager
Before making any requests from the pod serving API, you must create an Ad
Manager livestream event for each stream you process. You can create a
livestream event using the LiveStreamEventService API
or the Google Ad Manager web interface
.
For a livestream event to be used with the pod serving API, you will need to populate several attributes of your event:
-
customAssetKey
- A custom identifier to be used for this Event. Must be unique across all Events for the network. -
adTags
- Primary ad tag URL generated by the Ad Manager trafficking workflow. -
dynamicAdInsertionType
- Must be set toPOD_SERVING_REDIRECT
. -
streamingFormat
- Set toHLS
orDASH
accordingly. -
segmentUrlAuthenticationKeyIds
- at least one HMAC key used to sign ad segment requests. -
daiEncodingProfileIds
- A list of the DAIEncodingProfile IDs enabled for this event. -
startDateTime
- The start date and time of the event -
endDateTime
- The scheduled end date and time of this event. This attribute is required ifunlimitedEndDateTime
is false and ignored if
unlimitedEndDateTimeis true.
unlimitedEndDateTime` - Boolean. See above.
Receive stream manifest requests
Your manifest manipulator must provide an API endpoint to listen for manifest requests from the video player client app. At minimum, this endpoint must collect a stream ID from the client player app, and must return a stitched stream manifest. The stream ID is used to identify the streaming session to Ad Manager.
You also need to collect some other information to identify the appropriate content stream, for example, a content ID.
Example of a potential manifest request endpoint
GET/api/video/{asset_key}/manifest.{format} Host:{your_domain}
asset_key
format
mpd
|
For MPEG-DASH streams |
---|---|
m3u8
|
For HLS streams |
stream_id
Retrieve the content stream
Use the content ID collected from the manifest request to select the content stream to stitch with ads.
Stitch ad segments into content stream
Stitching ad segment URLs will differ, depending on your stream format.
HLS streams
HLS streams are usually served as a multivariant manifest, which will contain a set of links to variant manifests, which correspond to each of the encoding profiles.
note: For simplicity, this guide assumes that your HLS media is encoded in a format which muxes audio and video into the same segment file.
Proxy multivariant playlists
You will need to replace each variant playlist URL in the original multivariant playlist with another endpoint call to the manipulator to process the player's selected variant manifest.
The remaining steps for stitching HLS will assume that a single variant manifest is being processed.
Example of a potential variant request endpoint
GET/api/video/{asset_key}/variant/{variant_id}.m3u8 Host:{your_domain}
asset_key
variant
stream_id
Example unprocessed multivariant manifest
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.4d000c,mp4a.40.5"
https://cdn.{...}/1080p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720,CODECS="avc1.4d000c,mp4a.40.5"
https://cdn.{...}/720p.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.4d000d,mp4a.40.5"
https://cdn.{...}/360p.m3u8
Example proxied multivariant manifest
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.4d000c,mp4a.40.5"
https://{manifest_manipulator}/api/video/tears_of_steel/variant/1080p.m3u8?stream_id=6e69425c-0ac5-43ef-b070-c5143ba68541:CHS
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=1280x720,CODECS="avc1.4d000c,mp4a.40.5"
https://{manifest_manipulator}/api/video/tears_of_steel/variant/720p.m3u8?stream_id=6e69425c-0ac5-43ef-b070-c5143ba68541:CHS
#EXT-X-STREAM-INF:BANDWIDTH=1000000,RESOLUTION=640x360,CODECS="avc1.4d000d,mp4a.40.5"
https://{manifest_manipulator}/api/video/tears_of_steel/variant/360p.m3u8?stream_id=6e69425c-0ac5-43ef-b070-c5143ba68541:CHS
Identify ad break segments and insert discontinuities
As you process the variant manifest, keep track of the start time, duration, and index of the next upcoming ad break, until the dynamic manifest being processed contains segments that will be replaced by the ad content.
Ad breaks may be delineated from content segments in different ways, depending
on your encoder. One common way to delineate an ad break is to preface the ad
segments with an #EXT-X-CUE-OUT
tag and follow it with an #EXT-X-CUE-IN
tag.
To separate Google-hosted ad breaks from your content segments, you must insert #EXT-X-DISCONTINUITY
tags at the start and end of each ad break. If these
discontinuity tags don't appear in the final manifest, playback will fail.
The inserted ad segment URIs are unencrypted. If your content is encrypted,
you will also need to remove encryption by specifying #EXT-X-KEY:METHOD=NONE
prior to the first ad segment of each ad break and then add it back after the
ad break.
Sample manifest (original)
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:5.005,
contentorigin.com/1.ts
#EXTINF:5.005,
contentorigin.com/2.ts #EXT-X-CUE-OUT:15.000#EXTINF:5.005, contentorigin.com/3.ts#EXTINF:5.005, contentorigin.com/4.ts#EXTINF:5.005, contentorigin.com/5.ts#EXTINF:5.000,d contentorigin.com/6.ts #EXT-X-CUE-IN#EXTINF:5.005,
contentorigin.com/7.mp4
#EXTINF:5.005,
contentorigin.com/8.mp4
Manifest with discontinuities inserted
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:5.005,
contentorigin.com/1.ts
#EXTINF:5.005,
contentorigin.com/2.ts
#EXTINF:5.005, #EXT-X-DISCONTINUITY
{... New segments will go here ...}
#EXT-X-DISCONTINUITY#EXTINF:5.005,
contentorigin.com/7.mp4
#EXTINF:5.005,
contentorigin.com/8.mp4
Process ad pod segments
For each segment within an ad pod, you must track a few additional values:
-
segment_number
: Segment index within the ad pod, starting with zero. Or "init" for mp4 initialization segment. -
segment_duration
: Duration of the current segment in milliseconds. This value should be the same for all segments except the last one in the pod. -
segment_offset
: Segment offset calculated by adding the previous segment's duration to its segment offset in milliseconds -
last
: Boolean value identifying the last segment in an ad pod. Defaults to false.
Build ad segment URLs
Replace each segment within the ad break with a URL of the format:
/linear/pods/v1/seg/network/{network_code}/custom_asset/{custom_asset_key}/{pod_identifier}/profile/{profile_name}/{segment_number}.(ts|mp4|vtt|aac|ac3|eac3)
network_code
custom_asset_key
pod_identifier
The following formats are supported:
pod/{integer}
The numeric identifier for the current ad break. Ad pod IDs are
assigned incrementally for each ad break event, starting at 1
.
ad_break_id/{string}
The string identifier for the current ad break.
profile_name
segment_number
When using MP4 container, the initialization segment can be requested by setting segment_number to "init".
stream_id
stream_id
param returned from the Stream Create
request.sd
segment_duration
so
segment_offset
If so
is missing, it's assumed that previous segments all
have the same duration and the segment offset is calculated from segment_number
and sd
.
pd
ad_pod_duration
.last
The query parameter values must be properly encoded to be URL-safe. This is
especially important for the auth-token
field, since it could contain /
, +
, and =
characters.
Sample manifest (after segment replacement)
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:5.005,
contentorigin.com/1.ts
#EXTINF:5.005,
contentorigin.com/2.ts #EXT-X-DISCONTINUITY#EXTINF:5.005, https://dai.google.com/linear/pods/v1/seg/network/6062/custom_asset/iYdOkYZdQ1KFULXSN0Gi7g/ad_break_id/adbreak1/profile/devrel4628000/0.ts?sd=5005&so=0&pd=18015&auth-token=ad_break_id%3Dadbreak1~custom_asset_key%3DiYdOkYZdQ1KFULXSN0Gi7g~cust_params%3D~exp%3D1489680000~network_code%3D6062~pd%3D180000~hmac%3D44bf78223c240cbc5bae3cdfd794bfc6971b6583cd296f44ef3a46944605cf9a&stream_id=fe6c9136-09a4-4ff6-862e-daee1dea0e1b:MRN2#EXTINF:5.005, https://dai.google.com/linear/pods/v1/seg/network/6062/custom_asset/iYdOkYZdQ1KFULXSN0Gi7g/ad_break_id/adbreak1/profile/devrel4628000/1.ts?sd=5005&so=5005&pd=18015&auth-token=ad_break_id%3Dadbreak1~custom_asset_key%3DiYdOkYZdQ1KFULXSN0Gi7g~cust_params%3D~exp%3D1489680000~network_code%3D6062~pd%3D180000~hmac%3D44bf78223c240cbc5bae3cdfd794bfc6971b6583cd296f44ef3a46944605cf9a&stream_id=fe6c9136-09a4-4ff6-862e-daee1dea0e1b:MRN2#EXTINF:5.005, https://dai.google.com/linear/pods/v1/seg/network/6062/custom_asset/iYdOkYZdQ1KFULXSN0Gi7g/ad_break_id/adbreak1/profile/devrel4628000/2.ts?sd=5005&so=10010&pd=18015&auth-token=ad_break_id%3adbreak1~custom_asset_key%3DiYdOkYZdQ1KFULXSN0Gi7g~cust_params%3D~exp%3D1489680000~network_code%3D6062~pd%3D180000~hmac%3D44bf78223c240cbc5bae3cdfd794bfc6971b6583cd296f44ef3a46944605cf9a&stream_id=fe6c9136-09a4-4ff6-862e-daee1dea0e1b:MRN2#EXTINF:3.000, https://dai.google.com/linear/pods/v1/seg/network/6062/custom_asset/iYdOkYZdQ1KFULXSN0Gi7g/ad_break_id/adbreak1/profile/devrel4628000/3.ts?sd=3000&so=15015&pd=18015&auth-token=ad_break_id%3Dadbreak1~custom_asset_key%3DiYdOkYZdQ1KFULXSN0Gi7g~cust_params%3D~exp%3D1489680000~network_code%3D6062~pd%3D180000~hmac%3D44bf78223c240cbc5bae3cdfd794bfc6971b6583cd296f44ef3a46944605cf9a&stream_id=fe6c9136-09a4-4ff6-862e-daee1dea0e1b:MRN2&last=true #EXT-X-DISCONTINUITY#EXTINF:5.005,
contentorigin.com/7.mp4
#EXTINF:5.005,
contentorigin.com/8.mp4
Congratulations! You are now serving a livestream with ad segments provided by the DAI Pod Serving API.
DASH Streams
DASH Streams are provided as an MPD file, which contains all stream encodings in a single file, where content is represented as a series of periods.
Request period template
Request a period template from Google Ad Manager. This template will become your ad break period, once the macros it contains are populated.
You should only request this template once per stream session, and cache it for reuse with each ad break.
Period template request endpointhjf
GET/linear/pods/v1/dash/network/{network_code}/custom_asset/{custom_asset}/pods.json Host:dai.google.com Content-Type:application/json
network_code
custom_asset
stream_id
dash_period_template
segment_duration_ms
Example request (cURL)
curl
https://dai.google.com/linear/pods/v1/dash/network/21775744923/custom_asset/tears_of_steel/pods.json?stream-id =
cc59197a-44c0-4be2-a8cc-9a6fdb80158f:DLS
Example response
{
"dash_period_template"
:
"<Period id="
adpod
-
$$pod
-
id$$
" $$period-start$$ $$period-duration$$> <BaseURL>https://dai.google.com/linear/pods/v1/seg/event/{event_code}/pods/$$pod-id$$/profile/</BaseURL>
<SegmentTemplate initialization="
$Represe
ntat
io
n
ID$/i
n
i
t
.mp
4
?s
trea
m_id=
{
a
-
s
trea
m
-
id
}
& amp;sd=
5000
& pd=$$pod
-
dura
t
io
n
$$&cus
t
_params=$$cus
t
_params$$&au
t
h_
t
oke
n
=$$
t
oke
n
$$
" media="
$Represe
ntat
io
n
ID$/$Number$.mp
4
?s
trea
m_id=
{
a
-
s
trea
m
-
id
}
& amp;sd=
5000
& pd=$$pod
-
dura
t
io
n
$$&cus
t
_params=$$cus
t
_params$$&sc
te
35
=$$sc
te
35
$$&au
t
h_
t
oke
n
=$$
t
oke
n
$$
" startNumber="
1
" presentationTimeOffset="
0
"
> <SegmentTimeline>
<S t="
0
" d="
5
" r="
$$
nu
mber
-
o
f
-
repea
te
d
-
segme
nts
$$
"/
> </SegmentTimeline>
</SegmentTemplate>
<AdaptationSet id="
0
" width="
1280
" height="
720
" frameRate="
30
" contentType="
video
" subsegmentAlignment="
true
" startWithSAP="
1
"
> <InbandEventStream schemeIdUri="
h
tt
ps
:
//developer.apple.com/streaming/emsg-id3"/
>
< Role
schemeIdUri=
"urn:mpeg:dash:role:2011"
value=
"main"
/
>
< Represe
ntat
io
n
mimeType=
"video/mp4"
codecs=
"avc1.640029"
id=
"a943ff679a2f3e71d9181a21b7542122g"
ba
n
dwid
t
h=
"3200000"
/
>
< Represe
ntat
io
n
mimeType=
"video/mp4"
codecs=
"avc1.640029"
id=
"abbbd80q4w5ce2fs28308rd1f4g4bat0"
ba
n
dwid
t
h=
"1500000"
/
>
< /Adap
tat
io
n
Se
t
>
< Adap
tat
io
n
Se
t
id=
"1"
co
ntent
Type=
"audio"
>
< Represe
ntat
io
n
audioSampli
n
gRa
te
=
"48000"
mimeType=
"audio/mp4"
codecs=
"mp4a.40.2"
id=
"a87ff679a2f3e71d9181a67b7542122c"
ba
n
dwid
t
h=
"95000"
/
>
< Represe
ntat
io
n
audioSampli
n
gRa
te
=
"48000"
mimeType=
"audio/mp4"
codecs=
"mp4a.40.2"
id=
"eccbc87e4b5ce2fe28308fd9f2a7baf3"
ba
n
dwid
t
h=
"127000"
/
>
< /Adap
tat
io
n
Se
t
>
< /Period
> ",
"
segme
nt
_dura
t
io
n
_ms":5000}
Populate the period template
The period template contains several macros that you must replace for each ad break. All macros must be replaced. Unused macros should be replaced with an empty string ("").
Macro | Description | Example |
---|---|---|
$$pod-id$$
|
The index of the ad pod this period represents. This value must match for the same pod across all viewer sessions. | 1
|
$$period-start$$
|
The time when the period starts in the current MPD. An optional attribute
that should be replaced by start="###"
, where ###
is the presentation time at which the ad break starts. If
the period's start time is not provided, this macro should be replaced
with an empty string. |
start="PT2H33M30S"
|
$$period-duration$$
|
The duration of the complete ad period. An optional attribute that should
be replaced by duration="###"
, where ###
is the
duration of the ad period in the standard DASH duration format. If the
period's duration is not provided, this macro should be replaced with an
empty string. |
duration="PT15S"
|
$$pod-duration$$
|
The expected duration of ads to be decisioned for this pod, in milliseconds. | 15000
|
$$number-of-repeated-segments$$
|
This value is calculated by dividing the ad period duration (in milliseconds) by the value of segment_duration_ms, and rounding up to the nearest whole number. | 3
|
$$cust_params$$
|
This macro can be replaced by the custom targeting parameters unique to the current ad break, if. provided. The value must be formatted as described in this Ad Manager Help Center article . If no custom params are needed this macro should be replaced with an empty string. | &cust_params=section%3Dblog%26anotherKey%3Dvalue1%2Cvalue2
|
$$scte35$$
|
This macro needs to be replaced by a scte35 value unique to that ad break, if one is provided. If no scte35 information is needed, this macro should be replaced with an empty string. | /DAqAAAAAAAA///wDwVAAAT2f0/+ecF1mQABC/8ACgAIQ1VFSQAAAAsuZVlR
|
$$token$$
|
A signed, url-encoded HMAC token . This token is required. | custom_asset_key%3DiYdOkYZdQ1KFULXSN0Gi7g~exp%3D1489680000~network_code%3D6062~pd%3D180000~pod_id%3D5~hmac%3D6a8c44c72e4718ff63ad2284edf2a8b9e319600b430349d31195c99b505858c9
|
Raw period template, containing macros
<Period
id="adpod-$$pod-id$$"
$$period-start$$
$$period-duration$$>
<BaseURL>
https://dai.google.com/linear/pods/v1/seg/event/{event_code}/pods/$$pod-id$$/profile/
</BaseURL>
<SegmentTemplate
initialization="$RepresentationID$/init.mp4?stream_id=cc59197a-44c0-4be2-a8cc-9a6fdb80158f:DLS&sd=5000&pd=$$pod-duration$$&cust_params=$$cust_params$$&auth_token=$$token$$"
media="$RepresentationID$/$Number$.mp4?stream_id=ç√&sd=5000&pd=$$pod-duration$$&cust_params=$$cust_params$$&scte35=$$scte35$$&auth_token=$$token$$"
startNumber="1"
presentationTimeOffset="0">
<SegmentTimeline>
<S
t="0"
d="5"
r="$$number-of-repeated-segments$$"/>
</SegmentTimeline>
</SegmentTemplate>
<AdaptationSet
id="0"
width="1280"
height="720"
frameRate="30"
contentType="video"
subsegmentAlignment="true"
startWithSAP="1">
<InbandEventStream
schemeIdUri="https://developer.apple.com/streaming/emsg-id3"/>
<Role
schemeIdUri="urn:mpeg:dash:role:2011"
value="main"/>
<Representation
mimeType="video/mp4"
codecs="avc1.640029"
id="a943ff679a2f3e71d9181a21b7542122g"
bandwidth="3200000"/>
<Representation
mimeType="video/mp4"
codecs="avc1.640029"
id="abbbd80q4w5ce2fs28308rd1f4g4bat0"
bandwidth="1500000"/>
</AdaptationSet>
<AdaptationSet
id="1"
contentType="audio">
<Representation
audioSamplingRate="48000"
mimeType="audio/mp4"
codecs="mp4a.40.2"
id="a87ff679a2f3e71d9181a67b7542122c"
bandwidth="95000"/>
<Representation
audioSamplingRate="48000"
mimeType="audio/mp4"
codecs="mp4a.40.2"
id="eccbc87e4b5ce2fe28308fd9f2a7baf3"
bandwidth="127000"/>
</AdaptationSet>
</Period>
Populated ad period
<Period
id="pod-0"
start="PT5H50M12S">
<BaseURL>
https://dai.google.com/linear/pods/v1/seg/event/M-nTcApTRTi6CEGIt4GYMw/pod/0/profile/
</BaseURL>
<SegmentTemplate
startNumber="0"
media="1080p/0.mp4?stream_id=cc59197a-44c0-4be2-a8cc-9a6fdb80158f:DLS&sd=5000&pd=30000&cust_params=&auth-token=&scte35="
initialization="$RepresentationID$/init.mp4?stream_id=cc59197a-44c0-4be2-a8cc-9a6fdb80158f:DLS&pd=30000&cust_params=&auth-token=&scte35=">
<SegmentTimeline>
<S
d="5"
r="1"/>
</SegmentTimeline>
</SegmentTemplate>
<AdaptationSet
mimeType="video/mp4"
scanType="progressive"
contentType="video">
<Role
schemeIdUri="urn:mpeg:dash:role:2011"
value="main"/>
<Representation
width="768"
height="432"
frameRate="30"
codecs="avc1.42c01e"
id="fmp4-video-1200k"
bandwidth="1300000">
<InbandEventStream
schemeIdUri="https://developer.apple.com/streaming/emsg-id3"/>
</Representation>
</AdaptationSet>
<AdaptationSet
mimeType="audio/mp4"
scanType="progressive"
contentType="audio">
<Role
schemeIdUri="urn:mpeg:dash:role:2011"
value="main"/>
<Representation
audioSamplingRate="48000"
codecs="mp4a.40.2"
id="fmp4-audio-128kbps"
bandwidth="128000">
<AudioChannelConfiguration
schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011"
value="2"/>
</Representation>
</AdaptationSet>
</Period>
Insert your populated period into the DASH Manifest
Finally, replace the appropriate period in your raw manifest with the newly populated ad period, and return the final stitched manifest to the requesting video client, for playback.
Example raw content manifest
<?xml version="1.0"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:DASH:schema:MPD:2011" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011" profiles="urn:mpeg:dash:profile:isoff-main:2011" type="static" mediaPresentationDuration="PT0H9M56.46S">
<BaseURL>
http://example.com/tears_of_steel/
</BaseURL> <Period start="PT0S">
<AdaptationSet bitstreamSwitching="true">
<Representation id="0" codecs="avc1" mimeType="video/mp4" width="1920" height="1080" startWithSAP="1" bandwidth="500000">
<SegmentBase>
<Initialization sourceURL="segments/1080/1.m4s" range="0-862"/>
</SegmentBase>
<SegmentList duration="15">
<SegmentURL media="segments/1080p/2.m4s" mediaRange="863-7113"/>
<SegmentURL media="segments/1080p/3.m4s" mediaRange="7114-14104"/>
<SegmentURL media="segments/1080p/4.m4s" mediaRange="14105-17990"/>
...
</SegmentList>
</Representation>
<Representation id="1" codecs="avc1" mimeType="video/mp4" width="1280" height="720" startWithSAP="1" bandwidth="250000">
<SegmentBase>
<Initialization sourceURL="segments/720p/1.m4s" range="0-864"/>
</SegmentBase>
<SegmentList duration="15">
<SegmentURL media="segments/720p/2.m4s" mediaRange="865-11523"/>
<SegmentURL media="segments/720p/3.m4s" mediaRange="11524-25621"/>
<SegmentURL media="segments/720p/4.m4s" mediaRange="25622-33693"/>
...
</SegmentList>
</Representation>
<Representation id="1" codecs="avc1" mimeType="video/mp4" width="640" height="480" startWithSAP="1" bandwidth="100000">
<SegmentBase>
<Initialization sourceURL="segment/480p/1.m4s" range="0-865"/>
</SegmentBase>
<SegmentList duration="15">
<SegmentURL media="segment/480p/2.m4s" mediaRange="866-26970"/>
<SegmentURL media="segment/480p/3.m4s" mediaRange="26971-72543"/>
<SegmentURL media="segment/480p/4.m4s" mediaRange="72544-95972"/>
...
</SegmentList>
</Representation>
...
</AdaptationSet>
</Period end></MPD>
Example stitched manifest
<?xml version="1.0"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:mpeg:DASH:schema:MPD:2011" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011" profiles="urn:mpeg:dash:profile:isoff-main:2011" type="static" mediaPresentationDuration="PT0H9M56.46S">
<BaseURL>
http://example.com/tears_of_steel/
</BaseURL> <Period id="pod-0" start="PT5H50M12S">
<BaseURL>
https://dai.google.com/linear/pods/v1/seg/event/M-nTcApTRTi6CEGIt4GYMw/pod/0/profile/
</BaseURL>
<SegmentTemplate startNumber="0" media="1080p/0.mp4?stream_id=cc59197a-44c0-4be2-a8cc-9a6fdb80158f:DLS&sd=5000&pd=30000&cust_params=&auth-token=&scte35=$$scte35$$" initialization="$RepresentationID$/init.mp4?stream_id=cc59197a-44c0-4be2-a8cc-9a6fdb80158f:DLS&pd=30000&cust_params=&auth-token=&scte35=$$scte35$$">
<SegmentTimeline>
<S d="5" r="1"/>
</SegmentTimeline>
</SegmentTemplate>
<AdaptationSet mimeType="video/mp4" scanType="progressive" contentType="video">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<Representation width="768" height="432" frameRate="30" codecs="avc1.42c01e" id="fmp4-video-1200k" bandwidth="1300000">
<InbandEventStream schemeIdUri="https://developer.apple.com/streaming/emsg-id3"/>
</Representation>
</AdaptationSet>
<AdaptationSet mimeType="audio/mp4" scanType="progressive" contentType="audio">
<Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
<Representation audioSamplingRate="48000" codecs="mp4a.40.2" id="fmp4-audio-128kbps" bandwidth="128000">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
</Representation>
</AdaptationSet>
</Period></MPD>
Congratulations! You are now serving a DASH livestream with ad segments provided by the DAI Pod Serving API.
Additional resources
- Pod serving playback with the IMA SDK:
- Pod serving playback with the DAI API