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.pyimport 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_durationis0when starting an ad, the ad break lasts until the nextcontent_start,blackout, or explicitPLACEMENT_OPPORTUNITY_END. - If
segmentation_durationis 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}]}Updated about 2 hours ago