From 229670e829c2977f4d929c2ed4c59b0bbedb9409 Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Fri, 1 Nov 2024 16:54:20 +0100 Subject: [PATCH] fix(android): buffer state and video not loading --- app/(auth)/music-player.tsx | 6 +- app/(auth)/player.tsx | 187 ++++++++++++++++----------- utils/jellyfin/media/getStreamUrl.ts | 2 +- 3 files changed, 118 insertions(+), 77 deletions(-) diff --git a/app/(auth)/music-player.tsx b/app/(auth)/music-player.tsx index a13f1eb1..7f0be132 100644 --- a/app/(auth)/music-player.tsx +++ b/app/(auth)/music-player.tsx @@ -207,8 +207,9 @@ export default function page() { ); const reportPlaybackStopped = async () => { + if (!item?.Id) return; await getPlaystateApi(api!).onPlaybackStopped({ - itemId: item?.Id!, + itemId: item.Id, mediaSourceId: mediaSourceId, positionTicks: Math.floor(progress.value), playSessionId: stream?.sessionId, @@ -216,8 +217,9 @@ export default function page() { }; const reportPlaybackStart = async () => { + if (!item?.Id) return; await getPlaystateApi(api!).onPlaybackStart({ - itemId: item?.Id!, + itemId: item?.Id, audioStreamIndex: audioIndex ? audioIndex : undefined, subtitleStreamIndex: subtitleIndex ? subtitleIndex : undefined, mediaSourceId: mediaSourceId, diff --git a/app/(auth)/player.tsx b/app/(auth)/player.tsx index d7f23b54..8b775059 100644 --- a/app/(auth)/player.tsx +++ b/app/(auth)/player.tsx @@ -7,16 +7,12 @@ import { useOrientationSettings } from "@/hooks/useOrientationSettings"; import { useWebSocket } from "@/hooks/useWebsockets"; import { TrackInfo } from "@/modules/vlc-player"; import { apiAtom, userAtom } from "@/providers/JellyfinProvider"; -import { - PlaybackType, - usePlaySettings, -} from "@/providers/PlaySettingsProvider"; import { useSettings } from "@/utils/atoms/settings"; import { getBackdropUrl } from "@/utils/jellyfin/image/getBackdropUrl"; import { getAuthHeaders } from "@/utils/jellyfin/jellyfin"; import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl"; +import native from "@/utils/profiles/native"; import { secondsToTicks } from "@/utils/secondsToTicks"; -import { ticksToSeconds } from "@/utils/time"; import { Api } from "@jellyfin/sdk"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client"; import { @@ -85,7 +81,15 @@ export default function page() { } = useQuery({ queryKey: ["item", itemId], queryFn: async () => { - if (!api) return; + if (!api) { + throw new Error("No api"); + } + + if (!itemId) { + console.warn("No itemId"); + return null; + } + const res = await getUserLibraryApi(api).getItem({ itemId, userId: user?.Id, @@ -93,7 +97,6 @@ export default function page() { return res.data; }, - enabled: !!itemId && !!api, staleTime: 0, }); @@ -102,9 +105,25 @@ export default function page() { isLoading: isLoadingStreamUrl, isError: isErrorStreamUrl, } = useQuery({ - queryKey: ["stream-url"], + queryKey: [ + "stream-url", + itemId, + audioIndex, + subtitleIndex, + bitrateValue, + user, + mediaSourceId, + ], queryFn: async () => { - if (!api) return; + if (!api) { + throw new Error("No api"); + } + + if (!item) { + console.warn("No item", itemId, item); + return null; + } + const res = await getStreamUrl({ api, item, @@ -114,13 +133,17 @@ export default function page() { maxStreamingBitrate: bitrateValue, mediaSourceId: mediaSourceId, subtitleStreamIndex: subtitleIndex, + deviceProfile: native, }); if (!res) return null; const { mediaSource, sessionId, url } = res; - if (!sessionId || !mediaSource || !url) return null; + if (!sessionId || !mediaSource || !url) { + console.warn("No sessionId or mediaSource or url", url); + return null; + } return { mediaSource, @@ -128,6 +151,8 @@ export default function page() { url, }; }, + enabled: !!item, + staleTime: 0, }); const poster = usePoster(item, api); @@ -202,8 +227,9 @@ export default function page() { ); const reportPlaybackStopped = async () => { + if (!item?.Id) return; await getPlaystateApi(api!).onPlaybackStopped({ - itemId: item?.Id!, + itemId: item.Id, mediaSourceId: mediaSourceId, positionTicks: Math.floor(progress.value), playSessionId: stream?.sessionId, @@ -211,8 +237,9 @@ export default function page() { }; const reportPlaybackStart = async () => { + if (!item?.Id) return; await getPlaystateApi(api!).onPlaybackStart({ - itemId: item?.Id!, + itemId: item.Id, audioStreamIndex: audioIndex ? audioIndex : undefined, subtitleStreamIndex: subtitleIndex ? subtitleIndex : undefined, mediaSourceId: mediaSourceId, @@ -230,9 +257,14 @@ export default function page() { progress.value = ticks; cacheProgress.value = secondsToTicks(data.playableDuration); - setIsBuffering(data.playableDuration === 0); - if (!item?.Id || data.currentTime === 0) return; + // TODO: Use this when streaming with HLS url, but NOT when direct playing + // TODO: since playable duration is always 0 then. + // setIsBuffering(data.playableDuration === 0); + + if (!item?.Id || data.currentTime === 0) { + return; + } await getPlaystateApi(api!).onPlaybackProgress({ itemId: item.Id, @@ -314,8 +346,6 @@ export default function page() { ); - if (!stream || !item || !videoSource) return null; - return ( - ); } @@ -452,7 +491,7 @@ export function useVideoSource( subtitle: item?.Album ?? undefined, }, }; - }, [item, api, poster]); + }, [item, api, poster, url]); return videoSource; } diff --git a/utils/jellyfin/media/getStreamUrl.ts b/utils/jellyfin/media/getStreamUrl.ts index 9dce3c78..5f79cbe2 100644 --- a/utils/jellyfin/media/getStreamUrl.ts +++ b/utils/jellyfin/media/getStreamUrl.ts @@ -86,7 +86,7 @@ export const getStreamUrl = async ({ { method: "POST", data: { - deviceProfile: native, + deviceProfile, userId, maxStreamingBitrate, startTimeTicks,