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: Thescte_baseline.py file is included in the Live Slicer download package (within the pluginsfolder).

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

scte_type: python
scte_module: scte_baseline.py
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:

{'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}]}

Did this page help you?