feat: add calcOffsetSecs utility to compute accurate elapsed seconds for broadcasts

This commit is contained in:
2026-03-11 21:21:43 +01:00
parent 477de2c49d
commit d7b21120c8
2 changed files with 12 additions and 1 deletions

View File

@@ -16,6 +16,7 @@ import {
useStreamUrl, useStreamUrl,
fmtTime, fmtTime,
calcProgress, calcProgress,
calcOffsetSecs,
minutesUntil, minutesUntil,
toScheduleSlots, toScheduleSlots,
findNextSlot, findNextSlot,
@@ -223,7 +224,7 @@ export default function TvPage() {
ref={videoRef} ref={videoRef}
src={streamUrl} src={streamUrl}
className="absolute inset-0 h-full w-full" className="absolute inset-0 h-full w-full"
initialOffset={broadcast?.offset_secs ?? 0} initialOffset={broadcast ? calcOffsetSecs(broadcast.slot.start_at) : 0}
onStreamError={handleStreamError} onStreamError={handleStreamError}
/> />
); );

View File

@@ -24,6 +24,16 @@ export function calcProgress(startAt: string, durationSecs: number): number {
return Math.min(100, Math.max(0, Math.round((elapsedSecs / durationSecs) * 100))); return Math.min(100, Math.max(0, Math.round((elapsedSecs / durationSecs) * 100)));
} }
/**
* Seconds elapsed since a slot started, computed from the current wall clock.
* Use this instead of `broadcast.offset_secs` when the broadcast may be cached —
* start_at is a fixed timestamp so the offset is always accurate regardless of
* when the broadcast response was fetched.
*/
export function calcOffsetSecs(startAt: string): number {
return Math.max(0, (Date.now() - new Date(startAt).getTime()) / 1000);
}
/** Minutes until a future timestamp (rounded, minimum 0). */ /** Minutes until a future timestamp (rounded, minimum 0). */
export function minutesUntil(iso: string): number { export function minutesUntil(iso: string): number {
return Math.max(0, Math.round((new Date(iso).getTime() - Date.now()) / 60_000)); return Math.max(0, Math.round((new Date(iso).getTime() - Date.now()) / 60_000));