What version of HLS.js are you using?
1.7.0-beta.1 and current master (006387660). Does not reproduce on builds prior to #7846 (987320e05): those start the preroll at asset 1.
What browser (including version) are you using?
Chromium 142 (Electron 42), headless. Also reproduces in desktop Chrome.
What OS (including version) are you using?
Linux (Amazon Linux 2023, aarch64)
Test stream
AWS MediaTailor live SGAI stream: CUE="PRE,ONCE" preroll daterange with X-ASSET-LIST (2×15s assets) and X-PLAYOUT-LIMIT=30.0, plus recurring 15s SCTE-35 midroll dateranges. No slate prepend; asset playlists are clean CMAF VOD. Reproduces identically on the standard and LL-HLS endpoints:
Full debug: true logs, asset-list request captures, and 1.6.16 contrast runs for both endpoints:
https://gist.github.com/philhar88/a5521acb23950bb7300f55d5f85914b3
Configuration
{
"debug": true,
"enableWorker": true,
"lowLatencyMode": false,
"backBufferLength": 90
}
Additional player setup steps
None. Default interstitials handling, autoplay muted, no seeking or other interaction.
Checklist
- The issue observed is not already reported by searching on Github under https://github.com/video-dev/hls.js/issues
- The issue occurs in the latest client (main branch) on https://hlsjs-dev.video-dev.org/demo and not just on my page
- The stream has correct Access-Control-Allow-Origin headers (CORS)
- There are no network errors such as 404s in the browser console when trying to play the stream (all playlist/asset-list responses are 200; the fragLoadErrors described below are requests for expired segment sequence numbers)
Steps to reproduce
- Load the stream and autoplay.
- Observe preroll asset selection, the asset-list network requests, and what happens after the preroll ends.
Expected behaviour
- Preroll plays asset 1 then asset 2 from the beginning (
CUE="PRE").
- After the preroll, primary playback joins near the live edge.
- Any
_HLS_start_offset on an asset-list request reflects an offset into that interstitial.
What actually happened?
Four observations, deterministic across runs and across both endpoints:
1. Preroll starts at the last asset; asset 1 never plays.
[interstitials]: [checkStart (preroll)] Advancing timeline position to 28.538537061171866
[interstitials]: setSchedulePosition 0, undefined (["aws-mediatailor-preroll-1": 0.00-28.54]) pos: 28.538537061171866
[interstitials]: INTERSTITIAL_ASSET_STARTED 2/2 ["aws-mediatailor-preroll-1-2-211891537" 15.00-30.00]
On the LL-HLS endpoint the live join position (~28.5) falls inside asset 2's window (15.00–30.00) and the player additionally seeks into the asset, so total preroll playback is ~1.6s:
[stream-controller]: seek to target start position 13.53753706117186 from current time 0 buffer start 12.066666
On the standard endpoint (deeper window, join position ~880) asset 2 plays from 0. Either way asset 1 is skipped.
2. After the preroll, the scheduler enters the oldest midroll in the playlist (its segments near expiry at the trailing edge of the live window) instead of joining at the live edge. The viewer gets an additional, unscheduled ad break.
3. The asset-list request for that midroll carries an out-of-range _HLS_start_offset — 818.975 (standard) / 28.542 (LL-HLS) for a 15-second interstitial. The value equals liveStartPosition − interstitial.timelineStart, i.e. a primary-timeline position rather than an offset into the interstitial:
[interstitials]: Load interstitial asset 1/0 ["1781218837866-101-270F" -0.00-14.93] live-start: 28.541537061171866 start-offset: 28.542
4. Primary playback never starts. After the stale midroll ends, the primary resumes at a timeline position at/behind the sliding live window and every fragment request fails; the session is unrecoverable within ~32s of load (~90s observed with no recovery, empty buffer, readyState 0):
[interstitials]: [attachPrimary] Advancing timeline position to 15.166000666666664
[interstitials]: INTERSTITIALS_PRIMARY_RESUMED [primary: 14.93-59.97]
→ repeated fragLoadError (51 events), buffered=[], readyState 0
A fatal audioTrackLoadError on the detached primary was also observed during the preroll on the LL-HLS endpoint.
Minor, related: after the CUE="ONCE" preroll is removed from the schedule, each playlist refresh logs Ignoring invalid DATERANGE tag for the SCTE35-IN companion of the already-removed midroll daterange ID.
Console output
See gist for full per-run logs (asset-list requests, debug log, API events, buffer/readyState ticks):
https://gist.github.com/philhar88/a5521acb23950bb7300f55d5f85914b3
Chrome media internals output
Not applicable — no media decode error. The behavior is in interstitial schedule position, asset selection, and resume position.
Additional context
For contrast (included in the gist), v1.6.16 on the same stream plays the full preroll (asset 1 → asset 2) with no offset on asset-list requests; its post-preroll join failure is a different, pre-existing issue and out of scope here. The wrong-asset selection in observation 1 bisects to #7846 (1a6cdfe0e); builds at 987320e05 (immediately before) and 1214aa024 start at asset 1. Related to #7845, whose unit tests cover the midroll _HLS_start_offset value but not which preroll asset is selected at live join.
What version of HLS.js are you using?
1.7.0-beta.1 and current master (
006387660). Does not reproduce on builds prior to #7846 (987320e05): those start the preroll at asset 1.What browser (including version) are you using?
Chromium 142 (Electron 42), headless. Also reproduces in desktop Chrome.
What OS (including version) are you using?
Linux (Amazon Linux 2023, aarch64)
Test stream
AWS MediaTailor live SGAI stream:
CUE="PRE,ONCE"preroll daterange withX-ASSET-LIST(2×15s assets) andX-PLAYOUT-LIMIT=30.0, plus recurring 15s SCTE-35 midroll dateranges. No slate prepend; asset playlists are clean CMAF VOD. Reproduces identically on the standard and LL-HLS endpoints:llhls.m3u8Full
debug: truelogs, asset-list request captures, and 1.6.16 contrast runs for both endpoints:https://gist.github.com/philhar88/a5521acb23950bb7300f55d5f85914b3
Configuration
Additional player setup steps
None. Default interstitials handling, autoplay muted, no seeking or other interaction.
Checklist
Steps to reproduce
Expected behaviour
CUE="PRE")._HLS_start_offseton an asset-list request reflects an offset into that interstitial.What actually happened?
Four observations, deterministic across runs and across both endpoints:
1. Preroll starts at the last asset; asset 1 never plays.
On the LL-HLS endpoint the live join position (~28.5) falls inside asset 2's window (15.00–30.00) and the player additionally seeks into the asset, so total preroll playback is ~1.6s:
On the standard endpoint (deeper window, join position ~880) asset 2 plays from 0. Either way asset 1 is skipped.
2. After the preroll, the scheduler enters the oldest midroll in the playlist (its segments near expiry at the trailing edge of the live window) instead of joining at the live edge. The viewer gets an additional, unscheduled ad break.
3. The asset-list request for that midroll carries an out-of-range
_HLS_start_offset—818.975(standard) /28.542(LL-HLS) for a 15-second interstitial. The value equalsliveStartPosition − interstitial.timelineStart, i.e. a primary-timeline position rather than an offset into the interstitial:4. Primary playback never starts. After the stale midroll ends, the primary resumes at a timeline position at/behind the sliding live window and every fragment request fails; the session is unrecoverable within ~32s of load (~90s observed with no recovery, empty buffer,
readyState 0):A fatal
audioTrackLoadErroron the detached primary was also observed during the preroll on the LL-HLS endpoint.Minor, related: after the
CUE="ONCE"preroll is removed from the schedule, each playlist refresh logsIgnoring invalid DATERANGE tagfor the SCTE35-IN companion of the already-removed midroll daterange ID.Console output
Chrome media internals output
Not applicable — no media decode error. The behavior is in interstitial schedule position, asset selection, and resume position.
Additional context
For contrast (included in the gist), v1.6.16 on the same stream plays the full preroll (asset 1 → asset 2) with no offset on asset-list requests; its post-preroll join failure is a different, pre-existing issue and out of scope here. The wrong-asset selection in observation 1 bisects to #7846 (
1a6cdfe0e); builds at987320e05(immediately before) and1214aa024start at asset 1. Related to #7845, whose unit tests cover the midroll_HLS_start_offsetvalue but not which preroll asset is selected at live join.