|
|
@@ -178,12 +178,18 @@ export async function preloadNextSongIfNeeded(
|
|
|
const account = await manager.getWebDavAccountById(nextSong.webdav_account_id);
|
|
|
if (account) {
|
|
|
const itemId = nextSong.remote_rel_path || nextSong.id || nextSong.filePath;
|
|
|
+ const downloadUrl = await jellyfinApi.buildDownloadUrl(account, itemId);
|
|
|
+ const canDownload = await jellyfinApi.canAccessUrl(account, downloadUrl);
|
|
|
+ const staticStreamUrl = await jellyfinApi.buildStreamUrl(account, itemId, true);
|
|
|
+ const canStaticStream = await jellyfinApi.canAccessUrl(account, staticStreamUrl);
|
|
|
const streamUrl = await jellyfinApi.buildStreamUrl(account, itemId);
|
|
|
+ const cacheUrl = canDownload ? downloadUrl : (canStaticStream ? staticStreamUrl : streamUrl);
|
|
|
+ const cacheMode = canDownload ? 'download' : (canStaticStream ? 'static' : 'stream');
|
|
|
|
|
|
void (async () => {
|
|
|
try {
|
|
|
- console.info(TAG, `后台提前缓存Jellyfin下一首: ${itemId}`);
|
|
|
- await ensureJellyfinFileCached(account, itemId, streamUrl, nextSong.videoSize);
|
|
|
+ console.info(TAG, `后台提前缓存Jellyfin下一首(${cacheMode}): ${itemId}`);
|
|
|
+ await ensureJellyfinFileCached(account, itemId, cacheUrl, nextSong.videoSize);
|
|
|
console.info(TAG, `Jellyfin下一首提前缓存完成`);
|
|
|
} catch (error) {
|
|
|
const err = error as Error;
|
|
|
@@ -412,21 +418,28 @@ export async function setVideoUrlForSong(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 缓存不存在,获取流媒体URL并开始后台缓存
|
|
|
+ // 缓存不存在,优先尝试Download直链,失败则尝试Static流,再回退普通Stream
|
|
|
+ const downloadUrl = await jellyfinApi.buildDownloadUrl(account, jellyfinSongId);
|
|
|
+ const canDownload = await jellyfinApi.canAccessUrl(account, downloadUrl);
|
|
|
+ const staticStreamUrl = await jellyfinApi.buildStreamUrl(account, jellyfinSongId, true);
|
|
|
+ const canStaticStream = await jellyfinApi.canAccessUrl(account, staticStreamUrl);
|
|
|
const streamUrl = await jellyfinApi.buildStreamUrl(account, jellyfinSongId);
|
|
|
- void ServerLogUtil.info(TAG, `Jellyfin 流地址构建成功: ${streamUrl}`);
|
|
|
+ const cacheUrl = canDownload ? downloadUrl : (canStaticStream ? staticStreamUrl : streamUrl);
|
|
|
+ const cacheMode = canDownload ? 'Download' : (canStaticStream ? 'StaticStream' : 'Stream');
|
|
|
+ void ServerLogUtil.info(TAG, `Jellyfin 流地址构建成功(播放): ${streamUrl}`);
|
|
|
+ void ServerLogUtil.info(TAG, `Jellyfin 缓存地址选择(${cacheMode}): ${cacheUrl}`);
|
|
|
void ServerLogUtil.debug(TAG, `播放songId=${jellyfinSongId}, account=${ServerLogUtil.sanitizeAccount(account)}`);
|
|
|
|
|
|
// 立即返回流媒体URL,同时后台异步缓存
|
|
|
const sanitizedUrl = sanitizePlaybackUrl(streamUrl);
|
|
|
void (async () => {
|
|
|
try {
|
|
|
- Logger.info(TAG, `后台开始缓存Jellyfin文件: ${jellyfinSongId}`);
|
|
|
- void ServerLogUtil.info('JellyfinStream', `开始缓存: itemId=${jellyfinSongId}`);
|
|
|
+ Logger.info(TAG, `后台开始缓存Jellyfin文件(${cacheMode}): ${jellyfinSongId}`);
|
|
|
+ void ServerLogUtil.info('JellyfinStream', `开始缓存: itemId=${jellyfinSongId}, mode=${cacheMode}`);
|
|
|
const cachedFilePath = await ensureJellyfinFileCached(
|
|
|
account,
|
|
|
jellyfinSongId,
|
|
|
- streamUrl,
|
|
|
+ cacheUrl,
|
|
|
song.videoSize
|
|
|
);
|
|
|
Logger.info(TAG, `后台缓存完成: ${cachedFilePath}`);
|