Live API: Cue Points and Ad Beacons with SSAI

In this topic, you will learn how to manage cue points and ad beacons when using Brightcove's Server-Side Ad Insertion (SSAI) for your live stream jobs.

Overview

Server-side ad insertion (SSAI) allows you display ads during a live streaming event at specified times. For general information, see the Live API: Server-Side Ad Insertion (SSAI) document.

Cue points

Ad breaks are triggered by cue points, which can be specified in two ways:

  • Sent to Brightcove by the encoder
  • Immediate cue points created via the Live API

From the encoder

The Brightcove live delivery system can interpret cue points submitted by the encoder in the AMF format:

      AMFDataList
        [0]:onCuePoint
        [1]:{Obj[]:
        time: 1.9889, //Difference from PTS of THIS packet to the first PTS of the 1st video frame in the adbreak
        name: "scte35",
        type: "event",
        ad_server_data: "eyJrZXkiOiJ2YWx1ZSJ9", // optional introduced by Brightcove. It is a base64 encoded json map of
        parameters e.g. {"key":"value"}
        parameters: {Obj[]:
        type: "avail_in",
        duration: 12.0
        }
        }
    

Notes:

  • Since timecodes are expressed in HH:MM:SS, there is no notion of what day is meant. This can lead to problems such as sending cue point at 23:55:00 for an ad break to start at 00:01:00 and having the server interpret that as almost 24 hours ago. Brightcove has implemented a fix for this as follows: for cue points arriving between 23:50:00 and 00:00:00 only, we will assume you are scheduling an ad break for the following day.
  • Up to 128 cue points can be stacked in a single request, but given the rules around "rollover" explained above, cue points cannot be sent in this manner for the following day.
  • Since SMPTE timecodes are associated with the stream, it is possible that a cue could arrive after the scheduled time in the stream. Brightcove will allow up to a 5 seconds tolerance after the cue to still insert a Cue point.
  • Only avail_in and avail_out type cue points are currently supported in RTMP input.
  • SCTE-35 cue points are supported in RTP and SRT inputs.

Manual cue point insertion

You can create immediate cue points for a job or a redundant group using the Live API by sending a POST request:

Method POST
URL (for a job) https://api.bcovlive.io/v1/jobs/{Job_ID}/cuepoint
URL (for a redundant group) https://api.bcovlive.io/v1/jobs/{Redundant_Group_ID}/cue point
Header X-API-KEY: {your API KEY}

Include a request body specifying the following:

Field Type Description
duration Integer Duration of the break in seconds.

The duration of the cue point being inserted needs to be at least twice the length of the segments in the job. See the duration example.
timecode SMPTE format OPTIONAL: A timecode in SMPTE format, HH:MM:SS:FF (FF = frames), to specify when a set of any variables (key/value pairs) should be passed to the adServer.

If omitted, the cue point will be inserted immediately.

If you use the timecode property, the encoder must be sending SMPTE-formatted (HH:MM:SS:FF) timecode stored in the tc property via OnFI. Timecodes are from the start of the live stream.
ad_server_data Object OPTIONAL: The key/value pairs you pass will depend on the ad server you are using. For more details, see your ad server documentation and the Targeting ads using ad macros section.
cuepoint_id String OPTIONAL: Optional. ID to use when creating cue point. If cancel is true, then this field is required and is the ID of cue point to cancel.
cancel Boolean OPTIONAL: Optional. Default: false. When true, cue point specified by cuepoint_id will be canceled. If the ad break is already in progress, a crash-out will occur, returning to the main content.

Duration example

The duration of the cue point being inserted needs to be at least twice the length of the segments in the job.

For example, inserting a 10 second cue point in a job with "segment_seconds"=4, will work fine. However, inserting the same cue point in a job with "segment_seconds"=6 will result in the following error:

      "error": "The parameter duration should be greater than
        or equal to (2 * target duration) of the job"
      
    
 

Sample request body

      {
        "duration": 30,
        "timecode": "15:50:49:16",
        "ad_server_data" : {
        "adbreakid": 12312
        "breaktheme": "fitness"
        }
        }
    

