diff --git a/k-tv-frontend/app/(main)/tv/page.tsx b/k-tv-frontend/app/(main)/tv/page.tsx index c800df1..ffcaa76 100644 --- a/k-tv-frontend/app/(main)/tv/page.tsx +++ b/k-tv-frontend/app/(main)/tv/page.tsx @@ -16,6 +16,7 @@ import { useStreamUrl, fmtTime, calcProgress, + calcOffsetSecs, minutesUntil, toScheduleSlots, findNextSlot, @@ -223,7 +224,7 @@ export default function TvPage() { ref={videoRef} src={streamUrl} className="absolute inset-0 h-full w-full" - initialOffset={broadcast?.offset_secs ?? 0} + initialOffset={broadcast ? calcOffsetSecs(broadcast.slot.start_at) : 0} onStreamError={handleStreamError} /> ); diff --git a/k-tv-frontend/hooks/use-tv.ts b/k-tv-frontend/hooks/use-tv.ts index 63c95d1..0a6f67e 100644 --- a/k-tv-frontend/hooks/use-tv.ts +++ b/k-tv-frontend/hooks/use-tv.ts @@ -24,6 +24,16 @@ export function calcProgress(startAt: string, durationSecs: number): number { 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). */ export function minutesUntil(iso: string): number { return Math.max(0, Math.round((new Date(iso).getTime() - Date.now()) / 60_000));