feat:优化lx音源问题

This commit is contained in:
alger
2025-12-20 02:29:22 +08:00
parent a9fb487332
commit 5bcef29f10
10 changed files with 814 additions and 130 deletions
+110 -11
View File
@@ -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
}