feat(同步任务): 增加从URL提取songId的功能并优化媒体获取重试机制
在sync_jobs.js中添加从网易云音乐URL提取songId的逻辑,避免冗余匹配 在media_fetcher/index.js中增加重试机制和超时控制,提高媒体获取的稳定性
This commit is contained in:
@@ -92,6 +92,20 @@ async function createJob(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
// 如果前端没有传递 songId,尝试从 URL 中提取
|
||||
if (!songId) {
|
||||
logger.info(`[sync_jobs] No songId provided, trying to extract from URL: ${url}`);
|
||||
// 支持网易云音乐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]) {
|
||||
songId = match[1];
|
||||
logger.info(`[sync_jobs] Extracted netease songId from URL: ${songId}`);
|
||||
}
|
||||
}
|
||||
// TODO: 支持其他音乐平台 (QQ音乐等)
|
||||
}
|
||||
|
||||
if (songId) {
|
||||
// 直接传递songId给后续处理,避免冗余的网易云匹配
|
||||
// 如果后续需要,可以根据songId进行精确匹配
|
||||
|
||||
@@ -212,45 +212,63 @@ async function getMetaWithUrl(url) {
|
||||
|
||||
// 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);
|
||||
// logger.info(message);
|
||||
logger.info('-------')
|
||||
if (code != 0) {
|
||||
logger.error(`getMetaWithUrl failed with ${url}, err: ${message}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
let meta;
|
||||
// 增加重试机制和超时控制
|
||||
const maxRetries = 2;
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
meta = JSON.parse(message);
|
||||
} catch (e) {
|
||||
logger.error(`[getMetaWithUrl] Failed to parse media-get response: ${e}`, message)
|
||||
return false;
|
||||
}
|
||||
logger.info(`[getMetaWithUrl] Attempt ${attempt}/${maxRetries} for ${url}`);
|
||||
const {code, message} = await cmd(getBinPath(), ['-u', `"${url}"`, '-m', '--infoFormat=json', '-l=silence', '--timeout=30']);
|
||||
logger.info('-------')
|
||||
logger.info(code);
|
||||
// logger.info(message);
|
||||
logger.info('-------')
|
||||
if (code != 0) {
|
||||
logger.error(`getMetaWithUrl failed with ${url}, err: ${message}`);
|
||||
if (attempt === maxRetries) {
|
||||
return false;
|
||||
}
|
||||
// 等待一段时间后重试
|
||||
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
|
||||
continue;
|
||||
}
|
||||
|
||||
return {
|
||||
songName: meta.title,
|
||||
artist: meta.artist,
|
||||
album: meta.album,
|
||||
duration: meta.duration,
|
||||
coverUrl: meta.cover_url,
|
||||
publicTime: meta.public_time,
|
||||
isTrial: meta.is_trial,
|
||||
resourceType: meta.resource_type,
|
||||
audios: meta.audios,
|
||||
fromMusicPlatform: meta.from_music_platform,
|
||||
resourceForbidden: meta.resource_forbidden,
|
||||
source: meta.source
|
||||
let meta;
|
||||
try {
|
||||
meta = JSON.parse(message);
|
||||
} catch (e) {
|
||||
logger.error(`[getMetaWithUrl] Failed to parse media-get response: ${e}`, message);
|
||||
if (attempt === maxRetries) {
|
||||
return false;
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
|
||||
continue;
|
||||
}
|
||||
|
||||
return {
|
||||
songName: meta.title,
|
||||
artist: meta.artist,
|
||||
album: meta.album,
|
||||
duration: meta.duration,
|
||||
coverUrl: meta.cover_url,
|
||||
publicTime: meta.public_time,
|
||||
isTrial: meta.is_trial,
|
||||
resourceType: meta.resource_type,
|
||||
audios: meta.audios,
|
||||
fromMusicPlatform: meta.from_music_platform,
|
||||
resourceForbidden: meta.resource_forbidden,
|
||||
source: meta.source
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`[getMetaWithUrl] media-get crashed or timed out for ${url}`, error);
|
||||
if (attempt === maxRetries) {
|
||||
return false;
|
||||
}
|
||||
// 等待一段时间后重试
|
||||
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`[getMetaWithUrl] media-get crashed or timed out for ${url}`, error);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async function searchSongFromAllPlatform({
|
||||
|
||||
Reference in New Issue
Block a user