mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-23 15:47:23 +08:00
feat:优化lx音源问题
This commit is contained in:
@@ -13,6 +13,74 @@ import type { SongResult } from '@/types/music';
|
||||
import type { MusicParseResult } from './musicParser';
|
||||
import { CacheManager } from './musicParser';
|
||||
|
||||
/**
|
||||
* 解析可能是 API 端点的 URL,获取真实音频 URL
|
||||
* 一些音源脚本返回的是 API 端点,需要额外请求才能获取真实音频 URL
|
||||
*/
|
||||
const resolveAudioUrl = async (url: string): Promise<string> => {
|
||||
try {
|
||||
// 检查是否看起来像 API 端点(包含 /api/ 且有查询参数)
|
||||
const isApiEndpoint = url.includes('/api/') || (url.includes('?') && url.includes('type=url'));
|
||||
|
||||
if (!isApiEndpoint) {
|
||||
// 看起来像直接的音频 URL,直接返回
|
||||
return url;
|
||||
}
|
||||
|
||||
console.log('[LxMusicStrategy] 检测到 API 端点,尝试解析真实 URL:', url);
|
||||
|
||||
// 尝试获取真实 URL
|
||||
const response = await fetch(url, {
|
||||
method: 'HEAD',
|
||||
redirect: 'manual' // 不自动跟随重定向
|
||||
});
|
||||
|
||||
// 检查是否是重定向
|
||||
if (response.status >= 300 && response.status < 400) {
|
||||
const location = response.headers.get('Location');
|
||||
if (location) {
|
||||
console.log('[LxMusicStrategy] API 返回重定向 URL:', location);
|
||||
return location;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果 HEAD 请求没有重定向,尝试 GET 请求
|
||||
const getResponse = await fetch(url, {
|
||||
redirect: 'follow'
|
||||
});
|
||||
|
||||
// 检查 Content-Type
|
||||
const contentType = getResponse.headers.get('Content-Type') || '';
|
||||
|
||||
// 如果是音频类型,返回最终 URL
|
||||
if (contentType.includes('audio/') || contentType.includes('application/octet-stream')) {
|
||||
console.log('[LxMusicStrategy] 解析到音频 URL:', getResponse.url);
|
||||
return getResponse.url;
|
||||
}
|
||||
|
||||
// 如果是 JSON,尝试解析
|
||||
if (contentType.includes('application/json') || contentType.includes('text/json')) {
|
||||
const json = await getResponse.json();
|
||||
console.log('[LxMusicStrategy] API 返回 JSON:', json);
|
||||
|
||||
// 尝试从 JSON 中提取 URL(常见字段)
|
||||
const audioUrl = json.url || json.data?.url || json.audio_url || json.link || json.src;
|
||||
if (audioUrl && typeof audioUrl === 'string') {
|
||||
console.log('[LxMusicStrategy] 从 JSON 中提取音频 URL:', audioUrl);
|
||||
return audioUrl;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果都不是,返回原始 URL(可能直接可用)
|
||||
console.warn('[LxMusicStrategy] 无法解析 API 端点,返回原始 URL');
|
||||
return url;
|
||||
} catch (error) {
|
||||
console.error('[LxMusicStrategy] URL 解析失败:', error);
|
||||
// 解析失败时返回原始 URL
|
||||
return url;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 将 SongResult 转换为 LxMusicInfo 格式
|
||||
*/
|
||||
@@ -82,9 +150,17 @@ export class LxMusicStrategy {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否导入了脚本
|
||||
const script = settingsStore?.setData?.lxMusicScript;
|
||||
return Boolean(script);
|
||||
// 检查是否有激活的音源
|
||||
const activeLxApiId = settingsStore?.setData?.activeLxMusicApiId;
|
||||
if (!activeLxApiId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查音源列表中是否存在该 ID
|
||||
const lxMusicScripts = settingsStore?.setData?.lxMusicScripts || [];
|
||||
const activeScript = lxMusicScripts.find((script: any) => script.id === activeLxApiId);
|
||||
|
||||
return Boolean(activeScript && activeScript.script);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,18 +179,30 @@ export class LxMusicStrategy {
|
||||
|
||||
try {
|
||||
const settingsStore = useSettingsStore();
|
||||
const script = settingsStore.setData?.lxMusicScript;
|
||||
|
||||
if (!script) {
|
||||
console.log('[LxMusicStrategy] 未导入落雪音源脚本');
|
||||
// 获取激活的音源 ID
|
||||
const activeLxApiId = settingsStore.setData?.activeLxMusicApiId;
|
||||
if (!activeLxApiId) {
|
||||
console.log('[LxMusicStrategy] 未选择激活的落雪音源');
|
||||
return null;
|
||||
}
|
||||
|
||||
// 从音源列表中获取激活的脚本
|
||||
const lxMusicScripts = settingsStore.setData?.lxMusicScripts || [];
|
||||
const activeScript = lxMusicScripts.find((script: any) => script.id === activeLxApiId);
|
||||
|
||||
if (!activeScript || !activeScript.script) {
|
||||
console.log('[LxMusicStrategy] 未找到激活的落雪音源脚本');
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(`[LxMusicStrategy] 使用激活的音源: ${activeScript.name} (ID: ${activeScript.id})`);
|
||||
|
||||
// 获取或初始化执行器
|
||||
let runner = getLxMusicRunner();
|
||||
if (!runner || !runner.isInitialized()) {
|
||||
console.log('[LxMusicStrategy] 初始化落雪音源执行器...');
|
||||
runner = await initLxMusicRunner(script);
|
||||
runner = await initLxMusicRunner(activeScript.script);
|
||||
}
|
||||
|
||||
// 获取可用音源
|
||||
@@ -144,22 +232,33 @@ export class LxMusicStrategy {
|
||||
const lxQuality: LxQuality = QUALITY_TO_LX[quality || 'higher'] || '320k';
|
||||
|
||||
// 获取音乐 URL
|
||||
const url = await runner.getMusicUrl(bestSource, lxMusicInfo, lxQuality);
|
||||
const rawUrl = await runner.getMusicUrl(bestSource, lxMusicInfo, lxQuality);
|
||||
|
||||
if (!url) {
|
||||
if (!rawUrl) {
|
||||
console.log('[LxMusicStrategy] 获取 URL 失败');
|
||||
CacheManager.addFailedCache(id, this.name);
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log('[LxMusicStrategy] 解析成功:', url.substring(0, 50) + '...');
|
||||
console.log('[LxMusicStrategy] 脚本返回 URL:', rawUrl.substring(0, 80) + '...');
|
||||
|
||||
// 解析可能是 API 端点的 URL
|
||||
const resolvedUrl = await resolveAudioUrl(rawUrl);
|
||||
|
||||
if (!resolvedUrl) {
|
||||
console.log('[LxMusicStrategy] URL 解析失败');
|
||||
CacheManager.addFailedCache(id, this.name);
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log('[LxMusicStrategy] 最终音频 URL:', resolvedUrl.substring(0, 80) + '...');
|
||||
|
||||
return {
|
||||
data: {
|
||||
code: 200,
|
||||
message: 'success',
|
||||
data: {
|
||||
url,
|
||||
url: resolvedUrl,
|
||||
source: `lx-${bestSource}`,
|
||||
quality: lxQuality
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user