| 895 | |
| 896 | for (const [bin, args] of ytdlpCommands) { |
| 897 | try { |
| 898 | const { stdout } = await execFileAsync(bin, args); |
| 899 | result.ytdlp = true; |
| 900 | // 检查版本并提示更新 |
| 901 | const versionMatch = stdout.match(/(\d{4}\.\d{2}\.\d{2})/); |
| 902 | if (versionMatch) { |
| 903 | const version = versionMatch[1]; |
| 904 | const versionDate = new Date(version.replace(/\./g, '-')); |
| 905 | const thirtyDaysAgo = new Date(); |
| 906 | thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); |
| 907 | if (versionDate < thirtyDaysAgo) { |
| 908 | console.log(`[Music] yt-dlp版本较旧 (${version}),建议更新: yt-dlp -U 或 pip install -U yt-dlp`); |
| 909 | } |
| 910 | } |
| 911 | console.log(`[Music] Found yt-dlp via: ${bin}`); |
| 912 | break; |
| 913 | } catch {} |
| 914 | } |
| 915 | |
| 916 | // Check FFmpeg |
| 917 | try { |
| 918 | await execFileAsync('ffmpeg', ['-version']); |
| 919 | result.ffmpeg = true; |
| 920 | // 静默检查,不输出日志 |
| 921 | } catch { |
| 922 | console.log("[Music] FFmpeg 未找到,音频处理功能受限"); |
| 923 | } |
| 924 | |
| 925 | return result; |
| 926 | } |
| 927 | |
| 928 | async search(query: string, minDurationSec?: number): Promise<string | null> { |
| 929 | try { |
| 930 | const cookie = await ConfigManager.get(CONFIG.KEYS.COOKIE); |
| 931 | const proxy = await ConfigManager.get(CONFIG.KEYS.PROXY); |
| 932 | const cookieBrowser = await ConfigManager.get(CONFIG.KEYS.COOKIE_BROWSER); |
| 933 | |
| 934 | // 使用AI识别歌手和歌曲名,构建最终搜索词 |
| 935 | let finalQuery = query; |
| 936 | try { |
| 937 | const apiKey = await ConfigManager.get(CONFIG.KEYS.API); |
| 938 | if (apiKey && apiKey.trim()) { |
| 939 | const baseUrl = await ConfigManager.get(CONFIG.KEYS.BASE_URL); |
| 940 | const gemini = new GeminiClient(apiKey, baseUrl); |