| 187 | return finalFile; |
| 188 | } catch (e: any) { |
| 189 | console.error("生成音乐失败:", e.message || e); |
| 190 | return null; |
| 191 | } finally { |
| 192 | try { await fs.unlink(rawFile); } catch {} |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | // 语音 |
| 197 | async function generateSpeechSimple( |
| 198 | text: string, referenceId: string, apiKey: string |
| 199 | ): Promise<{ oggFile: string; mp3File: string } | null> { |
| 200 | const api_url = "https://api.fish.audio/v1/tts"; |
| 201 | const unique = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`; |
| 202 | const mp3File = path.join(cacheDir, `tts-${unique}.mp3`); |
| 203 | const oggFile = path.join(cacheDir, `tts-${unique}.ogg`); |
| 204 | try { |
| 205 | const res = await axios.post(api_url, { text, reference_id: referenceId }, { |
| 206 | headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" }, |
| 207 | responseType: "arraybuffer", |
| 208 | }); |
| 209 | await fs.writeFile(mp3File, res.data); |
| 210 | await execFileAsync("ffmpeg", ["-y", "-i", mp3File, "-c:a", "libopus", "-b:a", "64k", "-vbr", "on", oggFile], { shell: false }); |