diff --git a/client/src/views/player/Player.ts b/client/src/views/player/Player.ts index 2b24964..dd9d37e 100644 --- a/client/src/views/player/Player.ts +++ b/client/src/views/player/Player.ts @@ -1260,7 +1260,20 @@ function renderVideoPlayer(root: HTMLElement, partyId: string, party: PartyPubli loadMarkers(party.itemId); // not awaited - see onItemChanged's own comment await loadTrackOptions(party.itemId); - loadVideo(party.itemId, 0, false); + // Unlike onItemChanged's own loadVideo(..., 0, ...) - genuinely correct + // there since a fresh item has no position yet - mounting mid-party + // (a joining guest, or the host's own page reload) must NOT hardcode 0: + // the party's shared Emby transcode (PartyStreamService) is keyed by + // partyId alone, one PlaySessionId for every member, so a hls.js + // instance requesting segments from 0 against a session that already + // progressed well past that forces Emby to seek/restart the shared + // transcode - stalling it for every other member, host included, right + // as the newcomer joins. Seeding from the host's last-reported position + // (already in party.members, sent to every mount) lands the first + // segment request near where the shared session already is instead. + const hostMember = party.members.find((m) => m.isHost); + const initialResumeSeconds = hostMember ? hostMember.positionTicks / TICKS_PER_SECOND : 0; + loadVideo(party.itemId, initialResumeSeconds, false); conn = connectParty(partyId, { onMembers: renderMembers,