A validator answers one question guessing cannot: is the signalling in this stream actually well formed. Presence, pairing and payload — three checks, in that order, each one cheaper than the outage it prevents. Here is what a real report contains and how to read one.
Are there any cue tags in the media playlist at all? This one check resolves more support tickets than the other two combined, because the usual answer is no.
Does every CUE-OUT have a CUE-IN, and does the elapsed segment time between them match the declared break duration? Structural, cheap, and where real faults show.
Does the base64 or hex splice_info_section parse into a well-formed message whose command, event id and timing agree with the tags wrapped around it?
Most tools stop at the first check and call it validation. That is a grep, and the difference is worth being honest about: a playlist can contain perfectly formed CUE-OUT tags and still be unusable, because the durations do not add up or because the binary payload says something different from the attribute sitting next to it.
Ours prints counts first, then the pairing, then any decode results, then a single verdict. The counts matter as much as the verdict: a stream with four cue-outs when you scheduled five has a specific, findable problem, and a pass/fail line alone hides it.
========================================================
SCTE-35 Validation Report
========================================================
Playlist : index_marked.m3u8
#EXT-X-CUE-OUT : 4
#EXT-X-CUE-IN : 4
#EXT-X-DATERANGE: 4
expected breaks : 4
--------------------------------------------------------
break 1 out 00:04:12.000 in 00:04:42.000 30.0 s paired
break 2 out 00:11:48.000 in 00:12:18.000 30.0 s paired
break 3 out 00:19:06.000 in 00:19:36.000 30.0 s paired
break 4 out 00:27:30.000 in 00:28:00.000 30.0 s paired
--------------------------------------------------------
PASS - 4/4 breaks paired, durations consistent| Finding | What it means | What it breaks downstream |
|---|---|---|
| CUE-OUT with no CUE-IN | The break opens and never closes in the playlist | An insertion system without a duration timeout can leave viewers stranded in an ad state. |
| Count below the schedule | Fewer cues arrived than were sent | Inventory you sold does not exist. The break simply never happens, silently. |
| Duration disagrees with elapsed time | The declared break length does not match the segments between the tags | Return-to-programme lands early or late, usually cutting the last few seconds of a spot. |
| Payload will not decode | The base64 or hex section is truncated or malformed | Anything reading the binary rather than the attribute sees nothing. Chains differ in which they trust. |
| Tag says one thing, payload another | The attribute duration and the decoded break_duration differ | Two systems in the same chain take different decisions from the same cue. Very hard to debug without a decode. |
| Duplicate event ids | The same break signalled twice by two hops | Double insertion, or a second break opening inside the first, depending on the splicer. |
| Cues only in the master playlist | Tags placed where no player looks for them | Nothing acts on them. Cues belong in the media playlist. |
The reason to make this a script rather than an inspection is that a live channel gives you no second chance. A break that fails at 20:00 on a match night is revenue that does not come back, and the postmortem happens against a playlist that has already rolled off the window.
A validator with a clean exit code drops into CI, into a pre-flight check before a scheduled event, and into a cron job against your live URL. That last placement is the highest-value one and almost nobody does it: run the same three checks against production every few minutes and you find out that your packager stopped emitting cues on the day it happens, not in next month's revenue report.
The checks themselves are not proprietary — they follow from the public SCTE-35 and HLS specifications, which is exactly why we are comfortable describing all of them here.
We built this tooling because our own pipeline needed it, and running it against one more playlist costs us nothing. Send a live or VOD media playlist URL and you get back what cues are present, in which form, whether they pair, and whether the payloads decode — as a plain report, with no obligation and no account to create.
If the answer turns out to be that your stream carries no usable cues at all, that is worth knowing too, and it is not the end of the road. SCTE-35 ad insertion explains why schedule-driven insertion is a perfectly legitimate way to start monetising while the signalling chain gets fixed, and the marking and detection page covers writing cues into a stream that has none.
Three things, in increasing order of difficulty. First, presence: are there any cue tags in the playlist at all. Second, structure: does every CUE-OUT have a matching CUE-IN, and do the durations account for the time between them. Third, payload: does the base64 or hex splice_info_section decode into a well-formed message whose splice command and timing make sense. A validator that only does the first is a grep.
Fetch the media playlist — not the master, which carries no cues — and inspect the tags directly. Count the CUE-OUT and CUE-IN occurrences and confirm they pair. Count the DATERANGE tags carrying SCTE35-OUT or SCTE35-IN attributes. Then decode any binary payload you find and check that its splice command, event id and duration agree with what the tags claim. Any mismatch between the two is worth investigating before you conclude the stream is fine.
Yes. The splice_info_section is a documented binary structure and there are good open-source parsers — threefive is the one most commonly reached for in Python. Decoding tells you the splice command type, the event id, the timing reference and any segmentation descriptors, which is exactly the information the playlist tags summarise and sometimes summarise wrongly.
An unpaired CUE-OUT. The break opens and no CUE-IN ever arrives, either because a hop dropped it or because the encoder relies on break_duration to close the break implicitly. Both are legal in different chains, which is why a validator should report the pairing rather than simply failing on it — the real question is whether whatever consumes your stream downstream can cope.
No. Validation proves the signalling is well formed and internally consistent. It says nothing about whether your ad decision layer responds in time, whether the creative matches the programme encode, or whether the splice lands where the viewer expects. It rules out one whole class of failure, which is worth a great deal, but it is a necessary condition rather than a sufficient one.
Yes. Send one live playlist URL and we will report what cues are present, in which form, whether they pair and whether the payloads decode. We built the tooling for our own pipeline and running it against one more stream costs us nothing.
The exact tags a validator reads, and what each attribute means.
What the marker carries, and the six places it dies before reaching your player.
Marking a stream that has no cues, and detecting the cues in one you did not build.
You get a plain report: which cues are present, whether every break opens and closes, whether the durations agree, and the first hop where the signal disappears. One URL, one working day, and no obligation to buy anything.

Video-technology engineer in Thane, India. Send me one live stream URL and I will run a free test on your own feed. You get my reply within one working day (IST), from the person who builds it, not a sales queue.
Send us one live URL and what you want on it. We will put a demo on your own feed before you commit to anything.