Live - HLS

As in the Live - DASH example the HLS example follows five steps to completely implement VAST tracking client side.

Differences to DASH

For HLS-Live, VAST tracking is supported through Serverside.ai, where the VAST document can be fetched by the client to request the tracking URLs. Different from DASH there are no ad-ids in the HLS-standard manifests. Therefore you need to request the vast endpoint at the right point in time to get the vast response related to the ad that is going to run.

To signal the appearance of an ad there will be a EXT-X-PROGRAMM tag in the HLS manifest: EXT-X-PROGRAM-DATE-TIME:<date-time-msec>. It is now possible to call the vastURL at the moment when an ad is playing and receive the VAST data for this ad.

The rest of the process stays the same. We will nevertheless run through every single step below.

Option 1: Player has no API to retrieve segments

The parameter needed below can be viewed at Serverside.ai or via the https://admin.serverside.ai/api/v2/channels/:channelId API endpoint.

1. Manifest API Request

To retrieve a URL to the HLS master manifest and open a user session on the server use the following endpoint:

https://live.serverside.ai/hls/view/:channelId?&api-key=:api-key

For Example:

https://live.serverside.ai/hls/view/2aaf2594-68f5-43cc-89f5-f683963e2d23?&api-key=2aaf2594-68f5-43cc-89f5-f683963e2d23

In the response you'll get a json with mediaURL and vastURL like:

{
    "mediaURL":"https://live.serverside.ai/hls/:channelId/master.m3u8?sid=:sessionId&api-key=2aaf2594-68f5-43cc-89f5-f683963e2d23",
    "vastURL":"https://live.serverside.ai/hls/:channelId/:sessionId/vast.xml"
}

2. Starting Playback

Handover the mediaURL to the player which will load the manifests and video data.

GET Request:

https://live.serverside.ai/hls/:channelId/master.m3u8?api-key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Response Body:

#EXTM3U
#EXT-X-VERSION:4
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:FRAME-RATE="25.000",RESOLUTION=320x180,CODECS="avc1.4d400c,mp4a.40.2",AVERAGE-BANDWIDTH="545600",BANDWIDTH=545600
1d4b9e30-3232-11ea-a76d-29ae63114b99/320x180.m3u8
#EXT-X-STREAM-INF:FRAME-RATE="25.000",RESOLUTION=480x272,CODECS="avc1.4d4015,mp4a.40.2",AVERAGE-BANDWIDTH="765600",BANDWIDTH=765600
1d4b9e30-3232-11ea-a76d-29ae63114b99/480x270.m3u8
#EXT-X-STREAM-INF:FRAME-RATE="25.000",RESOLUTION=640x360,CODECS="avc1.77.30,mp4a.40.2",AVERAGE-BANDWIDTH="1161600",BANDWIDTH=1161600
1d4b9e30-3232-11ea-a76d-29ae63114b99/640x360.m3u8
#EXT-X-STREAM-INF:FRAME-RATE="25.000",RESOLUTION=960x540,CODECS="avc1.4d401f,mp4a.40.2",AVERAGE-BANDWIDTH="2140600",BANDWIDTH=2140600
1d4b9e30-3232-11ea-a76d-29ae63114b99/960x540.m3u8
#EXT-X-STREAM-INF:FRAME-RATE="25.000",RESOLUTION=1280x720,CODECS="avc1.4d401f,mp4a.40.2",AVERAGE-BANDWIDTH="3339600",BANDWIDTH=3339600
1d4b9e30-3232-11ea-a76d-29ae63114b99/1280x720.m3u8

3. Load-VAST data

To get the VAST document relating to the ad break that is currently playing use the vastURL from above. It will provide the original VAST response document together with the timing information for the synchronization on the player side.

GET Request:

https://live.serverside.ai/hls/:channelId/:sessionId/320x180.m3u8/vast.xml

Response Body:

{
  "time": TIMESTAMP_IN_MS_MATCHING_IMPRESSION_TIME,
  "vast": VAST_XML_STRING
}

Example

GET Request:

https://live.serverside.ai/hls/5cc9789c-44ce-4e20-927e-2f4fc206144f/de025740-ee93-11ea-8452-1140472856cb/VAR(BANDWIDTH=0;RESOLUTION=1280;).m3u8/vast.xml