Notes

  1. Software encoders such as Wirecast and OBS do not support the sending timecode via OnFI packets in the RTMP stream
  2. Elemental hardware encoders do support the sending timecode via OnFI packets in the RTMP stream

Sample response

      {
        "id": "Job_ID",
        "cue_point": {
        "id": "adBreak-2f58393ada1442d98eca0817fa565ba4",
        "duration": 30,
        "accuracy": "segment", [Can be segment or frame ]
        "inserted_at": "2017-07-21T09:30:46.307Z" [ Time when the cue point was inserted in the stream]
        },
        }
    

Beacons

Beacons are data points on playback sent to third-party analytics to track whether and how much of ads were played. In this section we will look at the beacon types that can be set using the Live API, and variables that can be used to provide the data. The next section will detail the API requests use to create and manage beacon sets.

Beacon types

Beacon Types
Beacon Type Description
Load Fired once per session and only triggered when top level manifest is requested
Play Content has been requested and the first segment returned
Heartbeat Target duration (segment seconds)
AdStart Individual ad started
AdFirstQuartile First ad quartile (25%)
AdMidpoint Second ad quartile (50%)
AdThirdQuartile Third ad quartile (75%)
AdComplete Individual ad completed
AdBreakStart Ad break has started
AdBreakComplete ad break has ended

Beacon/Ad variables

The table below shows the variables you can use to provide data for the beacon URLs. To include a variable, surround with double curly braces, like this: {{job.job_id}}. See the next section on managing beacon sets for full examples.

Ad Configuration Variables
Variable
Description
session.session_id
unique session id
job.job_id
unique job id
videocloud.video_id
Only available for jobs created with a VideoCloud video.
application_ad_configuration.description
value of the application at session creation
random.int32
random 32-bit signed integer
random.int64
random 64-bit signed integer
random.uint32
random 32-bit unsigned integer
random.uint64
random 64-bit unsigned integer
random.uuid
random uuid
server.timestamputc
epoch time in milliseconds when the call from the ads-api has been made
client.useragent
http user-agent header value at session creation
client.ipaddress
http x-forwarded-for header value at session creation, if provided, otherwise the remote address
client.referrer
http referer header value at session creation (note: that is the correct spelling)
client.referer
http referer header value at session creation (http spelling)
client.ipuaid
hash value of client.ipaddress and client.useragent
live.adbreak
(currently unused)
live.adbreakdurationms
Ad break duration in milliseconds
live.adbreakduration
Ad break duration in double-precision floating-point seconds
live.adbreakdurationint
Ad break duration in integer seconds
live.adbreak.timestamputc.wallclock
epoch time in milliseconds when the call to the ads server has been made
live.adbreak.timestamputc.origin
epoch time in milliseconds from the origin chunklist. This value indicates the time when the cue out chunk has been created in the origin chunklist.
live.adbreak.timestamputc.session
epoch time in milliseconds from the ssai chunklist. This value indicates the time of the cue out chunk in the ssai chunklist. Since the adbreak content and the adbreak gap are NOT usually the same, after the 1st adbreak the live.adbreak.timestamputc.origin is different from live.adbreak.timestamputc.session. This value takes into account the time adjustments that have been made in the SSAI chunklist.

SCTE-35 ad variables

The Society of Cable Telecommunications Engineers (SCTE) defines a standard for dynamic ad insertion for live streams. An SCTE-35 ad marker defines the timestamp and duration where an ad can be inserted into the stream.

If parsed from SCTE-35, the following configuration variables can be applied to your ad tags:

SCTE-35 Ad Configuration Variables
Variable
Description
{{scte35_eventID}}
an unique event id passed with an SCTE35 message.
{{scte35_programID}}
A unique program id passed with an SCTE35 message.
{{scte35_availNum}}
An id for a specific splice time available for ads, send via a SCTE35 message.
{{scte35_breakDuration}}
Break duration for the ad break, in terms of ticks of the program’s 90 kHz clock, passed with a SCTE35 message.
{{scte35_spliceTime}}
Splice time for an ad break, in terms of ticks of the program’s 90 kHz clock, passed with a SCTE35 message.

