Understanding SCTE-35


SCTE-35 is a standard to signal an advertisement (ad) insertion opportunity in a transport stream. This relatively short standard document is, however, difficult to understand without the insight of ad insertion workflow. This article explains the standard text with some background and context information.

Most TV programs make money by selling ad time slots to the advertisers. For example, 30 second ad time slot of Super Bowl 2014 was sold for $4 million.

Ads are not hard coded into the TV program. Instead, the broadcasters insert the ad to the time slot on the fly. This allows broadcasters to change ad based on the air time, geographic location, or even personal preference. All we need is a special marker in the broadcast stream to signal the ad time slots.

Network program and advertisement.

Analog broadcasting used a special audio tone called DTMF to signal the ad time slot. In digital broadcasting, we use SCTE-35.

SCTE-35 packets are multiplexed with video and audio packets in the transport stream. The syntax of the payload is called splice_info_section(). The syntax signals one of six commands. The most important command is splice_insert() and I explain it first.

Splice Insert Command


splice_insert signals a splice event. When out_of_network_indicator is 1, it signals switching from the network program to an advertisement. When out_of_network_indicator is 0, it signals switching back to the network program. Although not formally defined in the standard, these events are often called cue-out event and cue-in event respectively.


The timing of the splice event is specified in terms of PTS. It uses two fields; pts_adjustment field in splice_info_section() syntax and pts_time field in splice_insert() syntax. The splice event PTS is calculated as (pts\_time + pts\_adjustment) \mod{M} where M is PTS rollover modulo: 2^{33}. In practice, pts_time field often carries relative PTS from the network program start. When broadcasting the program, the edge multiplexer sets the current PTS offset in pts_adjustment so that the resultant event PTS is aligned with the broadcast time base.

Many ad time slots have a fixed duration such as 15, 30, and 45 seconds. Instead of explicitly signaling cue-in event, you can use break_duration() syntax to specify duration of the time slot in the cue-out event. When auto_return field is 0, the signaled duration is interpreted as “informative” and you still have to signal cue-in event. When auto_return field is 1, the devices terminates the break after the specified duration without a cue-in event. Note that you can always overwrite the break duration by signaling cue-in event explicitly.

It is also possible to signal a splice event without specifying the time. When splice_immediate_flag is 1, a splice event is triggered at the earliest possible timing. This, however, causes various headaches in practice. For example, when you have redundant systems to produce same broadcast streams, “Immediate” might result in slightly different timing on each system due to the command delivery latency. SCTE-35 recommends to use splice_immediate_flag = 1 only for early termination of ad breaks.

Splice Schedule Command

Another command to explain is splice_schedule(). It has similar syntax and semantic as splice_insert() but it uses wallclock time instead of PTS. This allows to schedule the ad breaks far before the actual event based on the broadcast schedule and wall clock time. On the other hand, wallclock time has only second precision and not suitable for frame accurate splicing.

It is worth noting that the wallclock time uses so called GPS time. For engineers who are familiar with C/C++ time function such as time(), GPS time is different in two important ways.

  1. The epoch is 1980/01/06T00:00:00Z instead of 1970/01/01T00:00:00Z.
  2. Leap seconds are counted instead of skipped. As of today, there are 16 leap seconds since 1980/01/06. Therefore, GPS time looks 16 seconds ahead of the wall clock time we are familiar with.


The leap second problem can be hard in some use cases. Since leap second is unpredictable, we need to look up the latest leap second information published by IERS. A correct way is to read GPS_UTC_offset value encoded in PSIP metadata carried in ATSC stream. However, not every system has access to the information. SCTE-35 allows implementation to ignore the leap second but it results in about 16 second error.

Splice Event Repetition and Cancellation

Both splice_insert and splice_schedule commands are issued with a unique identifier of each splice event. The identifier is 32 bit integer and usually incremented for each event.


You might wonder how to ensure the uniqueness of splice_event_id for long running 24/7 live event. It is 32 bits integer. Even if we have splice event for every second, we won’t running out of the number for 2^{32} / 60 / 60 / 24 / 365 = 136 years. We are good.

One use case of splice_event_id is redundant repetition. As transport stream packets are often delivered over unreliable network, it is recommended to send splice_insert command multiple times with a same splice_event_id before the actual event. Another use case is a cancellation. You can cancel an event by specifying the splice_event_id and set splice_event_cancel_indicator to 1. You can also override an event by inserting a new one after cancellation. To prevent a race condition, it is required to finalize the splice_event 4 second before the actual event.


SCTE-35 was originally designed for ad insertion. However, it turned out to be also useful for more general segmentation signaling.

Consider a movie program. The program may have one or more “chapters” as you see on DVD. Some parts of the program are reserved for provider ads such as announcement of TV drama to broadcast tonight. Within that time slot, some parts may be reserved for the local ads.

Depending on the distribution method (TV, Web, DVR recording, etc), the provider may want to make only the selected part of the program available for legal reasons.

Also, each segment may have associated identifier such as TMS ID, AD-ID, and ATSC content identifier. These identifiers are collectively called UPID (Unique Program Identifier) and would be useful for content management purpose.


