mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 15:48:05 +00:00
feat: cache and download music
This commit is contained in:
@@ -202,6 +202,12 @@ export type Settings = {
|
||||
videoPlayerIOS: VideoPlayerIOS;
|
||||
// Appearance
|
||||
hideRemoteSessionButton: boolean;
|
||||
// Audio look-ahead caching
|
||||
audioLookaheadEnabled: boolean;
|
||||
audioLookaheadCount: number;
|
||||
audioMaxCacheSizeMB: number;
|
||||
// Music playback
|
||||
preferLocalAudio: boolean;
|
||||
};
|
||||
|
||||
export interface Lockable<T> {
|
||||
@@ -284,6 +290,12 @@ export const defaultValues: Settings = {
|
||||
videoPlayerIOS: VideoPlayerIOS.VLC,
|
||||
// Appearance
|
||||
hideRemoteSessionButton: false,
|
||||
// Audio look-ahead caching defaults
|
||||
audioLookaheadEnabled: true,
|
||||
audioLookaheadCount: 2,
|
||||
audioMaxCacheSizeMB: 100,
|
||||
// Music playback
|
||||
preferLocalAudio: true,
|
||||
};
|
||||
|
||||
const loadSettings = (): Partial<Settings> => {
|
||||
|
||||
68
utils/jellyfin/audio/getAudioStreamUrl.ts
Normal file
68
utils/jellyfin/audio/getAudioStreamUrl.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import type { Api } from "@jellyfin/sdk";
|
||||
import type { MediaSourceInfo } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import { getMediaInfoApi } from "@jellyfin/sdk/lib/utils/api";
|
||||
import native from "@/utils/profiles/native";
|
||||
|
||||
export interface AudioStreamResult {
|
||||
url: string;
|
||||
sessionId: string | null;
|
||||
mediaSource: MediaSourceInfo | null;
|
||||
isTranscoding: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the audio stream URL for a Jellyfin item
|
||||
* Handles both direct streaming and transcoding scenarios
|
||||
*/
|
||||
export const getAudioStreamUrl = async (
|
||||
api: Api,
|
||||
userId: string,
|
||||
itemId: string,
|
||||
): Promise<AudioStreamResult | null> => {
|
||||
try {
|
||||
const res = await getMediaInfoApi(api).getPlaybackInfo(
|
||||
{ itemId },
|
||||
{
|
||||
method: "POST",
|
||||
data: {
|
||||
userId,
|
||||
deviceProfile: native,
|
||||
startTimeTicks: 0,
|
||||
isPlayback: true,
|
||||
autoOpenLiveStream: true,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const sessionId = res.data.PlaySessionId || null;
|
||||
const mediaSource = res.data.MediaSources?.[0] || null;
|
||||
|
||||
if (mediaSource?.TranscodingUrl) {
|
||||
return {
|
||||
url: `${api.basePath}${mediaSource.TranscodingUrl}`,
|
||||
sessionId,
|
||||
mediaSource,
|
||||
isTranscoding: true,
|
||||
};
|
||||
}
|
||||
|
||||
// Direct stream
|
||||
const streamParams = new URLSearchParams({
|
||||
static: "true",
|
||||
container: mediaSource?.Container || "mp3",
|
||||
mediaSourceId: mediaSource?.Id || "",
|
||||
deviceId: api.deviceInfo.id,
|
||||
api_key: api.accessToken,
|
||||
userId,
|
||||
});
|
||||
|
||||
return {
|
||||
url: `${api.basePath}/Audio/${itemId}/stream?${streamParams.toString()}`,
|
||||
sessionId,
|
||||
mediaSource,
|
||||
isTranscoding: false,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user