Skip to content

Introduce MEDIA_SOURCE_REQUIRES_RESET error event (MediaSource closed while attached or ended on append error) - #7699

Merged
robwalch merged 1 commit into
video-dev:masterfrom
christriants:refactor/media-source-close-error-flow
Jan 23, 2026
Merged

robwalch merged 1 commit into
video-dev:masterfrom
christriants:refactor/media-source-close-error-flow

Conversation

@christriants

@christriants christriants commented Jan 22, 2026 •

Copy link
Copy Markdown
Collaborator

This PR will...

Refactor the MediaSource close handler to emit a new error event instead of directly calling recovery, allowing applications to intercept and handle the error before automatic recovery occurs.

Changes:

  1. Buffer controller now emits MEDIA_SOURCE_REQUIRES_RESET error when MediaSource closes unexpectedly
  2. Buffer controller now emits MEDIA_SOURCE_REQUIRES_RESET error from SourceBuffer update error when MediaSource is ended
  3. Error controller handles the error in onErrorOut and calls recoverMediaError() if needed
  4. Adds new error detail: ErrorDetails.MEDIA_SOURCE_REQUIRES_RESET

Why is this Pull Request needed?

When MediaSource closes unexpectedly with media attached (on Safari bfcache restore), the buffer controller directly calls this.hls.recoverMediaError(), bypassing the normal error handling flow. This change allows the media to recover through the full error handling route, where recoverMediaError would end up getting called in error-controller, instead of directly in buffer-controller.

Resolves issues:

N/A - This is a refactor, not fixing a specific reported bug. Related discussion in #7693 (comment): #7693 (comment), and a follow-up to #7683

Manual testing:

  1. Open demo page
  2. Trigger bfcache restore (navigate away and use browser back button)
  3. Verify MEDIA_SOURCE_REQUIRES_RESET error is logged
  4. Verify playback recovers

Checklist

  • changes have been done against master branch, and PR does not conflict
  • new unit / functional tests have been added (whenever applicable)
  • API or design changes are documented in API.md

@christriants
christriants marked this pull request as ready for review January 22, 2026 17:28

@robwalch robwalch left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @christriants. Thanks for following up with this PR. We need to process this work in order and coordinate changes with @zalishchuk. I'd like to merge these PRs in the following order:

#7693 is merged and resolves recoverMediaError not restarting network requests when autoStartLoad is disabled.

#7697 will circuit append error handling when it detects that Safari put the MediaSource in an "ended" state. Ideally, this change would also emit the error you are introducing here, with a different error message. This PR should actually remove the handling of MediaSource readyState: ended/.test(data.error.message) in error-controller (review feedback pending).

#7699 (this PR) introduces a new error and manages recovery by calling recoverMediaError in the error controller. We do not want this in the NetworkErrorAction.SendAlternateToPenaltyBox block, as that block is meant to handle what happens after switching, and append retries have been exhausted. We probably want a new action for "requires reset" errors, but this should probably be discussed with whoever is doing and testing the implementation.

Comment thread src/controller/error-controller.ts Outdated
Comment on lines +471 to +496
case NetworkErrorAction.SendAlternateToPenaltyBox: {
this.sendAlternateToPenaltyBox(data);
const msg = data.error?.message || '';
const isMediaSourceEnded = /MediaSource readyState: ended/.test(msg);
const isMediaSourceClosed =
data.details === ErrorDetails.MEDIA_SOURCE_CLOSED_UNEXPECTEDLY;
if (
!data.errorAction.resolved &&
data.details !== ErrorDetails.FRAG_GAP
) {
data.fatal = true;
} else if (/MediaSource readyState: ended/.test(data.error.message)) {
this.warn(
`MediaSource ended after "${data.sourceBufferName}" sourceBuffer append error. Attempting to recover from media error.`,
);
}
if (isMediaSourceEnded || isMediaSourceClosed) {
if (isMediaSourceEnded) {
this.warn(
`MediaSource ended after "${data.sourceBufferName}" sourceBuffer append error. Attempting to recover from media error.`,
);
} else {
this.warn(
`MediaSource closed unexpectedly while media was attached (${data.sourceBufferName}). Attempting to recover from media error.`,
);
}
this.hls.recoverMediaError();
}
break;
}

@robwalch robwalch Jan 22, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With #7697, or as a follow-up, that should also emit the new error event. How is the new error getting assigned SendAlternateToPenaltyBox? Is it?

My advice would be to remove this block of changes and wait for #7697 to be merged. Coordinate with @zalishchuk on removal of the /MediaSource readyState: ended/.test(msg) test. With this PR, the new error being defined should replace that test, since the error event itself has a description signalling that a reset is required.

