Skip to content

HLS: hls.js no longer plays interstitials (ad breaks); FastStream plays the stream itself, in order - #613

Merged
Nawid3333 merged 2 commits into
mainfrom
fix/hls-no-interstitials
Oct 29, 2026
Merged

Nawid3333 merged 2 commits into
mainfrom
fix/hls-no-interstitials

Conversation

@Nawid3333

Copy link
Copy Markdown
Owner

FastStream now sets enableInterstitialPlayback: false. HLS interstitials are ad breaks: an EXT-X-DATERANGE of class com.apple.hls.interstitial that points at a separate ad stream. hls.js plays each one in a player of its own, built from FastStream's config, including FastStream's loader and level control, and FastStream drives none of it.

Measured with the new e2e spec hls-interstitials.e2e.mjs (the 9 s hls-ts fixture plus a 9 s ad):

Break Before After
replacing part of the stream (live-style, no X-RESUME-OFFSET) skipped from 0 to 9.9 s within a second, ended at 13 s. Plain hls.js played to 4 s, then the ad the stream's 9 s, in order
inserted before the stream (pre-roll) no ad, but hls.js fetched the ad's playlist the stream's 9 s, the ad never requested
inserted into the stream (mid-roll) no ad, hls.js's schedule stuck at 0 unchanged: the stream's 9 s

Playing the main stream when interstitials aren't played is what the HLS spec defines for players without interstitial support. With the switch turned back on, the spec fails twice (the ad playlist is fetched; the timeline is 13 s).

Verified locally: the spec with and without the change, lint, typecheck, 3378 unit tests.

🤖 Generated with Claude Code

Nawid3333 and others added 2 commits October 29, 2026 13:41
…m itself, in order

An interstitial is an EXT-X-DATERANGE of CLASS "com.apple.hls.interstitial"
whose X-ASSET-URI is another stream (an ad) played at that point. hls.js
plays one in a player of its own built from HLSPlayer's config - FastStream's
loader and level control included - and FastStream drives none of it.

Measured on the hls-ts fixture (9 s) with a 9 s ad, new e2e spec
hls-interstitials.e2e.mjs, before and after:
- a break replacing part of the stream (no X-RESUME-OFFSET, as live ad
  insertion has it): the video skipped from 0 to 9.9 s within a second and
  ended at 13 s; plain hls.js on the same stream played it to 4 s, then the ad;
- a break inserted before the stream (X-RESUME-OFFSET=0, CUE="PRE"): no ad
  played, but hls.js fetched the ad's playlist;
- a break inserted into it: no ad, hls.js's schedule stuck at 0 (already the
  stream itself, in order).
With enableInterstitialPlayback false, all three play the stream's 9 s in
order and never ask for the ad (hls.js's InterstitialsController still reads
the schedule; playbackDisabled stops asset lists, asset players and seeks).
That is what the HLS spec has a player without interstitials do. With the
switch back on, the spec fails twice (the ad playlist fetched; a 13 s
timeline), the inserted-into case passing as measured.

Verified locally: the spec with and without the change, lint, typecheck,
3378 unit tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s clock; the comments name the pre-roll for the ad playlist

The spec failed a step of more than 2.5 s between two samples a second
apart, so one slow round trip on a busy runner could fail a correct build.
Each sample now carries the page's clock (performance.now) beside
currentTime: a step fails when the video went back, or further than the
clock went plus a second. With interstitials back on and the duration check
left out, the replacing break still fails on it (from 0, 8.9 s ahead).

The ad's playlist was fetched for the break inserted before the stream
(CUE="PRE"), not the one inserted into it, which loaded nothing; the
comments in HLSPlayer and the spec said otherwise (glm's review).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Nawid3333
Nawid3333 merged commit 27b6973 into main Oct 29, 2026
23 checks passed
@Nawid3333
Nawid3333 deleted the fix/hls-no-interstitials branch October 29, 2026 13:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant