feat: enhance stream URL handling and add initial offset support in VideoPlayer
This commit is contained in:
@@ -65,30 +65,44 @@ export function findNextSlot(
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Resolves the live stream URL for a channel.
|
||||
* Resolves the live stream URL for a channel, starting at the correct
|
||||
* broadcast offset so refresh doesn't replay from the beginning.
|
||||
*
|
||||
* The backend's GET /channels/:id/stream endpoint returns a 307 redirect to
|
||||
* the Jellyfin stream URL. Since browsers can't read redirect Location headers
|
||||
* from fetch(), we proxy through /api/stream/[channelId] (a Next.js route that
|
||||
* runs server-side) and return the final URL as JSON.
|
||||
*
|
||||
* slotId is included in the query key so the URL is re-fetched automatically
|
||||
* when the current item changes (the next scheduled item starts playing).
|
||||
* Within the same slot, the URL stays stable — no mid-item restarts.
|
||||
*
|
||||
* Returns null when the channel is in a gap (no-signal / 204).
|
||||
*/
|
||||
export function useStreamUrl(channelId: string | undefined, token: string | null) {
|
||||
/**
|
||||
* slotId is in the query key so the URL refetches when the playing item
|
||||
* changes (new slot starts), but stays stable while the same item runs —
|
||||
* no mid-item restarts.
|
||||
*/
|
||||
export function useStreamUrl(
|
||||
channelId: string | undefined,
|
||||
token: string | null,
|
||||
slotId: string | undefined,
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: ["stream-url", channelId],
|
||||
queryKey: ["stream-url", channelId, slotId],
|
||||
queryFn: async (): Promise<string | null> => {
|
||||
const res = await fetch(
|
||||
`/api/stream/${channelId}?token=${encodeURIComponent(token!)}`,
|
||||
{ cache: "no-store" },
|
||||
);
|
||||
const params = new URLSearchParams({ token: token! });
|
||||
const res = await fetch(`/api/stream/${channelId}?${params}`, {
|
||||
cache: "no-store",
|
||||
});
|
||||
if (res.status === 204) return null;
|
||||
if (!res.ok) throw new Error(`Stream resolve failed: ${res.status}`);
|
||||
const { url } = await res.json();
|
||||
return url as string;
|
||||
},
|
||||
enabled: !!channelId && !!token,
|
||||
refetchInterval: 30_000,
|
||||
enabled: !!channelId && !!token && !!slotId,
|
||||
staleTime: Infinity,
|
||||
retry: false,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user