mirror of
https://github.com/streamyfin/streamyfin.git
synced 2025-08-20 18:37:18 +02:00
fix: download url not correct for direct streams
This commit is contained in:
4
app.json
4
app.json
@@ -2,7 +2,7 @@
|
|||||||
"expo": {
|
"expo": {
|
||||||
"name": "Streamyfin",
|
"name": "Streamyfin",
|
||||||
"slug": "streamyfin",
|
"slug": "streamyfin",
|
||||||
"version": "0.10.1",
|
"version": "0.10.2",
|
||||||
"orientation": "default",
|
"orientation": "default",
|
||||||
"icon": "./assets/images/icon.png",
|
"icon": "./assets/images/icon.png",
|
||||||
"scheme": "streamyfin",
|
"scheme": "streamyfin",
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
},
|
},
|
||||||
"android": {
|
"android": {
|
||||||
"jsEngine": "hermes",
|
"jsEngine": "hermes",
|
||||||
"versionCode": 30,
|
"versionCode": 31,
|
||||||
"adaptiveIcon": {
|
"adaptiveIcon": {
|
||||||
"foregroundImage": "./assets/images/icon.png"
|
"foregroundImage": "./assets/images/icon.png"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -65,15 +65,14 @@ const downloads: React.FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView>
|
<ScrollView
|
||||||
<View
|
contentContainerStyle={{
|
||||||
className="px-4 py-4"
|
paddingLeft: insets.left,
|
||||||
style={{
|
paddingRight: insets.right,
|
||||||
paddingLeft: insets.left,
|
paddingBottom: 100,
|
||||||
paddingRight: insets.right,
|
}}
|
||||||
paddingBottom: 100,
|
>
|
||||||
}}
|
<View className="px-4 py-4">
|
||||||
>
|
|
||||||
<View className="mb-4 flex flex-col space-y-4">
|
<View className="mb-4 flex flex-col space-y-4">
|
||||||
<View>
|
<View>
|
||||||
<Text className="text-2xl font-bold mb-2">Queue</Text>
|
<Text className="text-2xl font-bold mb-2">Queue</Text>
|
||||||
|
|||||||
@@ -27,9 +27,15 @@ export default function settings() {
|
|||||||
const insets = useSafeAreaInsets();
|
const insets = useSafeAreaInsets();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView>
|
<ScrollView
|
||||||
|
contentContainerStyle={{
|
||||||
|
paddingLeft: insets.left,
|
||||||
|
paddingRight: insets.right,
|
||||||
|
paddingBottom: 100,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<View
|
<View
|
||||||
className="p-4 flex flex-col gap-y-4 pb-12"
|
className="p-4 flex flex-col gap-y-4"
|
||||||
style={{
|
style={{
|
||||||
paddingLeft: insets.left,
|
paddingLeft: insets.left,
|
||||||
paddingRight: insets.right,
|
paddingRight: insets.right,
|
||||||
|
|||||||
@@ -145,15 +145,13 @@ export const DownloadItem: React.FC<DownloadProps> = ({ item, ...props }) => {
|
|||||||
item.Id
|
item.Id
|
||||||
}/universal?${searchParams.toString()}`;
|
}/universal?${searchParams.toString()}`;
|
||||||
}
|
}
|
||||||
}
|
} else if (mediaSource.TranscodingUrl) {
|
||||||
|
|
||||||
if (mediaSource.TranscodingUrl) {
|
|
||||||
console.log("Using transcoded stream!");
|
console.log("Using transcoded stream!");
|
||||||
url = `${api.basePath}${mediaSource.TranscodingUrl}`;
|
url = `${api.basePath}${mediaSource.TranscodingUrl}`;
|
||||||
} else {
|
|
||||||
throw new Error("No transcoding url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!url) throw new Error("No url");
|
||||||
|
|
||||||
return await startRemuxing(url);
|
return await startRemuxing(url);
|
||||||
}, [
|
}, [
|
||||||
api,
|
api,
|
||||||
|
|||||||
@@ -36,6 +36,14 @@ export const MediaSourceSelector: React.FC<Props> = ({
|
|||||||
if (mediaSources?.length) onChange(mediaSources[0]);
|
if (mediaSources?.length) onChange(mediaSources[0]);
|
||||||
}, [mediaSources]);
|
}, [mediaSources]);
|
||||||
|
|
||||||
|
const name = (name?: string | null) => {
|
||||||
|
if (name && name.length > 40)
|
||||||
|
return (
|
||||||
|
name.substring(0, 20) + " [...] " + name.substring(name.length - 20)
|
||||||
|
);
|
||||||
|
return name;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
className="flex shrink"
|
className="flex shrink"
|
||||||
@@ -69,7 +77,9 @@ export const MediaSourceSelector: React.FC<Props> = ({
|
|||||||
onChange(source);
|
onChange(source);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DropdownMenu.ItemTitle>{source.Name}</DropdownMenu.ItemTitle>
|
<DropdownMenu.ItemTitle>
|
||||||
|
{name(source.Name)}
|
||||||
|
</DropdownMenu.ItemTitle>
|
||||||
</DropdownMenu.Item>
|
</DropdownMenu.Item>
|
||||||
))}
|
))}
|
||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { useImageColors } from "@/hooks/useImageColors";
|
import { useImageColors } from "@/hooks/useImageColors";
|
||||||
import { apiAtom } from "@/providers/JellyfinProvider";
|
import { apiAtom } from "@/providers/JellyfinProvider";
|
||||||
import { itemThemeColorAtom } from "@/utils/atoms/primaryColor";
|
|
||||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||||
import { Image, ImageProps, ImageSource } from "expo-image";
|
import { Image, ImageProps, ImageSource } from "expo-image";
|
||||||
import { useAtom } from "jotai";
|
import { useAtom } from "jotai";
|
||||||
import { useEffect, useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { getColors } from "react-native-image-colors";
|
|
||||||
|
|
||||||
interface Props extends ImageProps {
|
interface Props extends ImageProps {
|
||||||
item: BaseItemDto;
|
item: BaseItemDto;
|
||||||
|
|||||||
4
eas.json
4
eas.json
@@ -21,13 +21,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"production": {
|
"production": {
|
||||||
"channel": "0.10.1",
|
"channel": "0.10.2",
|
||||||
"android": {
|
"android": {
|
||||||
"image": "latest"
|
"image": "latest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"production-apk": {
|
"production-apk": {
|
||||||
"channel": "0.10.1",
|
"channel": "0.10.2",
|
||||||
"android": {
|
"android": {
|
||||||
"buildType": "apk",
|
"buildType": "apk",
|
||||||
"image": "latest"
|
"image": "latest"
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
setJellyfin(
|
setJellyfin(
|
||||||
() =>
|
() =>
|
||||||
new Jellyfin({
|
new Jellyfin({
|
||||||
clientInfo: { name: "Streamyfin", version: "0.10.1" },
|
clientInfo: { name: "Streamyfin", version: "0.10.2" },
|
||||||
deviceInfo: { name: Platform.OS === "ios" ? "iOS" : "Android", id },
|
deviceInfo: { name: Platform.OS === "ios" ? "iOS" : "Android", id },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -80,7 +80,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
|||||||
return {
|
return {
|
||||||
authorization: `MediaBrowser Client="Streamyfin", Device=${
|
authorization: `MediaBrowser Client="Streamyfin", Device=${
|
||||||
Platform.OS === "android" ? "Android" : "iOS"
|
Platform.OS === "android" ? "Android" : "iOS"
|
||||||
}, DeviceId="${deviceId}", Version="0.10.1"`,
|
}, DeviceId="${deviceId}", Version="0.10.2"`,
|
||||||
};
|
};
|
||||||
}, [deviceId]);
|
}, [deviceId]);
|
||||||
|
|
||||||
|
|||||||
@@ -76,10 +76,12 @@ export const getStreamUrl = async ({
|
|||||||
throw new Error("no PlaySessionId");
|
throw new Error("no PlaySessionId");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let url: string | null | undefined;
|
||||||
|
|
||||||
if (mediaSource.SupportsDirectPlay || forceDirectPlay === true) {
|
if (mediaSource.SupportsDirectPlay || forceDirectPlay === true) {
|
||||||
if (item.MediaType === "Video") {
|
if (item.MediaType === "Video") {
|
||||||
console.log("Using direct stream for video!");
|
console.log("Using direct stream for video!");
|
||||||
return `${api.basePath}/Videos/${itemId}/stream.mp4?playSessionId=${sessionData.PlaySessionId}&mediaSourceId=${mediaSource.Id}&static=true&subtitleStreamIndex=${subtitleStreamIndex}&audioStreamIndex=${audioStreamIndex}&deviceId=${api.deviceInfo.id}&api_key=${api.accessToken}`;
|
url = `${api.basePath}/Videos/${itemId}/stream.mp4?playSessionId=${sessionData.PlaySessionId}&mediaSourceId=${mediaSource.Id}&static=true&subtitleStreamIndex=${subtitleStreamIndex}&audioStreamIndex=${audioStreamIndex}&deviceId=${api.deviceInfo.id}&api_key=${api.accessToken}`;
|
||||||
} else if (item.MediaType === "Audio") {
|
} else if (item.MediaType === "Audio") {
|
||||||
console.log("Using direct stream for audio!");
|
console.log("Using direct stream for audio!");
|
||||||
const searchParams = new URLSearchParams({
|
const searchParams = new URLSearchParams({
|
||||||
@@ -97,16 +99,16 @@ export const getStreamUrl = async ({
|
|||||||
EnableRedirection: "true",
|
EnableRedirection: "true",
|
||||||
EnableRemoteMedia: "false",
|
EnableRemoteMedia: "false",
|
||||||
});
|
});
|
||||||
return `${
|
url = `${
|
||||||
api.basePath
|
api.basePath
|
||||||
}/Audio/${itemId}/universal?${searchParams.toString()}`;
|
}/Audio/${itemId}/universal?${searchParams.toString()}`;
|
||||||
}
|
}
|
||||||
|
} else if (mediaSource.TranscodingUrl) {
|
||||||
|
console.log("Using transcoded stream!");
|
||||||
|
url = `${api.basePath}${mediaSource.TranscodingUrl}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediaSource.TranscodingUrl) {
|
if (!url) throw new Error("No url");
|
||||||
console.log("Using transcoded stream!");
|
|
||||||
return `${api.basePath}${mediaSource.TranscodingUrl}`;
|
return url;
|
||||||
} else {
|
|
||||||
throw new Error("No transcoding url");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user