Skip to content

Fix playback retry position - #8200

Closed
anagnorisis2peripeteia wants to merge 1 commit into
jellyfin:masterfrom
anagnorisis2peripeteia:preserve-retry-position
Closed

Fix playback retry position#8200
anagnorisis2peripeteia wants to merge 1 commit into
jellyfin:masterfrom
anagnorisis2peripeteia:preserve-retry-position

Conversation

@anagnorisis2peripeteia

Copy link
Copy Markdown

Background

I first noticed this at the gym, where the Wi-Fi and whatever 5G I could get inside the building were both pretty flaky. When the connection stalled, playback would sometimes seem to randomly restart.

It wasnt actually going back to the beginning. It was jumping back to the resume point the session originally started from, so any progress made during the current session was ditched.

Changes

This keeps the last real player position when the media element briefly reports zero and uses it for the retry. An actual seek back to zero still stays at zero.

It also makes HLS errors after startup go through the normal playback error path so fallback can actually run. This doesnt change codec, transcoding, subtitle, buffering, server or UI policy.

How it fixes it

There were two parts to the problem.

HLS errors that happened after playback had already started could still be handled like startup failures. That meant the normal playback error and fallback path didnt always run.

When the failing media element was reset it could also briefly report its position as zero. The retry would then fall back to the saved resume point from the start of the session, which is why it looked like playback had randomly restarted.

This change sends post-start HLS errors through the normal fallback path and keeps the last real playback position through that temporary zero. A deliberate seek back to zero is still kept as zero.

Issues

This addresses the HTML player and Android WebView recovery path behind the same kind of rewind reported in:

Both issues are still open, but they also contain reports involving other players and possible media timestamp problems. I dont think this PR should automatically close either of them or claim to fix the Android TV player.

Code assistance

I used Codex to trace the player paths, help write the patch and tests, run the local checks, and set up the controlled before and after test on my Viture Neckband. I reviewed the code, test results, recordings and proof as we worked through it.

Testing

  • npm run lint passed with 0 errors
  • npm run stylelint passed
  • npm run build:check passed
  • npm test passed, 16 files and 186 tests
  • npm run build:es-check passed the production build and checked 981 generated JavaScript files
  • Focused Stryker run covered 30 mutants with 29 killed, 1 timeout and 0 survivors

Before and after proof

I reproduced the flaky connection as a controlled failure using the same Viture Neckband V1231, Jellyfin Android 2.6.3, Android System WebView 150, Jellyfin server 10.10.3 and Fallout S2E7 H264/EAC3 HLS remux.

Both runs started from a five minute saved position, played past twenty minutes, then returned HTTP 503 for exactly the next HLS segment.

Before, playback was at 21:37 when the connection failed. The active session dropped to zero and paused, the app returned to the series backdrop, and there was no retry PlaybackInfo request.

After, playback was at 20:22 when the connection failed. The client immediately requested fallback PlaybackInfo, restarted near the current session position, and was still playing at 21:12.

The public clips are pixelated and have no audio. The package contains the supporting logs, session state and checksums.

Non-video proof

The redacted request logs and Jellyfin session snapshots show the same result as the recordings:

  • Before session state: playback went from 21:37 and playing to position zero and paused after the injected failure.
  • Before request log: the HLS segment received the controlled 503, but there was no fallback PlaybackInfo request.
  • After session state: playback went from 20:22 to 21:12 and remained playing.
  • After request log: the controlled 503 was immediately followed by a new PlaybackInfo request and fallback HLS segment requests.

Peer review: #8141 (review)

Review history: https://gist.github.com/8762ab257c5bee19c29ed0e1c62568cf


  • I have read and followed the contributing guidelines.
  • I have tested these changes.
  • I have verified that this is not duplicating changes in an existing PR.
  • I have provided a substantive review of another web PR.

@anagnorisis2peripeteia
anagnorisis2peripeteia requested a review from a team as a code owner July 11, 2026 20:44
@sonarqubecloud

Copy link
Copy Markdown

@thornbill thornbill added the invalid Doesn't seem right or does not follow the templates label Jul 11, 2026
@thornbill thornbill closed this Jul 11, 2026
@anagnorisis2peripeteia

Copy link
Copy Markdown
Author

@thornbill sorry, what's invalid?

@thornbill

Copy link
Copy Markdown
Member

Had you done what you claim then you should already know why this PR is invalid.

@anagnorisis2peripeteia

Copy link
Copy Markdown
Author

Had you done what you claim then you should already know why this PR is invalid.

@thornbill I have to assume given your unwillingness to be forthcoming you think I didn't adhere to the contributing guidelines somehow?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

invalid Doesn't seem right or does not follow the templates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants