feat(media_fetcher): 添加TuneHub优先下载策略并增强日志记录
为媒体获取服务添加TuneHub优先下载策略,当URL匹配时先尝试通过TuneHub下载,失败后再回退到media-get 同时增加详细的日志记录,包括URL解析、下载过程和错误处理
This commit is contained in:
@@ -38,18 +38,23 @@ function parsePageUrlParams(url) {
|
||||
if (!url) {
|
||||
return null;
|
||||
}
|
||||
// 支持网易云音乐PC版和手机版
|
||||
if (url.indexOf('music.163.com') >= 0 || url.indexOf('m.music.163.com') >= 0) {
|
||||
const match = url.match(/id=(\d+)/);
|
||||
if (match && match[1]) {
|
||||
logger.info(`[parsePageUrlParams] Parsed Netease URL: ${url} -> netease:${match[1]}`);
|
||||
return { source: 'netease', id: match[1] };
|
||||
}
|
||||
}
|
||||
// 支持QQ音乐
|
||||
if (url.indexOf('y.qq.com') >= 0) {
|
||||
const match = url.match(/songDetail\/([A-Za-z0-9]+)/);
|
||||
if (match && match[1]) {
|
||||
logger.info(`[parsePageUrlParams] Parsed QQ URL: ${url} -> qq:${match[1]}`);
|
||||
return { source: 'qq', id: match[1] };
|
||||
}
|
||||
}
|
||||
logger.info(`[parsePageUrlParams] URL not recognized: ${url}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -115,27 +120,59 @@ async function fetchWithUrl(url, {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try TuneHub first for supported URLs
|
||||
const params = parseTunehubParams(url) || parsePageUrlParams(url);
|
||||
if (params) {
|
||||
logger.info(`[fetchWithUrl] Trying TuneHub first for ${params.source}:${params.id}`);
|
||||
try {
|
||||
const downloadUrl = buildSongUrl(params.source, params.id);
|
||||
if (downloadUrl) {
|
||||
logger.info(`[fetchWithUrl] TuneHub download URL: ${downloadUrl}`);
|
||||
const downloadPath = `${fileBasePath}/${songName ? songName : requestHash}.mp3`;
|
||||
const isSucceed = await downloadFile(downloadUrl, downloadPath);
|
||||
if (isSucceed && fs.existsSync(downloadPath)) {
|
||||
logger.info(`[fetchWithUrl] Download success via TuneHub: ${downloadPath}`);
|
||||
return downloadPath;
|
||||
}
|
||||
logger.warn(`[fetchWithUrl] TuneHub download failed, will try media-get as fallback`);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`[fetchWithUrl] TuneHub download failed for ${params.source}:${params.id}`, error);
|
||||
}
|
||||
} else {
|
||||
logger.info(`[fetchWithUrl] URL not recognized as TuneHub-supported format, using media-get`);
|
||||
}
|
||||
|
||||
// Fallback to media-get
|
||||
addMediaTag = false; // todo: 等到 media-get fix 偶现的 添加 addMediaTag 后 panic 的问题,再移除这行代码
|
||||
const downloadPath = `${fileBasePath}/${songName ? songName : requestHash}.mp3`;
|
||||
logger.info(`start parse and download from ${url}`);
|
||||
logger.info(`[fetchWithUrl] Falling back to media-get for ${url} (may be unstable)`);
|
||||
|
||||
let args = ['-u', `"${url}"`, '--out', `${downloadPath}`, '-t', 'audio', `${addMediaTag ? '--addMediaTag' : ''}`];
|
||||
|
||||
logger.info(`${getBinPath()} ${args.join(' ')}`);
|
||||
|
||||
try {
|
||||
const {code, message} = await cmd(getBinPath(), args);
|
||||
logger.info('-------')
|
||||
logger.info(code);
|
||||
logger.info(message);
|
||||
logger.info('-------')
|
||||
if (code != 0) {
|
||||
logger.error(`[fetchWithUrl] media-get failed with code ${code}: ${message}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(downloadPath)) {
|
||||
logger.error(`[fetchWithUrl] media-get succeeded but file not found: ${downloadPath}`);
|
||||
return false;
|
||||
}
|
||||
logger.info(`[fetchWithUrl] media-get download success: ${downloadPath}`);
|
||||
return downloadPath;
|
||||
} catch (error) {
|
||||
logger.error(`[fetchWithUrl] media-get crashed or timed out for ${url}`, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function getMetaWithUrl(url) {
|
||||
@@ -143,14 +180,22 @@ async function getMetaWithUrl(url) {
|
||||
|
||||
const params = parseTunehubParams(url) || parsePageUrlParams(url);
|
||||
if (params) {
|
||||
logger.info(`[getMetaWithUrl] Trying TuneHub first for ${params.source}:${params.id}`);
|
||||
const tunehubInfo = await getSongInfo(params.source, params.id);
|
||||
if (tunehubInfo) {
|
||||
logger.info(`[getMetaWithUrl] TuneHub success for ${params.source}:${params.id}`);
|
||||
return buildMetaFromTunehub(params.source, tunehubInfo, url, params.id);
|
||||
}
|
||||
logger.warn(`[getMetaWithUrl] TuneHub failed for ${params.source}:${params.id}, will try media-get as fallback`);
|
||||
} else {
|
||||
logger.info(`[getMetaWithUrl] URL not recognized as TuneHub-supported format, trying media-get`);
|
||||
}
|
||||
|
||||
// Fallback to media-get only if TuneHub fails or URL format not supported
|
||||
logger.warn(`[getMetaWithUrl] Falling back to media-get for ${url} (may be unstable)`);
|
||||
let args = ['-u', `"${url}"`, '-m', '--infoFormat=json', '-l=silence'];
|
||||
|
||||
try {
|
||||
const {code, message} = await cmd(getBinPath(), args);
|
||||
logger.info('-------')
|
||||
logger.info(code);
|
||||
@@ -165,7 +210,7 @@ async function getMetaWithUrl(url) {
|
||||
try {
|
||||
meta = JSON.parse(message);
|
||||
} catch (e) {
|
||||
logger.error(e, message)
|
||||
logger.error(`[getMetaWithUrl] Failed to parse media-get response: ${e}`, message)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -183,6 +228,10 @@ async function getMetaWithUrl(url) {
|
||||
resourceForbidden: meta.resource_forbidden,
|
||||
source: meta.source
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`[getMetaWithUrl] media-get crashed or timed out for ${url}`, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function searchSongFromAllPlatform({
|
||||
|
||||
Reference in New Issue
Block a user