Comment thread src/errors.ts Outdated
Comment on lines +101 to +102
// Triggered when MediaSource is closed while media is still attached
MEDIA_SOURCE_CLOSED_UNEXPECTEDLY = 'mediaSourceClosedUnexpectedly',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this more generic so it covers any error that requires a MediaSource reset?
I'd also like it to cover the "ended" state issue described in #7697. I was thinking MEDIA_SOURCE_REQUIRES_RESET. The specific details could be included in the event's error message.

@robwalch

Copy link
Copy Markdown
Collaborator

Hi @christriants. #7697 has been merged. Let me know if you can rebase and take it from here. Thanks!

@robwalch robwalch added this to the 1.7.0 milestone Jan 23, 2026
@christriants
christriants force-pushed the refactor/media-source-close-error-flow branch 2 times, most recently from dbbf972 to 068140e Compare January 23, 2026 17:50
@robwalch

Copy link
Copy Markdown
Collaborator

I found a case where we recoverMediaError alone does not resolve playback: #7535

Penalizing/switching to a supported variant would resolve the issue. Making the error fatal after and not calling recoveryMediaError after the max append error count is also necessary in case there are no alternate codec variants.

cc #7697

@christriants
christriants force-pushed the refactor/media-source-close-error-flow branch from 38b85d9 to 5236d37 Compare January 23, 2026 17:53
@christriants
christriants force-pushed the refactor/media-source-close-error-flow branch from 5236d37 to c08c23c Compare January 23, 2026 18:02
@zalishchuk

Copy link
Copy Markdown
Contributor

Can this be deployed to CF Pages to see how it performs in a real-world scenario?

@christriants

Copy link
Copy Markdown
Collaborator Author

Hey, @zalishchuk. Yes. https://hlsjs-ms-require-reset.pages.dev

@robwalch robwalch changed the title refactor: route MediaSource close through error flow Introduce MEDIA_SOURCE_REQUIRES_RESET error event (MediaSource closed while attached or ended on append error) Jan 23, 2026
@robwalch
robwalch merged commit e1a424f into video-dev:master Jan 23, 2026
12 checks passed
@github-project-automation github-project-automation Bot moved this from Top priorities to Done in HLS.js Release Planning and Backlog Jan 23, 2026
@robwalch

Copy link
Copy Markdown
Collaborator

Taking the change as-is. You can test and provide feedback using https://hlsjs-dev.video-dev.org/demo/. I'll comment again with some follow-up work for #7535. After some reconsideration, we should always emit the appending/append error events. This involves a little backtracking on #7697, but ultimately, we'll have consistent behavior when appending is not possible, or an append fails, and we should limit recovery attempts following sb update errors using the configured appendErrorMaxRetry.

robwalch added a commit that referenced this pull request Jan 23, 2026
…DR, and reset media source error action and flags

Fixes #7535
Follow-up to #7699 and #7697
@zalishchuk

Copy link
Copy Markdown
Contributor

LGTM, the recovery happened on the "ended" append buffer error before bufferAppendingError/bufferAppendError occurred

@robwalch

robwalch commented Jan 24, 2026 •

Copy link
Copy Markdown
Collaborator

LGTM, the recovery happened on the "ended" append buffer error before bufferAppendingError/bufferAppendError occurred

With #7702 the appending error is back, but it will be followed by a source reset error. This event sequence is similar to buffer full errors. It is a bit odd that two errors are emitted at once, but I am choosing to maintain this order in case folks use it for reporting purposes. Chrome also goes through the same path with readyState “ended” when it fails to parse the media. If anyone can suggest ways to differentiate those Chrome pipeline errors from the Safari platform exception, then we can differentiate the error handling slightly, but we should leave the appending error. It should be safe to ignore. Please see and comment on #7702 now that this PR is merged.

robwalch added a commit that referenced this pull request Jan 29, 2026
* Handle `MEDIA_SOURCE_REQUIRES_RESET` with variant switch, switch to SDR, and reset media source error action and flags
Fixes #7535 with unsupported HLG only variants
Follow-up to #7699 and #7697

* Do not recover from MediaSource close while attached following fatal append error

* Add media error event logging
Related to #7116

* Use add/remove event listener helpers in buffer-controller
akashchamp pushed a commit to akashchamp/hls.js that referenced this pull request Sep 25, 2026
…-dev#7702)

* Handle `MEDIA_SOURCE_REQUIRES_RESET` with variant switch, switch to SDR, and reset media source error action and flags
Fixes video-dev#7535 with unsupported HLG only variants
Follow-up to video-dev#7699 and video-dev#7697

* Do not recover from MediaSource close while attached following fatal append error

* Add media error event logging
Related to video-dev#7116

* Use add/remove event listener helpers in buffer-controller
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

3 participants