Response-Body:

time: 1599213250873
vast: "<?xml version="1.0" encoding="UTF-8"?>↵    <VAST version="3.0">↵        <Ad id="7253b601c7fd8e8c1708ca6cff1fb994-3c4ca.d1a64.4c52.30">↵            <InLine>↵                <AdSystem version="1.0">SpotXchange</AdSystem>↵                <AdTitle><![CDATA[Nowtilus Test Ad - 30sec]]></AdTitle>↵                <Description><![CDATA[]]></Description>↵                <Impression><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock/Start?percentage=0]]></Impression>↵                <Error><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock?error=true]]></Error>↵                <Creatives>↵                    <Creative sequence="1">↵                        <Linear>↵                            <Duration>00:00:30</Duration>↵                            <TrackingEvents>↵                                <Tracking event="complete"><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock/Complete?percentage=100]]></Tracking>↵                                <Tracking event="firstQuartile"><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock/25?percentage=25]]></Tracking>↵                                <Tracking event="midpoint"><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock/50?percentage=50]]></Tracking>↵                                <Tracking event="thirdQuartile"><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock/75?percentage=75]]></Tracking>↵                            </TrackingEvents>↵                            <VideoClicks>↵                                <ClickTracking><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock]]></ClickTracking>↵                            </VideoClicks>↵                            <MediaFiles>↵                                <MediaFile delivery="progressive" type="video/mp4" width="480" height="360"><![CDATA[https://cdn.spotxcdn.com/media/videos/orig/1/0/10fa3ca3af9f4600e3eb580eb4da5afc.mp4]]></MediaFile>↵                            </MediaFiles>↵                        </Linear>↵                    </Creative>↵                </Creatives>↵                <Extensions>↵                    <Extension type="Pricing">↵                        <Price model="CPM" currency="USD" source="spotxchange"><![CDATA[0]]></Price>↵                    </Extension>↵                    <Extension type="SpotX-Count">↵                        <total_available><![CDATA[2]]></total_available>↵                    </Extension>↵                    <Extension type="Spotx-Regs">↵                        <GDPR>1</GDPR>↵                    </Extension>↵                    <Extension type="Spotx-User">↵                        <consent>2</consent>↵                    </Extension>↵                </Extensions>↵            </InLine>↵        </Ad>↵    </VAST>"

4. Detect the start of an ad in the stream

Same as for DASH-Live

5. Keep track of the ad playback and send beacons

Same as for DASH-Live

Option 2: Player has an API to retrieve segments

In the case the player has an API to retrieve the currently playing segment use the following option.

1. Manifest API Request

The URL to the ad-insertion enabled channel is called outputUrl and can be viewed at Serverside.ai or via the https://admin.serverside.ai/api/v2/channels/:channelId API endpoint.

An outputUrl for HLS will have the following schema:

https://live.serverside.ai/hls/:channelId/master.m3u8?api-key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

2. Fetching the Master Manifest

An HLS-Live session is created by fetching the master manifest.

GET Request:

https://live.serverside.ai/hls/:channelId/master.m3u8?api-key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Response Body:

#EXTM3U
#EXT-X-VERSION:4
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:FRAME-RATE="25.000",RESOLUTION=320x180,CODECS="avc1.4d400c,mp4a.40.2",AVERAGE-BANDWIDTH="545600",BANDWIDTH=545600
1d4b9e30-3232-11ea-a76d-29ae63114b99/320x180.m3u8
#EXT-X-STREAM-INF:FRAME-RATE="25.000",RESOLUTION=480x272,CODECS="avc1.4d4015,mp4a.40.2",AVERAGE-BANDWIDTH="765600",BANDWIDTH=765600
1d4b9e30-3232-11ea-a76d-29ae63114b99/480x270.m3u8
#EXT-X-STREAM-INF:FRAME-RATE="25.000",RESOLUTION=640x360,CODECS="avc1.77.30,mp4a.40.2",AVERAGE-BANDWIDTH="1161600",BANDWIDTH=1161600
1d4b9e30-3232-11ea-a76d-29ae63114b99/640x360.m3u8
#EXT-X-STREAM-INF:FRAME-RATE="25.000",RESOLUTION=960x540,CODECS="avc1.4d401f,mp4a.40.2",AVERAGE-BANDWIDTH="2140600",BANDWIDTH=2140600
1d4b9e30-3232-11ea-a76d-29ae63114b99/960x540.m3u8
#EXT-X-STREAM-INF:FRAME-RATE="25.000",RESOLUTION=1280x720,CODECS="avc1.4d401f,mp4a.40.2",AVERAGE-BANDWIDTH="3339600",BANDWIDTH=3339600
1d4b9e30-3232-11ea-a76d-29ae63114b99/1280x720.m3u8

3. Load-VAST data

The URIs pointing to the media manifests will contain the session id. Appending /vast to any of the media manifest URI will provide the original VAST response document together with the timing information for the synchronization on the player side.

GET Request:

https://live.serverside.ai/hls/:channelId/:sessionId/320x180.m3u8/vast.xml

Response Body:

{
  "time": TIMESTAMP_IN_MS_MATCHING_IMPRESSION_TIME,
  "vast": VAST_XML_STRING
}

Example

GET Request:

https://live.serverside.ai/hls/5cc9789c-44ce-4e20-927e-2f4fc206144f/de025740-ee93-11ea-8452-1140472856cb/VAR(BANDWIDTH=0;RESOLUTION=1280;).m3u8/vast.xml

Response-Body:

time: 1599213250873
vast: "<?xml version="1.0" encoding="UTF-8"?>↵    <VAST version="3.0">↵        <Ad id="7253b601c7fd8e8c1708ca6cff1fb994-3c4ca.d1a64.4c52.30">↵            <InLine>↵                <AdSystem version="1.0">SpotXchange</AdSystem>↵                <AdTitle><![CDATA[Nowtilus Test Ad - 30sec]]></AdTitle>↵                <Description><![CDATA[]]></Description>↵                <Impression><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock/Start?percentage=0]]></Impression>↵                <Error><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock?error=true]]></Error>↵                <Creatives>↵                    <Creative sequence="1">↵                        <Linear>↵                            <Duration>00:00:30</Duration>↵                            <TrackingEvents>↵                                <Tracking event="complete"><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock/Complete?percentage=100]]></Tracking>↵                                <Tracking event="firstQuartile"><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock/25?percentage=25]]></Tracking>↵                                <Tracking event="midpoint"><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock/50?percentage=50]]></Tracking>↵                                <Tracking event="thirdQuartile"><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock/75?percentage=75]]></Tracking>↵                            </TrackingEvents>↵                            <VideoClicks>↵                                <ClickTracking><![CDATA[http://ad-server-mock.azurewebsites.net/api/ad-server-mock]]></ClickTracking>↵                            </VideoClicks>↵                            <MediaFiles>↵                                <MediaFile delivery="progressive" type="video/mp4" width="480" height="360"><![CDATA[https://cdn.spotxcdn.com/media/videos/orig/1/0/10fa3ca3af9f4600e3eb580eb4da5afc.mp4]]></MediaFile>↵                            </MediaFiles>↵                        </Linear>↵                    </Creative>↵                </Creatives>↵                <Extensions>↵                    <Extension type="Pricing">↵                        <Price model="CPM" currency="USD" source="spotxchange"><![CDATA[0]]></Price>↵                    </Extension>↵                    <Extension type="SpotX-Count">↵                        <total_available><![CDATA[2]]></total_available>↵                    </Extension>↵                    <Extension type="Spotx-Regs">↵                        <GDPR>1</GDPR>↵                    </Extension>↵                    <Extension type="Spotx-User">↵                        <consent>2</consent>↵                    </Extension>↵                </Extensions>↵            </InLine>↵        </Ad>↵    </VAST>"

Find a complete implementation of HLS tracking for JavaScript and hls.js below.

4. Detect the start of an ad in the stream

Same as for DASH-Live

5. Keep track of the ad playback and send beacons

Same as for DASH-Live

Example integration of Option 2

The following HTML page shows a fully working example of the Serverside.ai HLS-live client-side tracking.

VAST Tracking - HLS-Live Example Implementation

Last updated