Live API: Cue Points and Ad Beacons with SSAI
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: "YWJjZGVmZ2g=", // 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:
- Only
avail_in
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 using the Live API by sending a POST
request:
Method | POST |
---|---|
URL | https://api.bcovlive.io/v1/jobs/Job_ID/cuepoint |
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. |
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
- Software encoders such as Wirecast and OBS do not support the sending timecode via
OnFI
packets in the RTMP stream - 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 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.
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. The following table summarizes the 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.
|
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.