seek via underlying media element for resume

This commit is contained in:
2026-06-06 21:54:01 +03:00
parent 5d12a5edc6
commit c9f6d92a7f
+47 -9
View File
@@ -348,6 +348,19 @@ export default function PlayerPage() {
}
return ''
})()
if (typeof window !== 'undefined' && playbackInfo) {
const transcodingUrl = resolvedSource?.TranscodingUrl
const supportsDirectPlay = resolvedSource?.SupportsDirectPlay
const hasRuntimeTicks = transcodingUrl ? transcodingUrl.includes('runtimeTicks=') : null
console.log('[player] stream resolved', {
id,
startTimeTicks,
supportsDirectPlay,
transcodingUrlPresent: !!transcodingUrl,
transcodingUrlHasRuntimeTicks: hasRuntimeTicks,
streamUrl: streamUrl.replace(/api_key=[^&]+/, 'api_key=***'),
})
}
/* Reset transient flags on item change */
useEffect(() => {
@@ -1164,8 +1177,13 @@ export default function PlayerPage() {
if (p && pendingSeekRef.current != null) {
const target = pendingSeekRef.current
pendingSeekRef.current = null
if (p.currentTime < target - 0.5 || p.currentTime > target + 0.5) {
try { p.currentTime = target } catch { /* ignore */ }
const mediaEl = (p as any).media as HTMLMediaElement | undefined
const before = mediaEl ? mediaEl.currentTime : p.currentTime
if (before < target - 0.5 || before > target + 0.5) {
try {
if (mediaEl) mediaEl.currentTime = target
else p.currentTime = target
} catch { /* ignore */ }
}
p.play().catch(() => {})
}
@@ -1403,13 +1421,29 @@ export default function PlayerPage() {
setResumePromptOpen(false)
const p = playerRef.current
const pos = Number(item?.UserData?.PlaybackPositionTicks ?? 0)
const target = pos > 0 ? pos / 10_000_000 : 0
if (typeof window !== 'undefined') {
console.log('[player] resume prompt clicked', {
id,
pos,
target,
mediaElementCurrentTime: (p as any)?.media?.currentTime,
streamUrlStart: streamUrl.includes('StartTimeTicks=') || streamUrl.includes('runtimeTicks='),
})
}
if (p) {
// Queue the seek: if the video isn't ready yet, onCanPlay
// picks it up. The setter works on a paused player in
// vidstack, but buffering the seek target can race the
// canPlay event for the initial source.
pendingSeekRef.current = pos > 0 ? pos / 10_000_000 : 0
try { p.currentTime = pendingSeekRef.current } catch { /* ignore */ }
// Vidstack has a known issue (GH #941) where setting
// currentTime on the MediaPlayerInstance for a direct-play
// MP4 source restarts the video from the beginning. The
// workaround is to set currentTime on the underlying
// HTMLMediaElement. For HLS it works either way; we use
// the underlying element for consistency.
pendingSeekRef.current = target
const mediaEl = (p as any).media as HTMLMediaElement | undefined
try {
if (mediaEl) mediaEl.currentTime = target
else p.currentTime = target
} catch { /* ignore */ }
p.play().catch(() => {})
}
},
@@ -1418,7 +1452,11 @@ export default function PlayerPage() {
const p = playerRef.current
if (p) {
pendingSeekRef.current = 0
try { p.currentTime = 0 } catch { /* ignore */ }
const mediaEl = (p as any).media as HTMLMediaElement | undefined
try {
if (mediaEl) mediaEl.currentTime = 0
else p.currentTime = 0
} catch { /* ignore */ }
p.play().catch(() => {})
}
},