Skip to content

fix(hls): don't refresh heartbeat on playlist-only polls (#2045) - #2065

Open
andyst-dev wants to merge 1 commit into
chrisbenincasa:mainfrom
andyst-dev:fix/hls-playlist-pin
Open

fix(hls): don't refresh heartbeat on playlist-only polls (#2045)#2065
andyst-dev wants to merge 1 commit into
chrisbenincasa:mainfrom
andyst-dev:fix/hls-playlist-pin

Conversation

@andyst-dev

Copy link
Copy Markdown
Contributor

Fixes #2045

Problem

On a channel with more than one viewer, the HLS playlist window can stop advancing for everyone once a client stops requesting segments — a paused player, a backgrounded tab, a device that went to sleep. The departed client's last-requested (low/old) segment keeps holding the window open for every other viewer.

Root cause

In the fragment route (server/src/api/streamApi.ts), session.recordHeartbeat(req.ip) ran for every file request — including a poll of the variant playlist (stream.m3u8). But the playlist poll takes an early return before onSegmentRequested is ever called (the fragment route only updates _minByIp when segments are actually requested).

So a client that only polls stream.m3u8 (paused player / backgrounded tab keeps the manifest alive) stays "alive" forever — heartbeat fresh, never stale-cleaned — while its _minByIp entry stays pinned at its last requested segment. minSegmentRequested then anchors the playlist window there for all viewers.

Fix

Extract an shouldRefreshHeartbeatForFragment helper: a variant-playlist poll in the HLS modes (stream.m3u8 × hls/hls_direct_v2) does not refresh the heartbeat; segment, subtitle and other file requests do. A playlist-only client now goes stale after stalenessMs, removeStaleConnections drops it, and its pinned _minByIp entry is released — so the window resumes advancing for the surviving viewers.

A client actively watching keeps refreshing its heartbeat via its (continuous) segment requests; the master-playlist handshake is untouched. Semantics: heartbeat = actively consuming media segments, a manifest-only poller is idle.

Test

  • server/src/api/streamApi-heartbeat.test.ts (4 cases): locks the invariant — stream.m3u8 × hls/hls_direct_v2 → no heartbeat; segments/subtitles/hls_slower → heartbeat. Verified RED against current main and GREEN with the fix.
  • vitest run src/api — 18 tests pass.
  • pnpm lint-changed clean.

Note for reviewers

Happy to switch to the alternative approach (re-anchoring _minByIp on playlist poll instead of dropping the connection) if you'd prefer it over a disconnect-after-stalenessMs.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HLS playlist window stops advancing for everyone once a client falls behind (or leaves) – _minByIp never gets cleaned up

1 participant