---
updatedAt: 2026-08-12T16:33:17.000Z
agentTools:
  projectIndex: https://docs.uplynk.com/llms.txt
---

# Baseline SCTE Plugin

Handle ad insertion, blackout and content start with the baseline SCTE plugin.

## Baseline SCTE Plugin

The baseline SCTE plugin provides SCTE signal processing functionality to the Live Slicer.

**Note: The`scte_baseline.py` file is included in the Live Slicer download package (within the `plugins`folder).**

To enable this functionality, add the following lines to your Live Slicer configuration file:

```toml
scte_type: python
scte_module: scte_baseline.py
```

```python
import slicer, time, syslog, os, traceback

'''Function calls should complete in under 250ms. Longer than that may result in dropped frames!'''

'''This function MUST be present and return slicer.initialize()'''
def Initialize():
    syslog.syslog(syslog.LOG_ALERT, "[upl-py] init: ")
    return slicer.Initialize()

STATE_INITIAL = -1
STATE_BLACKOUT = 0
STATE_SLICING = 1
STATE_AD = 2

state_desc = { \
    -1: "initial", \
    0: "blackout", \
    1: "slicing", \
    2: "ad" \
}

state = STATE_INITIAL
lastmod = 0

'''
splice_insert out_of_network indicator controls blackout.
time_signal segmentation_descriptor type 52 for ad starts, type 53 for ad ends.
'''
def Process35(slice_info):
    global state, lastmod, state_desc
    syslog.syslog(syslog.LOG_ALERT, "[upl-py] trigger: " + str(slice_info))

    try:
        initial = state

        #Reset ad state if we used an implicit ad end
        if state == STATE_AD and slicer.GetState() == 'slicing' and time.time() - lastmod > 30:
            state = STATE_SLICING

        if slicer.GetState() == 'start_blackout' and state == STATE_INITIAL:
            state = STATE_BLACKOUT #Initialize to blackout if the slicer started in blackout
        elif slicer.GetState() == 'slicing' and state == STATE_INITIAL:
            state = STATE_SLICING #Do this so later checks for going into ad break work

        if slice_info["splice_command_type"] == 5:
            if slice_info["command"]["out_of_network_indicator"] == 1 and state != STATE_BLACKOUT:
                slicer.Blackout(int(slice_info["pts_time"]))
                state = STATE_BLACKOUT
            elif slice_info["command"]["out_of_network_indicator"] == 0 and state != STATE_SLICING:
                slicer.ContentStart(int(slice_info["pts_time"]))
                state = STATE_SLICING
            #else Ignore state change, we are already in that state
        elif slice_info["splice_command_type"] == 6:
            if slice_info["descriptors"]:
                for descriptor in slice_info["descriptors"]:
                    if 'segmentation_type_id' in descriptor:
                        #Placement Opportunity Start
                        if descriptor["segmentation_type_id"] == 52 and state == STATE_SLICING:
                            if descriptor["segmentation_duration"] == 0:
                                slicer.AdStart(int(slice_info['pts_time']))
                            else:
                                slicer.AdStart(int(slice_info['pts_time']),int(descriptor["segmentation_duration"]*48000//90000))
                            state = STATE_AD
                        #Placement Opportunity End
                        elif descriptor["segmentation_type_id"] == 53 and state == STATE_AD:
                            slicer.AdEnd(int(slice_info['pts_time']))
                            state = STATE_SLICING
                        #Program Start
                        elif descriptor["segmentation_type_id"] == 0x10:
                            slicer.ContentStart(int(slice_info["pts_time"]))
                            state = STATE_SLICING

        if initial != state:
            syslog.syslog(syslog.LOG_ALERT, "[baseline plugin] State changed from %s -> %s"  % (state_desc[initial], state_desc[state]))
            lastmod = time.time()
    except Exception as e:
        for line in traceback.format_exc().split('\n'):
            print(line)
            syslog.syslog(syslog.LOG_ALERT, line)

    return int(0)

```

### Ad Insertion

Ad insertion is managed by `time_signals` with a segmentation descriptor having a `segmentation_type_id` of `0x34` (PLACEMENT\_OPPORTUNITY\_START). You can end an ad explicitly by sending a `time_signal` with a segmentation descriptor having a `segmentation_type_id` of `0x35` (PLACEMENT\_OPPORTUNITY\_END).

* If `segmentation_duration` is `0` when starting an ad, the ad break lasts until the next `content_start`, `blackout`, or explicit `PLACEMENT_OPPORTUNITY_END`.
* If `segmentation_duration` is set, the ad lasts for the specified duration and then returns automatically.
* You can always end an ad preemptively by sending a `PLACEMENT_OPPORTUNITY_END`.

### Blackout

The Baseline SCTE plugin triggers blackout based on the `splice_insert`'s `out_of_network_indicator` field.

To achieve the desired blackout effect, set the `out_of_network_indicator` field to:

* `1`: Enter blackout.
* `2`: Leave blackout.

### Content Start

In addition to a `splice_insert` with `out_of_network_indicator` set to `0`, you can start a new program by sending a `time_signal` with a segmentation descriptor where `segmentation_type_id` is set to `0x10` (PROGRAM\_START).

### Sample SCTE Message Payload

The following example shows an SCTE payload message. In this case, a type 6 (Time Signal), type 16 (Content Start) is being passed:

```python
{'base64': b'/DAzAAAAAAAA///wBQb/+SORKAAdAhtDVUVJAAAAAH+/AQwxMjI4NzYzMjU0NzIQAQCmbExp', 'splice_command_type': 6, 'pts_adjustment': 0, 'pts_time': 206229733, 'command': {}, 'descriptors': [{'segmentation_event_id': 0, 'segmentation_event_cancel_indicator': 0, 'delivery_not_restricted_flag': 1, 'segmentation_duration': 0, 'segmentation_upid_type': 1, 'segmentation_upid_length': 12, 'segmentation_upid': b'122876325472', 'segmentation_type_id': 16, 'segment_num': 1, 'segments_expected': 0, 'identifier': 1129661769, 'descriptor_length': 27, 'splice_descriptor_tag': 2}]}
```