Ad Markers
CUE-OUT/IN
For LL-HLS/HLS
You can dynamically insert Ad Markers into LL-HLS and HLS playlists using the REST API.
When requesting the CUE-OUT event, the following tags will be added to the playlist:
#EXT-X-CUE-OUT:DURATION=<time>
…
#EXT-X-CUE-IN
| Element | Description |
|---|---|
#EXT-X-CUE-OUT,#EXT-X-CUE-IN | #EXT-X-CUE-OUT and #EXT-X-CUE-IN are a pair, and the entire section between the two tags will be replaced with ad content by the ad server |
DURATION=<time> | DURATION=<time> is required and represents the duration of the ad. |
You can request the CUE-IN event to end an inserted ad early. When the event is called, the #EXT-X-CUE-IN tag is immediately added to the playlist, and the previously added #EXT-X-CUE-IN tag is removed.
API Interface
Request
POST /v1/vhosts{vhost}/apps/{app}/streams/{stream}:sendEvent
Header
Authorization: Basic {credentials}
# Authorization
Credentials for HTTP Basic Authentication created with <AccessToken>
Body
{
"eventFormat": "cue",
"events":[
{
"cueType": "out", // out | in
"duration": 60500 // milliseconds, only available when cueType is out
}
]
}
POST /v1/vhosts{vhost}/apps/{app}/streams/{stream}:sendEvents
Header
Authorization: Basic {credentials}
# Authorization
Credentials for HTTP Basic Authentication created with <AccessToken>
Body
[
{
"eventFormat": "id3v2",
"eventType": "video", // "eventTarget": "video" is same
"events":[
{
"frameType": "TXXX",
"info": "AirenSoft",
"data": "OvenMediaEngine"
},
{
"frameType": "TIT2",
"data": "OvenMediaEngine 123"
}
]
},
{
"eventFormat": "cue",
"events":[
{
"cueType": "out", // out | in
"duration": 60500 // milliseconds, only available when cueType is out
}
]
}
]
Responses
200 Ok
The request has succeeded
Header
Content-Type: application/json
Body
{
"message": "OK",
"statusCode": 200
}
400 Bad Request
Invalid request. Body is not a Json Object or does not have a required value
401 Unauthorized
Authentication required
Header
WWW-Authenticate: Basic realm=”OvenMediaEngine”
Body
{
"message": "[HTTP] Authorization header is required to call API (401)",
"statusCode": 401
}
404 Not Found
The given vhost name or application name could not be found.
Body
{
"message": "[HTTP] Could not find the application: [default/app2] (404)",
"statusCode": 404
}
SCTE-35 Event Insertion
For LL-HLS/HLS
Using the REST API, you can insert ad markers into LL-HLS and HLS playlists as #EXT-X-DATERANGE tags. #EXT-X-DATERANGE specifies ad timing via the SCTE-35 OUT/IN attributes.
For SRT Push
Starting with OvenMediaEngine Enterprise 0.20.0.0-1, you can insert SCTE-35 events (splice_insert()) not only into LL-HLS and HLS playlists, but also into SRT Push. When you send ad start/end signals (OUT/IN) or other custom events to OvenMediaEngine Enterprise via the sendEvents API, the information is inserted into the SRT Push and propagated to other systems.
Behavior Rule
- When an
OUTevent is received, anINis automatically scheduled after the specifiedduration(ms) elapses. - If an
INis inserted before the duration expires, the previously auto-insertedINis removed.
Some downstream devices may fail to detect a return from ad break. We recommend sending an IN event after an OUT event.
API Interface
Request
POST /v1/vhosts{vhost}/apps/{app}/streams/{stream}:sendEvent
Header
Authorization: Basic {credentials}
# Authorization
Credentials for HTTP Basic Authentication created with <AccessToken>
Body
{
"eventFormat": "scte35",
"events":[
{
"id": {{randomId}}, // required, 32bits unsigned number, auto filled if not present
"type": "out", // required, out | in
"duration": 10000 // milliseconds, only available when cueType is out
}
]
}
POST /v1/vhosts{vhost}/apps/{app}/streams/{stream}:sendEvents
Header
Authorization: Basic {credentials}
# Authorization
Credentials for HTTP Basic Authentication created with <AccessToken>
Body
[
{
"eventFormat": "scte35",
"events":[
{
"spliceCommand": "spliceInsert",
"id": {{randomId}}, // required, 32bits unsigned number, auto filled if not present
"type": "out", // required, out | in
"duration": 30000 // milliseconds, only available when cueType is out
}
]
}
]
You enter duration in milliseconds (ms), but it is emitted to the playlist as PLANNED-DURATION in seconds (s).
Responses
200 Ok
The request has succeeded
Header
Content-Type: application/json
Body
{
"message": "OK",
"statusCode": 200
}
400 Bad Request
Invalid request. Body is not a JSON object or does not have a required value
401 Unauthorized
Authentication required
Header
WWW-Authenticate: Basic realm=”OvenMediaEngine”
Body
{
"message": "[HTTP] Authorization header is required to call API (401)",
"statusCode": 401
}
404 Not Found
The given vhost name or application name could not be found.
Body
{
"message": "[HTTP] Could not find the application: [default/app2] (404)",
"statusCode": 404
}
Example: Successful Event Insertion
For LL-HLS/HLS
Below is an LL-HLS playlist sample after injecting an SCTE-35 event:
#EXT-X-DATERANGE:ID="123",START-DATE="2025-01-01T09:15:00+00:00",PLANNED-DURATION=10.0,SCTE35-OUT=0xF...
...
#EXT-X-DATERANGE:ID="123",START-DATE="2025-01-01T09:15:00+00:00",SCTE35-IN=0xF
| Element | Description |
|---|---|
SCTE35-OUT | SCTE-35 payload indicating the start of the ad break (content → ad). |
SCTE35-IN | SCTE-35 payload indicating the end of the ad break (ad → content). |
PLANNED-DURATION | Ad break duration in seconds. When used with OUT, an IN is auto-inserted after this time. |
ID | An identifier that ties the OUT/IN to the same break. * 32-bit unsigned integer. |
START-DATE | Ad start timestamp (ISO-8601). * yyyy-mm-ddThh:mm:ss±UTC |
For SRT Push
If the OvenMediaEngine Enterprise log shows output similar to the example below, the SCTE-35 event was delivered successfully.
[11-03 21:29:02.028] D [SW-Push:2415407] FFmpegWriter | writer.cpp:523 | SCTE-35 Event: SpliceCommandType=5, ID=2025, OutOfNetwork=true, Timestamp=372370 ms, Duration=30000 ms, AutoReturn=false