Page Summary
-
This guide provides steps for building a client application to load HLS or DASH livestreams with Pod serving API and a manifest manipulator.
-
Prerequisites include configuring a livestream event with the
Pod serving redirectDAI type and determining IMA SDK availability for your platform. -
To initiate a stream, make a
POSTrequest to the livestream service method, passing ad targeting parameters, and store the returned stream session ID and other data from the JSON response. -
Poll for ad metadata by making a
GETrequest to themetadata_urlobtained from the stream registration response, saving thetagsobject and setting a timer based onpolling_frequency. -
Load the stream into your video player using the session ID and listen for ad events by checking timed metadata in your stream's container format.
-
Show ad event data by using the ad event ID to find corresponding
TagSegmentandAdBreakobjects from the ad metadata. -
Send media verification pings for all ad events except those of type
progressby appending the full ad event ID to themedia_verification_urland making aGETrequest.
This guide covers developing a client application to load an HLS or DASH livestream with Pod serving API and your manifest manipulator.
Prerequisites
Before continuing, you must have the following:
A custom asset key for a livestream event configured with the
Pod serving redirectDAI type. To get this key, follow:Use a SOAP API client library to call the
LiveStreamEventService.createLiveStreamEventsmethod with aLiveStreamEventobject and thedynamicAdInsertionTypeproperty set to thePOD_SERVING_REDIRECTenum value. For all client libraries, see Client libraries and example code.
Determine if the Interactive Media Ads (IMA) SDK is available for your platform. We recommend using the IMA SDK to enhance revenue. For details, see Set up the IMA SDk for DAI.
Make a stream request
When your user selects a stream, do the following:
Make a
POSTrequest to the livestream service method. For details, see Method: stream.Pass ad targeting parameters in
application/x-www-form-urlencodedorapplication/jsonformats. This request registers a stream session with Google DAI.The following example makes a stream request:
Form encoding
const url = `https://dai.google.com/ssai/pods/api/v1/` + `network/NETWORK_CODE/custom_asset/CUSTOM_ASSET_KEY/stream`; const params = new URLSearchParams({ cust_params: 'section=sports&page=golf,tennis' }).toString(); const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params }); console.log(await response.json());JSON encoding
const url = `https://dai.google.com/ssai/pods/api/v1/` + `network/NETWORK_CODE/custom_asset/CUSTOM_ASSET_KEY/stream`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ cust_params: { section: 'sports', page: 'golf,tennis' } }) }); console.log(await response.json());If successful, you see output similar to the following:
{ "stream_id": "c4a5dad5-aaa8-4550-8acb-7cda3cdb21bb:DLS", "media_verification_url": "https://dai.google.com/view/.../event/c14aZDWtQg-ZwQaEGl6bYA/media/", "metadata_url": "https://dai.google.com/linear/pods/hls/.../metadata", "session_update_url": "https://dai.google.com/linear/.../session", "polling_frequency": 10 }In the JSON response, locate the stream session ID and store other data for subsequent steps.
Poll ad metadata
To poll ad metadata, do the following:
Read the
metadata_urlvalue from the stream registration response.Make an initial
GETrequest to themetadata_urlendpoint.- Omit the
delta_tokenquery parameter. This process lets the server return the full metadata for the stream's Digital Video Recorder (DVR) window. The DVR window contains the timeframe of the broadcast available for a viewer to rewind and play. The response includes anext_delta_tokenfield.
- Omit the
To optimize bandwidth, store the
next_delta_tokenvalue from the most recent response.On your next request, send that value as the
delta_tokenquery parameter. The server returns only the metadata that changed since that token was generated. Always send the latest token you received. Don't attempt to parse, modify, or construct the token. For details, see Method: metadata.The following example fetches ad metadata:
// Initial request (returns full metadata and next_delta_token) let response = await fetch(metadata_url); let metadata = await response.json(); let deltaToken = metadata.next_delta_token; // Subsequent request (returns only changes since deltaToken) if (deltaToken) { const url = new URL(metadata_url); url.searchParams.append('delta_token', deltaToken); response = await fetch(url.toString()); const deltaMetadata = await response.json(); // Merge deltaMetadata into your local cache mergeMetadata(metadata, deltaMetadata); deltaToken = deltaMetadata.next_delta_token; }If successful, you receive the PodMetadata response. If you provide the
delta_tokenparameter, the response contains only the ads, ad breaks, and tags that the server added or updated since the server generated the token. The response also contains a newnext_delta_tokenvalue. If any ad breaks are outdated, the response also includes anobsolete_ad_break_idslist of the ad breaks to remove from your cache.{ "next_delta_token": "eyJyYW5nZXMiOlt7InMiOjEsImUiOjN9XX0", "obsolete_ad_break_ids": ["0003069407"], "tags":{ "google_1022389921":{ "ad":"0003069408_ad1", "ad_break_id":"0003069408", "type":"start" }, ... }, "ads":{ "0003069408_ad1":{ "ad_break_id":"0003069408", "position":1, "duration":10.01, "title":"External - Pod Midroll 1", "clickthrough_url":"https://.../", ... }, ... }, "ad_breaks":{ "0003069408":{ "type":"mid", "duration":30, "ads":3 }, ... } }Save the
tagsobject and merge updates into your local cache. If theobsolete_ad_break_idsparameter is present, remove those ad breaks and associated ads and tags from your cache.Set a timer using the
polling_frequencyvalue to regularly request metadata. In each poll, send thenext_delta_tokenvalue returned in the most recent metadata response as thedelta_tokenquery parameter.
Load the stream into your video player
After you have the session ID from the registration response, pass the ID to your manifest manipulator, or construct a manifest URL to load the stream into a video player.
To pass the session ID, see your manifest manipulator documentation. If you develop a manifest manipulator, see Manifest manipulator for livestream.
The following example assembles a manifest URL:
https://<your_manifest_manipulator_url>/manifest.m3u8?DAI_stream_ID=SESSION_ID&network_code=NETWORK_CODE&DAI_custom_asset_key=CUSTOM_ASSET_KEY"
When your player is ready, begin playback.
Listen for ad events
Check your stream's container format for the timed metadata:
HLS streams with Transport Stream (TS) containers use timed ID3 tags to carry timed metadata. For details, see About the Common Media Application Format with HTTP Live Streaming (HLS).
DASH streams use
EventStreamelements to specify events in the manifest.DASH streams use
InbandEventStreamelements when the segments contain Event Message (emsg) boxes for payload data, including ID3 tags. For details, see InbandEventStream.CMAF streams, including DASH and HLS, use
emsgboxes containing ID3 tags.
To retrieve ID3 tags from your stream, refer to your video player's guide. For details, see Handle timed metadata guide
To retrieve the ad event ID from ID3 tags, do the following:
- Filter the events by
scheme_id_uriwithurn:google:dai:2018orhttps://aomedia.org/emsg/ID3. Extract the byte array from the
message_datafield.The following example decodes the
emsgdata into JSON:{ "scheme_id_uri": "https://developer.apple.com/streaming/emsg-id3", "presentation_time": 27554, "timescale": 1000, "message_data": "ID3TXXXgoogle_1022389921", ... }Filter the ID3 tags with the format
TXXXgoogle_{ad_event_ID}:TXXXgoogle_1022389921
Show ad event data
To find the
TagSegment
object, do the following:
Retrieve the ad metadata
tagsobject from Poll ad metadata. Thetagsobject is an array ofTagSegmentobjects.Use the full ad event ID to find a
TagSegmentobject with the typeprogress.Use the first 17 characters of the ad event ID to find a
TagSegmentobject of other types.Because your client app polls ad metadata periodically, a delay might occur between when your video player encounters an ID3 tag in the stream and when the associated metadata is available. If your client app doesn't find an ID3 tag in the stored tags, keep the tag in a queue and re-process the tag after the next metadata poll. Keep the tag in the queue until processing finishes.
After you have the
TagSegment, use thead_break_idproperty as the key to find theAdBreakobject in the ad metadataad_breaksobject.The following example finds an
AdBreakobject:{ "type":"mid", "duration":15, "ads":1 }Use the
TagSegmentandAdBreakdata to show information about the ad position in the ad break. For example,Ad 1 of 3.
Send media verification pings
For every ad event, except the progress type, send a media verification ping.
Google DAI discards progress events, and sending these events frequently might
impact your app performance.
To generate the complete media verification URL of an ad event, do the following:
From the stream response, append the full ad event ID to the
media_verification_urlvalue.Make a
GETrequest with the complete URL:// media_verification_url: "https://dai.google.com/view/.../event/c14aZDWtQg-ZwQaEGl6bYA/media/" const completeUrl = `${media_verification_url}google_1022389921`; const response = await fetch(completeUrl);If successful, you receive a code status
202response. Otherwise, you receive a404error code.
You can use the Stream Activity Monitor (SAM) to inspect a historical log of all ad events. For details, see monitor and troubleshoot a livestream