As part of the HLS manifests, the SCTE-35 messages are also base64 with the variables in JSON. For example:

      {"scte35_eventID": somevalue, "scte35_programID":
        somevalue}
    

Managing beacon sets

This section provides details on the API requests to manage beacon sets. See the previous section for beacon types and variables.

To add a beacon set to a Live job, first create the beacon set, and then include the id when you create the job, like this:

      {
        "live_stream": true,
        "region": "us-west-2",
        "reconnect_time": 30,
        "ad_insertion": true,
        "beacon_set": "beacon_set_id", ...
    

Create a beacon set

To create a beacon set, send a POST request:

Method POST
URL https://api.bcovlive.io/v1/ssai/beaconsets
Header X-API-KEY: your API KEY

Sample request body

      {
        "account_id": "User's Account ID [Optional]",
        "beacon_urls": [
        {
        "beacon_url":
        "https://myserver.com/beaconRX/{{job.job_id}}/load?position=load&sid={{session.session_id}}&jid={{job.job_id}}&app={{application_ad_configuration.description}}&rnd32={{random.int32}}&rnd64={{random.int64}}&bid={{random.uuid}}&t={{server.timestamputc}}&ua={{client.useragent}}&ip={{client.ipaddress}}&ref={{client.referrer}}&ref={{client.referer}}&ab={{live.adbreak}}&abd={{live.adbreakduration}}&abdi={{live.adbreakdurationint}}",
        "beacon_type": "Load"
        },
        {
        "beacon_url":
        "https://myserver.com/beaconRX/{{job.job_id}}/play?position=play&sid={{session.session_id}}&jid={{job.job_id}}&app={{application_ad_configuration.description}}&rnd32={{random.int32}}&rnd64={{random.int64}}&bid={{random.uuid}}&t={{server.timestamputc}}&ua={{client.useragent}}&ip={{client.ipaddress}}&ref={{client.referrer}}&ref={{client.referer}}&ab={{live.adbreak}}&abd={{live.adbreakduration}}&abdi={{live.adbreakdurationint}}",
        "beacon_type": "Play"
        }
        ]
        }
    

Sample response

      {
        "beacon_set": {
        "beacon_urls": [{
        "beacon_url":
        "https://myserver.com/beaconRX/{{job.job_id}}/load?position=load&sid={{session.session_id}}&jid={{job.job_id}}&app={{application_ad_configuration.description}}&rnd32={{random.int32}}&rnd64={{random.int64}}&bid={{random.uuid}}&t={{server.timestamputc}}&ua={{client.useragent}}&ip={{client.ipaddress}}&ref={{client.referrer}}&ref={{client.referer}}&ab={{live.adbreak}}&abd={{live.adbreakduration}}&abdi={{live.adbreakdurationint}}",
        "beacon_type": "Load"
        },
        {
        "beacon_url":
        "https://myserver.com/beaconRX/{{job.job_id}}/play?position=play&sid={{session.session_id}}&jid={{job.job_id}}&app={{application_ad_configuration.description}}&rnd32={{random.int32}}&rnd64={{random.int64}}&bid={{random.uuid}}&t={{server.timestamputc}}&ua={{client.useragent}}&ip={{client.ipaddress}}&ref={{client.referrer}}&ref={{client.referer}}&ab={{live.adbreak}}&abd={{live.adbreakduration}}&abdi={{live.adbreakdurationint}}",
        "beacon_type": "Play"
        }],
        "beacon_set_id": "Inserted Beacon Set ID",
        "account_id": "USER's ACCOUNT ID"
        }
        "inserted": true
        }
    

Update a beacon set

Updating a beacon set is similar to creating one. Submit a PUT request:

Method PUT
URL https://api.bcovlive.io/v1/ssai/beaconsets/beaconset/beacon_set_id
Header X-API-KEY: your API KEY

Sample request body

      {
        "account_id": "User's Account ID [Optional]",
        "beacon_urls": [
        {
        "beacon_url": "https://myserver.com/beaconRX/load",
        "beacon_type": "Load"
        },
        {
        "beacon_url": "https://myserver.com/beaconRX/play",
        "beacon_type": "Play"
        }
        ]
        }
    

Sample response

      {
        "beacon_set": {
        "account_id": "User's Account ID",
        "beacon_set_id": "Beacon set ID",
        "beacon_urls": [{
        "beacon_url": "https://myserver.com/beaconRX/load",
        "beacon_type": "Load"
        },
        {
        "beacon_url": "https://myserver.com/beaconRX/play",
        "beacon_type": "Play"
        }],
        "updated_beacon_set": {
        "beacon_set_id": "Beacon set ID",
        "beacon_urls": [{
        "beacon_url": "https://myserver.com/beaconRX/load",
        "beacon_type": "Load"
        },
        {
        "beacon_url": "https://myserver.com/beaconRX/play",
        "beacon_type": "Play"
        }],
        "account_id": "User's Account ID"
        }
        }
        }
    

Get beacon sets

To retrieve the beacon sets for an account, submit a GET request:

Method GET
URL https://api.bcovlive.io/v1/ssai/beaconsets/account/Account ID
Header X-API-KEY: your API KEY

Sample response

      [{
        "account_id": "User's Account ID",
        "beacon_set_id": "Beacon set ID1",
        "beacon_urls": [{
        "beacon_url": "https://myserver.com/beaconRX/load",
        "beacon_type": "Load"
        }]
        },
        {
        "account_id": "User's Account ID",
        "beacon_set_id": "Beacon set ID2",
        "beacon_urls": [{
        "beacon_url": "https://myserver.com/beaconRX2/load",
        "beacon_type": "Load"
        },
        {
        "beacon_url": "https://myserver.com/beaconRX2/play",
        "beacon_type": "Play"
        }]
        }]
    

Get beacon sets for requesting user

You can also get the beacon sets for the account of the requesting user without including the account id in the request URL:

Method GET
URL https://api.bcovlive.io/v1/ssai/beaconsets
Header X-API-KEY: your API KEY

Sample response

      [{
        "account_id": "User's Account ID",
        "beacon_set_id": "Beacon set ID1",
        "beacon_urls": [{
        "beacon_url": "https://myserver.com/beaconRX/load",
        "beacon_type": "Load"
        }]
        },
        {
        "account_id": "User's Account ID",
        "beacon_set_id": "Beacon set ID2",
        "beacon_urls": [{
        "beacon_url": "https://myserver.com/beaconRX2/load",
        "beacon_type": "Load"
        },
        {
        "beacon_url": "https://myserver.com/beaconRX2/play",
        "beacon_type": "Play"
        }]
        }]
    

Get a beacon set by id

To retrieve a single beacon set by its id, submit a GET request:

Method GET
URL https://api.bcovlive.io/v1/ssai/beaconsets/beaconset/beacon_set_id
Header X-API-KEY: your API KEY

Sample response

      {
        "account_id": "User account ID",
        "beacon_set_id": "Beacon set ID",
        "beacon_urls": [{
        "beacon_type": "Load",
        "beacon_url": "https://myserver.com/beaconRX2/load"
        },
        {
        "beacon_type": "Play",
        "beacon_url": "https://myserver.com/beaconRX2/play"
        }]
        }
    

Delete a beacon set

Finally, to delete a beacon set, send a DELETE request:

Method DELETE
URL https://api.bcovlive.io/v1/ssai/beaconsets/beaconset/beacon_set_id
Header X-API-KEY: your API KEY

Sample response

The response will look like this:

      {
        "beacon_set_id": "Beacon set ID",
        "deleted": true
        }
    

Appendix

Below is a screenshot to show a sample cue point setup for the Elemental encoder.

Elemental Cue Point Setup
Elemental Cue Point Setup