SCTE-35 Injector

December 3, 2025 · 3 minute read

Why I built scte35-injector

If you’re working with video streams, especially MPEG-TS (transport streams), you may have heard of SCTE-35. It’s a widely used standard to embed cue-messages in video streams, indicating where to splice in content commonly for ad breaks, program boundaries, blackouts, or regional content insertion.

Lately I spent a lot of time with SCTE-35 and SCTE-250, with event handling and program control flow in live streams. There is a constant need for test assets, and I needed ways to fabricate them. While there are existing SCTE-35 tools and libraries to parse or manipulate these cues like threefive, tsp or SuperKabuki, I found myself needing a simpler command-line tool to inspect or inject SCTE-35 cues in MPEG-TS files without depending on heavy tools or libs. Thus, scte35-injector was born: a lightweight CLI tool written in Rust for exactly that.

In short: I wanted a “TSDuck-style” utility but focused specifically on SCTE-35, easy to use, and reliable.

What scte35-injector does

scte35-injector is a command-line tool that can:

  • List existing SCTE-35 cues in a given MPEG-TS file (by detecting cues in PSI or PES tables).
  • Inject new cues*: insert new base64-encoded splice_info_section messages at specified timestamps. You can control where (on the TS timeline) to insert packets, and optionally rewrite the internal splice_time inside the cue.
  • Auto-add an SCTE-35 PID if none exists: the tool will allocate a free PID ≥ 0x30, rewrite the PMT accordingly (with CRC, correct descriptor), and update continuity counters as needed.
  • Work incrementally: it processes TS packets as a stream. No full-file buffering, so even large transport-streams can be handled efficiently.
  • Run tests: the repo includes unit, edge and end-to-end tests, as well as sample fixture files under test-assets/, to ensure correct behavior.

It’s cross-platform, and doesn’t require FFmpeg or other heavy multimedia dependencies. That was a conscious design decision to keep it minimal and robust.

Tradeoffs & Limitations

  • The tool is offline only: designed for file-based TS processing. It’s not a live-streaming inserter (so no real-time ad-insertion out of the box).
  • No bitrate shaping / null-packet padding: injecting packets may change stream bitrate. If you need strict bit-rate constraints, external padding may be required.
  • No built-in support for multi-program TS. For streams with multiple programs or services, scte35-injector may not (yet) be suitable.

These tradeoffs are part of the design: I wanted something simple, predictable, and maintainable rather than a full-featured streaming solution.

How to Use It

scte35-injector --input input.ts \
  --output output.ts \
  --cue "00:00:25.000@00:00:30.000=/DAWAAAAAAAAAP/wBQb+Qjo1vQAAuwxz9A=="

This command will: at 25 seconds (on the TS timeline), insert SCTE-35 packets, rewriting the internal splice_time to 30 seconds (so downstream players/readers see the cue as “splice at 00:00:30”).

If you only want to list cues in a file:

scte35-injector --input input.ts --list-cues

It will print out existing cues (if any) with their PTS and base64 payloads.