Such hierarchical structure cannot be signaled by splice_insert syntax. Also, splice_insert is not sufficient to carry various metadata such as restrictions and UPID. The SCTE-35 segmentation descriptor addresses the problem.

Segmentation is signaled by a combination of time_signal command and segmentaiton_descriptor. The time_signal command simply signals a timestamp of the segmentation.


The complex matter is all taken care by segment descriptor.


The red part describes various restrictions based on the delivery method. For example, you can make the segment not available for Web delivery.

The blue part carries UPID which identifies the content of the segment. For example, you can identify a segment to be “Gone with the wind” by looking up UPID (ISAN number) encoded in the SCTE-35 message.

The structure of segmentation is similar to splice event except one important difference. In splice event, splice_event_id identifies each splice event, i.e. cue-out and cue-in have different splice_event_id. On the other hand, segmentation_event_identifier identifies one entire segment. This allows segments to be nested and make hierarchical structure.


SCTE-35 on over the top delivery

SCTE-35 is specific to a transport stream which is mainly used for traditional broadcasting context. As Web based video delivery becomes popular, many companies try to make something similar to SCTE-35 for Web delivery. For example, one attempt can be seen in a proprietary extension to HLS media playlist m3u8 format for ad insertion.

Although it is difficult to predict the future, I think all these proprietary ad marker technologies are to be faded out and the industry trends is moving in favor of using SCTE-35 as the ad marker data model. For example, a company uses XML representation of SCTE-35 as Web video ad marker. Another company uses base-64 encoded SCTE-35 splice_info_section syntax as an adaptive bit rate streaming ad marker. This is because they don’t want to lose any information of SCTE-35, which is matured and well supported by various devices, on the way from the content management system to cable network to Web delivery.


About Moto

Engineer who likes coding
This entry was posted in Video and tagged , , . Bookmark the permalink.

12 Responses to Understanding SCTE-35

  1. abc28890 says:

    Is this information accessible to end user ?

    • Gary Hughes says:

      All SCTE standards can be freely downloaded from http://www.scte.org/standards/Standards_Available.aspx

      Typically only the latest versions are available from the web site and since the revision year is embedded in the file name, links to specific documents can go stale.
      I recommend that you also download SCTE 67 which is guidelines for the use of SCTE 35. This was recently revised to add sections on the use of SCTE 35 with DASH, HLS etc.

  2. Mayeul says:

    Hi Moto,

    Thank you for this very useful post, it clarifies a lot the spec. However one points remains totally unclear for me: the correlation between the splice_events and the segments.

    I understand how a splice_insert command inserts a splice_event and how a set of time_signal commands specifies a segment. But what is the correlation between a the splice_events and the segments? I guess that each segment is delimited by two splice_events but I cannot figure out how this is achieved because, according to the spec, the splice_events and segments seems totally uncorrelated. For instance, how is the beginning of a chapter linked to a splice_event defined by a splice_insert command since time_signal does not contain a field “splice_event_id” to do the connection?
    What is the difference between a segment defined by a splice_insert command and one defined by a time_signal command? Finally what is the purpose of this bloody time_signal command? Why not using splice_insert instead?

    I would be infinitely grateful if you could clarify those points for me =)
    Thanks for your attention.

    • Gary Hughes says:

      You can carry segmentation descriptors in either splice_insert or time_signal commands. They have the same meaning. Time_signal allows you to link an event (e.g. chapter start) to the media timeline without necessarily commanding a splicer to insert or replace an ad (some splicer implementations are that dumb).

      Consider a program start for example. Many networks like to run programs back to back, so a program start is not a valid ad insert point, but being able to signal program start is very useful for network PVR, so you would carry that descriptor in a time_signal command.

  3. Michel says:

    Thank you for this interesting post.

    Would you know where I can find recordings of video streams containing SCTE-35 messages?

  4. Pingback: Azure Media Services のライブ エンコード機能の概要 - Microsoft Azure Japan Team Blog (ブログ) - Site Home - MSDN Blogs

  5. Pingback: Microsoft Azure Media Services 即時編碼 (Live Encoding) 簡介 - Microsoft Azure 中文部落格 - Site Home - TechNet Blogs

  6. Pingback: 使用 Azure 媒体服务进行实时编码简介 - 微软云计算: Windows Azure 中文博客 - Site Home - MSDN Blogs

  7. amit says:

    I am researching on this project and can someone please share with me a sample TS stream containing SCTE-35 cue .My email is amit.shivnani@gmail.com .

    Thanks in Advance .

  8. Biswa says:

    Iam looking for couple of things regarding SCTE35
    1. SCTE35 inserted mpeg2 ts content, will appreciate if someone can post with a link for sample content. This will help perform compliance test on my code.
    2. Also are there any SCTE35 supported player/analysers which show messages with timestamp available freely?.

    Thanks in advance

  9. Nagarajan G says:

    Hi Amit,
    If you got any streams with scte35 info (splice_insert and time_signal) please share with me.
    mail_id: nagarajan.guna@yahoo.com

    Thanks in Advance

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s