Background
All three client apps currently let the manifest's EXT-X-SERVER-CONTROL HOLD-BACK (HLS) or its DASH equivalent decide where the player joins live:
- Android (Compose / Media3) —
MediaItem.LiveConfiguration.setTargetOffsetMs(C.TIME_UNSET) in PlayerViewModel.loadStream().
- Apple (AVPlayer) —
item.automaticallyPreservesTimeOffsetFromLive = true in PlaybackViewModel.swift.
- Roku — defers to the OS player; no equivalent override surfaced.
Both clients report liveOffset for metrics, but neither lets the user pin the player to a specific offset.
Ask
Add an optional Live Offset Override under Settings → Advanced (next to the existing 4K / Local Proxy / Auto-Recovery / Go Live toggles), with two states:
- Off (default) — current behavior, manifest decides.
- On — exposes a numeric input or stepper (e.g. 1–60 s in 1 s steps) and pins the player to that offset.
Behavior when on:
- Android:
setTargetOffsetMs(<seconds>*1000) plus setMinOffsetMs / setMaxOffsetMs so ABR / rate-adjustment doesn't drift away.
- Apple:
item.automaticallyPreservesTimeOffsetFromLive = false and seek to currentDate - <offset> after the manifest is parsed.
Why
- Reproducible bug repros: pin every device to the same offset to compare ABR / stall behavior under identical conditions.
- Test the server's HOLD-BACK math: pinning a known-good offset eliminates client-side variance.
- Verify recovery — see whether the player snaps back to the configured offset after a stall, or drifts.
Out of scope
- Changing the server's HOLD-BACK is a separate problem (already configurable via go-live env).
- Overriding
MIN-OFFSET / MAX-OFFSET independently — start with the simple single-value override.
Touch points
android/InfiniteStreamPlayer/app/src/main/java/com/infinitestream/player/state/PlayerState.kt — add field on UiState
.../PlayerViewModel.kt — persist + apply in loadStream()
.../ui/screen/SettingsOverlay.kt — Advanced picker row
apple/InfiniteStreamPlayer/.../PlaybackViewModel.swift — same pattern
- Possibly the dashboard, if we want a per-session override there too — separate issue if so.
Background
All three client apps currently let the manifest's
EXT-X-SERVER-CONTROL HOLD-BACK(HLS) or its DASH equivalent decide where the player joins live:MediaItem.LiveConfiguration.setTargetOffsetMs(C.TIME_UNSET)inPlayerViewModel.loadStream().item.automaticallyPreservesTimeOffsetFromLive = trueinPlaybackViewModel.swift.Both clients report
liveOffsetfor metrics, but neither lets the user pin the player to a specific offset.Ask
Add an optional Live Offset Override under Settings → Advanced (next to the existing 4K / Local Proxy / Auto-Recovery / Go Live toggles), with two states:
Behavior when on:
setTargetOffsetMs(<seconds>*1000)plussetMinOffsetMs/setMaxOffsetMsso ABR / rate-adjustment doesn't drift away.item.automaticallyPreservesTimeOffsetFromLive = falseand seek tocurrentDate - <offset>after the manifest is parsed.Why
Out of scope
MIN-OFFSET/MAX-OFFSETindependently — start with the simple single-value override.Touch points
android/InfiniteStreamPlayer/app/src/main/java/com/infinitestream/player/state/PlayerState.kt— add field on UiState.../PlayerViewModel.kt— persist + apply inloadStream().../ui/screen/SettingsOverlay.kt— Advanced picker rowapple/InfiniteStreamPlayer/.../PlaybackViewModel.swift— same pattern