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 eventendDateTime
- 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}
Path parameters | |||||
---|---|---|---|---|---|
asset_key |
A hypothetical ID corresponding to the requested livestream in your system. | ||||
format |
A hypothetical parameter corresponding to the stream format. One of either:
|
Query parameters | |
---|---|
stream_id |
The Ad Manager stream ID from the client video player app. |
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}
Path parameters | |
---|---|
asset_key |
A hypothetical ID corresponding to the requested livestream in your system. |
variant |
A hypothetical parameter containing an identifier for the specific variant being processed. |
Query parameters | |
---|---|
stream_id |
The Ad Manager stream ID from the client video player app. used here to identify a user session with the manifest manipulator. |
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 millisecondslast
: 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)
Path parameters | |
---|---|
network_code
|
The Ad Manager 360 network code for this network. |
custom_asset_key
|
The custom livestream asset key specified in the LiveStreamEventService API or on the livestream page in the Ad Manager 360 web interface. |
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
ad_break_id/{string}
The string identifier for the current ad break. |
profile_name
|
Identifier for the profile being requested, |
segment_number
|
The index of this segment within the current ad pod, starting at zero. When using MP4 container, the initialization segment can be requested by setting segment_number to "init". |
Query parameters | ||
---|---|---|
stream_id
|
Required | The user's stream_id param returned from the Stream Create
request.
|
sd
|
Required | segment_duration
|
so
|
Optional | segment_offset
If |
pd
|
Required, except for events with durationless ad breaks enabled | The duration (in milliseconds) of the ad break. Also referred to as
ad_pod_duration .
|
auth-token
|
Required | A signed, url-encoded HMAC token for this ad pod. |
last
|
Optional | Boolean indicating the last segment in the ad break. Defaults to false. |
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
Path parameters | |
---|---|
network_code |
The publisher's Ad Manager 360 network code. |
custom_asset |
The custom asset key of the livestream event in Google Ad Manager. |
Query parameters | |
---|---|
stream_id |
The Ad Manager stream ID from the client video player. |
Response JSON | |
---|---|
dash_period_template |
The period template XML string. |
segment_duration_ms |
The duration of each ad media segment in the dash period template, in milliseconds. |
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="$RepresentationID$/init.mp4?stream_id={a-stream-id}&sd=5000&pd=$$pod-duration$$&cust_params=$$cust_params$$&auth_token=$$token$$" media="$RepresentationID$/$Number$.mp4?stream_id={a-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>",
"segment_duration_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