diff --git a/components/PlayButton.tsx b/components/PlayButton.tsx index 4a6a2e30..66d1c434 100644 --- a/components/PlayButton.tsx +++ b/components/PlayButton.tsx @@ -115,96 +115,100 @@ export const PlayButton: React.FC = ({ case 0: if (!Platform.isTV) { await CastContext.getPlayServicesState().then(async (state) => { - if (state && state !== PlayServicesState.SUCCESS) + if (state && state !== PlayServicesState.SUCCESS) { CastContext.showPlayServicesErrorDialog(state); - else { + } else { // Get a new URL with the Chromecast device profile: - const data = await getStreamUrl({ - api, - item, - deviceProfile: chromecastProfile, - startTimeTicks: item?.UserData?.PlaybackPositionTicks!, - userId: user?.Id, - audioStreamIndex: selectedOptions.audioIndex, - maxStreamingBitrate: selectedOptions.bitrate?.value, - mediaSourceId: selectedOptions.mediaSource?.Id, - subtitleStreamIndex: selectedOptions.subtitleIndex, - }); - - if (!data?.url) { - console.warn("No URL returned from getStreamUrl", data); - Alert.alert( - t("player.client_error"), - t("player.could_not_create_stream_for_chromecast") - ); - return; - } - - client - .loadMedia({ - mediaInfo: { - contentUrl: data?.url, - contentType: "video/mp4", - metadata: - item.Type === "Episode" - ? { - type: "tvShow", - title: item.Name || "", - episodeNumber: item.IndexNumber || 0, - seasonNumber: item.ParentIndexNumber || 0, - seriesTitle: item.SeriesName || "", - images: [ - { - url: getParentBackdropImageUrl({ - api, - item, - quality: 90, - width: 2000, - })!, - }, - ], - } - : item.Type === "Movie" - ? { - type: "movie", - title: item.Name || "", - subtitle: item.Overview || "", - images: [ - { - url: getPrimaryImageUrl({ - api, - item, - quality: 90, - width: 2000, - })!, - }, - ], - } - : { - type: "generic", - title: item.Name || "", - subtitle: item.Overview || "", - images: [ - { - url: getPrimaryImageUrl({ - api, - item, - quality: 90, - width: 2000, - })!, - }, - ], - }, - }, - startTime: 0, - }) - .then(() => { - // state is already set when reopening current media, so skip it here. - if (isOpeningCurrentlyPlayingMedia) { - return; - } - CastContext.showExpandedControls(); + try { + const data = await getStreamUrl({ + api, + item, + deviceProfile: chromecastProfile, + startTimeTicks: item?.UserData?.PlaybackPositionTicks!, + userId: user?.Id, + audioStreamIndex: selectedOptions.audioIndex, + maxStreamingBitrate: selectedOptions.bitrate?.value, + mediaSourceId: selectedOptions.mediaSource?.Id, + subtitleStreamIndex: selectedOptions.subtitleIndex, }); + + if (!data?.url) { + console.warn("No URL returned from getStreamUrl", data); + Alert.alert( + t("player.client_error"), + t("player.could_not_create_stream_for_chromecast") + ); + return; + } + + client + .loadMedia({ + mediaInfo: { + contentUrl: data?.url, + contentType: "video/mp4", + metadata: + item.Type === "Episode" + ? { + type: "tvShow", + title: item.Name || "", + episodeNumber: item.IndexNumber || 0, + seasonNumber: item.ParentIndexNumber || 0, + seriesTitle: item.SeriesName || "", + images: [ + { + url: getParentBackdropImageUrl({ + api, + item, + quality: 90, + width: 2000, + })!, + }, + ], + } + : item.Type === "Movie" + ? { + type: "movie", + title: item.Name || "", + subtitle: item.Overview || "", + images: [ + { + url: getPrimaryImageUrl({ + api, + item, + quality: 90, + width: 2000, + })!, + }, + ], + } + : { + type: "generic", + title: item.Name || "", + subtitle: item.Overview || "", + images: [ + { + url: getPrimaryImageUrl({ + api, + item, + quality: 90, + width: 2000, + })!, + }, + ], + }, + }, + startTime: 0, + }) + .then(() => { + // state is already set when reopening current media, so skip it here. + if (isOpeningCurrentlyPlayingMedia) { + return; + } + CastContext.showExpandedControls(); + }); + } catch (e) { + console.log(e); + } } }); } diff --git a/utils/jellyfin/media/getStreamUrl.ts b/utils/jellyfin/media/getStreamUrl.ts index de5f2e41..482f7833 100644 --- a/utils/jellyfin/media/getStreamUrl.ts +++ b/utils/jellyfin/media/getStreamUrl.ts @@ -36,6 +36,7 @@ export const getStreamUrl = async ({ mediaSource: MediaSourceInfo | undefined; } | null> => { if (!api || !userId || !item?.Id) { + console.warn("Missing required parameters for getStreamUrl"); return null; } @@ -120,9 +121,7 @@ export const getStreamUrl = async ({ sessionId: sessionId, mediaSource, }; - } - - if (mediaSource?.SupportsDirectPlay) { + } else { const searchParams = new URLSearchParams({ playSessionId: sessionData?.PlaySessionId || "", mediaSourceId: mediaSource?.Id || "", @@ -149,39 +148,4 @@ export const getStreamUrl = async ({ }; } } - - if (item.MediaType === "Audio") { - if (mediaSource?.TranscodingUrl) { - return { - url: `${api.basePath}${mediaSource.TranscodingUrl}`, - sessionId, - mediaSource, - }; - } - - const searchParams = new URLSearchParams({ - UserId: userId, - DeviceId: api.deviceInfo.id, - MaxStreamingBitrate: "140000000", - Container: - "opus,webm|opus,mp3,aac,m4a|aac,m4b|aac,flac,webma,webm|webma,wav,ogg", - TranscodingContainer: "mp4", - TranscodingProtocol: "hls", - AudioCodec: "aac", - api_key: api.accessToken, - PlaySessionId: sessionData?.PlaySessionId || "", - StartTimeTicks: "0", - EnableRedirection: "true", - EnableRemoteMedia: "false", - }); - return { - url: `${ - api.basePath - }/Audio/${itemId}/universal?${searchParams.toString()}`, - sessionId, - mediaSource, - }; - } - - throw new Error("Unsupported media type"); }; diff --git a/utils/profiles/chromecast.ts b/utils/profiles/chromecast.ts index 83bb6eb2..da4d0588 100644 --- a/utils/profiles/chromecast.ts +++ b/utils/profiles/chromecast.ts @@ -15,6 +15,7 @@ export const chromecastProfile: DeviceProfile = { Codec: "aac,mp3,flac,opus,vorbis", }, ], + ContainerProfiles: [], DirectPlayProfiles: [ { Container: "mp4",