SCTE-35 Explained: Splice Messages and How to Verify Them
SCTE 35 is the in-stream signaling standard that tells downstream equipment where an ad break, a program or a blackout starts and ends. This guide covers how the cues are carried and built, splice_insert versus time_signal, segmentation descriptors and UPIDs, PTS timing and pre-roll, and how to verify cues in a live stream. Field names and rules below follow ANSI/SCTE 35-1 2023r2, the current edition.
What is SCTE 35?
SCTE 35, “Digital Program Insertion Cueing Message”, is published by SCTE. The standard describes itself as “the core signaling standard for advertising, Program and distribution control (e.g., blackouts) of content for content providers and content distributors”. In the 2023r2 edition it was renumbered SCTE 35-1, “Part 1: Legacy Splice-Based and Time-Based Signaling”, to set it apart from the new SCTE 35-2, “Part 2: Event-Based Signaling”, which adds an EventDescriptor to the time_signal command.
The standard supports frame accurate and non-frame accurate events in MPEG-2 transport streams, MPEG-DASH and HLS.
How SCTE 35 is carried in a transport stream
- Registration descriptor. Each program that complies with the standard carries a registration descriptor (tag 0x05) in the program_info loop of its PMT, with the format identifier 0x43554549, ASCII “CUEI”.
- Stream type 0x86. SCTE 35 sections travel on one or more PIDs of that program, listed in the PMT with stream_type 0x86. A cue PID only describes splice events of its own program.
- Cue identifier descriptor. An optional cue_identifier_descriptor (tag 0x8A) in the elementary stream loop labels what the PID carries through cue_stream_type: 0x00 splice_insert, splice_null and splice_schedule only; 0x01 all commands (the default when the descriptor is absent); 0x02 segmentation; 0x03 tiered splicing; 0x04 tiered segmentation.
- Packetization. Only one section, or part of a section, may be in a transport packet, and a splice_info_section always starts at the beginning of a packet payload, with pointer_field 0x00 and payload_unit_start_indicator set to 1.
The splice_info_section
Every SCTE 35 message is a splice_info_section, an MPEG short section with table_id 0xFC. Its main fields:
- section_syntax_indicator 0 and private_indicator 0; section_length may not exceed 4093.
- sap_type (2 bits): the Stream Access Point type at the signaled point, if the content preparation system created one; 0x3 means not specified.
- protocol_version: currently the only valid value is 0.
- pts_adjustment (33 bits): an offset added to every pts_time in the message (see the timing section below).
- tier (12 bits): authorization tier; 0xFFF is ignored by downstream equipment.
- splice_command_length, splice_command_type and the command itself.
- descriptor_loop_length followed by splice descriptors, then CRC_32 over the whole section.
| splice_command_type | Command | Purpose |
|---|---|---|
| 0x00 | splice_null | Carries descriptors without a command; can serve as a heartbeat for cue injection and link integrity. |
| 0x04 | splice_schedule | Conveys a schedule of splice events in advance. |
| 0x05 | splice_insert | Signals an upcoming splice event (an Out Point or In Point). |
| 0x06 | time_signal | Associates a pts_time with descriptors, usually segmentation descriptors. |
| 0x07 | bandwidth_reservation | Reserves bandwidth for the cue PID in a multiplex. |
| 0xFF | private_command | User-defined command, identified by a registered 32-bit identifier. |
splice_insert vs time_signal
splice_insert is the legacy command with a large installed base. It carries a 32-bit splice_event_id and a splice_event_cancel_indicator, and, when not cancelled:
- out_of_network_indicator: 1 for an opportunity to leave the network feed (an Out Point), 0 for a return (an In Point);
- program_splice_flag: 1 to splice all components of the program. Component Splice Mode (flag 0) is deprecated;
- splice_immediate_flag: 1 means no splice_time; the splicer picks the nearest opportunity;
- break_duration(), when duration_flag is 1: a 33-bit duration in 90 kHz ticks and an auto_return flag. With auto_return set, the splicer returns to the network when the duration ends, without needing an In Point message;
- unique_program_id, avail_num and avails_expected to identify the avail within a viewing event.
The standard recommends that an Out Point splice_insert include a break_duration, and recommends Auto Return Mode to support dynamic avail durations.
time_signal carries only a splice_time(). The meaning comes from the descriptors in the same section. When time_signal is used to signal splice events, it must carry one or more segmentation descriptors. The standard positions time_signal as the mechanism for new applications where there is control over the installed equipment, and warns that because of its descriptors a time_signal can exceed one transport packet, which some legacy equipment may not accept.
Segmentation descriptors and UPIDs
The segmentation_descriptor (splice_descriptor_tag 0x02, identifier “CUEI”) describes a segment of content. It may be used with time_signal, splice_insert and splice_null. Its key fields:
- segmentation_event_id and a cancel indicator;
- delivery restrictions, when delivery_not_restricted_flag is 0: web_delivery_allowed_flag, no_regional_blackout_flag, archive_allowed_flag and device_restrictions;
- segmentation_duration: 40 bits in 90 kHz ticks, 0 for end messages;
- segmentation_upid_type, segmentation_upid_length and the UPID itself;
- segmentation_type_id, with segment_num and segments_expected (and sub-segment fields for some types).
Frequently used segmentation_type_id values:
| Value | Segmentation message |
|---|---|
| 0x10 / 0x11 | Program Start / Program End |
| 0x22 / 0x23 | Break Start / Break End |
| 0x30 / 0x31 | Provider Advertisement Start / End |
| 0x32 / 0x33 | Distributor Advertisement Start / End |
| 0x34 / 0x35 | Provider Placement Opportunity Start / End |
| 0x36 / 0x37 | Distributor Placement Opportunity Start / End |
| 0x40 / 0x41 | Unscheduled Event Start / End |
The UPID (unique program identifier) names the content. Common types include 0x03 Ad-ID (12 bytes), 0x06 ISAN (12 bytes), 0x08 AiringID (8 bytes), 0x0A EIDR (12 bytes), 0x0C MPU (managed private UPID), 0x0D MID (several UPIDs in one descriptor), 0x0F URI and 0x10 UUID (16 bytes). Types 0x01, 0x02 and 0x05 are deprecated. For segmentation_type_id 0x01 (Content Identification), the UPID type must be non-zero.
Other descriptors defined by the standard are avail_descriptor (0x00), DTMF_descriptor (0x01), time_descriptor (0x03) and audio_descriptor (0x04). Tags 0xF0 to 0xFF are reserved for DVB use as specified in ETSI TS 103 752-1.
PTS timing and pre-roll
pts_time is a 33-bit value in ticks of the program’s 90 kHz clock. The splice time is pts_time plus pts_adjustment, ignoring any carry on wrap. The Splice Point is the first PES packet with a PTS greater than or equal to that adjusted time. An Out Point lies before the first presentation unit at or after that time; an In Point is that first presentation unit.
pts_adjustment exists because devices downstream may restamp PCR, PTS and DTS. The cue creator normally sets it to 0. The first restamping device that passes the cue inserts the delta between its input and output time domains, later restamping devices add their own delta, and every device that changes the field must recalculate CRC_32.
Pre-roll. A cue can be repeated before the Splice Point; the standard gives sending it at 8, 5, 4 and 2 seconds before as an example, and warns that a message received with less than 4 seconds of notice may not create the desired result. For splice_insert, at least one message for a network Out Point shall arrive at least 4 seconds before the signaled splice time. A time_signal or splice_insert carrying a segmentation descriptor should be sent at least once a minimum of 4 seconds in advance. Splice Immediate Mode is allowed for an Out Point, but the actual splice time is then undefined, and the standard recommends using it only for the early termination of breaks.
Event ids. Only one occurrence of an event id may be active at a time. The top 4 bits of the 32-bit id identify the source: 0 for cues in the original source material, 4 for automation, 6 for manual triggers and 12 for local content replacement.
SCTE 35 outside the transport stream
For HLS, SCTE 35-1 recommends EXT-X-DATERANGE as defined for HLS timed metadata, and specifies the legacy EXT-X-SCTE35 tag as an alternative; both may appear in one playlist. Carriage in MPEG-DASH is defined in SCTE 214-1. In SDI facilities, SCTE 104 defines the interface between an automation system and the compression system that inserts the SCTE 35 sections; SMPTE 2010 maps SCTE 104 messages into the vertical ancillary data. See also the OTT stream monitoring guide.
Common SCTE 35 errors and how to check them
- Cue PID not signaled. Check for the “CUEI” registration descriptor in the PMT program_info loop and stream_type 0x86 on the cue PID.
- Too little pre-roll. Compare the arrival time of each Out Point cue with its adjusted pts_time; less than 4 seconds breaks the splice_insert rule.
- Wrong pts_adjustment. After a restamping device, the adjusted splice time must still point at the intended picture; a CRC_32 error after such a device suggests the field was changed without recalculating the CRC.
- Splice Point not on a suitable picture. SCTE 35 refers to SCTE 172 for coding constraints at Splice Points; check which picture the adjusted time actually lands on.
- Breaks that do not end. An Out Point without break_duration, or with auto_return 0, depends on a later In Point message; if that message is lost, the splicer has no return time.
- Event id reuse. An event id used for a new event while the earlier event with that id is still active.
- time_signal without a segmentation descriptor, or with a Content Identification type and a zero UPID type.
Verifying SCTE 35 with DVBAnalyzer, DVBMonitor and DVBMosaic
DVBAnalyzer lists every broadcast SCTE-35 event in its SCTE-35 Viewer, and the events can be exported to Text, XML or Excel format. The events are also listed in the SI/PSI bar tree, and the Hex Viewer interprets an SCTE-35 section bit by bit. The Timing Viewer draws SCTE-35 cues as markers on its timing chart: SPLICE OUT and SPLICE IN for splice_insert, TIME SIGNAL for time_signal. Each marker sits at the moment the cue takes effect, with a connector back to where it was announced, so the pre-roll is visible as a length. Hovering a marker shows the command, direction, event id, pts_time, duration and auto-return, and which picture the splice lands on: green for an I-frame, amber for anything else, with the drift from the nearest picture when the splice time is not exactly on one. On SDI input, SCTE-104 messages in the ancillary data are converted to SCTE-35 on their own PID and read in the SCTE-35 Viewer like any other splice signaling.
For continuous supervision, DVBMonitor includes SCTE-35 monitoring and logging alongside ETR 290, table change, video quality and loudness checks, with alarms by SNMP and mail. DVBMosaic, the multiviewer, includes monitoring of SCTE-35 events.
Related guides: ETSI TR 101 290 (ETR 290) explained and loudness measurement.
Frequently asked questions
What is the difference between splice_insert and time_signal?
splice_insert (0x05) is a self-contained Out Point or In Point command with its own event id, break duration and auto-return. time_signal (0x06) only carries a time; its meaning comes from the segmentation descriptors in the same message.
What is the difference between SCTE 35 and SCTE 104?
SCTE 35 is the cue message in the compressed stream (transport stream, HLS, DASH). SCTE 104 is the interface between an automation system and the compression system that inserts those SCTE 35 messages, and in SDI it is carried in the ancillary data.
How far in advance must an SCTE 35 cue be sent?
For splice_insert, at least one message for a network Out Point must arrive at least 4 seconds before the signaled splice time. Cues with segmentation descriptors should also be sent at least once 4 seconds ahead.
Which PID carries SCTE 35?
There is no fixed PID. The cue PID is listed in the program’s PMT with stream_type 0x86, and the program carries a registration descriptor with the identifier “CUEI”.