Skip to content

1.7.0 regression: Live join with interstitial preroll starts at wrong asset, then enters stale midroll with invalid _HLS_start_offset instead of resuming at live edge #7906

Description

@philhar88

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

  1. Load the stream and autoplay.
  2. 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_offset818.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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status
    Done
    Status
    Done

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions