From 336f970e34e701deb1dec816d85c62592e71ac2f Mon Sep 17 00:00:00 2001 From: duzc2 Date: Mon, 9 Jun 2025 13:15:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=9F=B3=E4=B9=90=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E3=80=81=E4=B8=8B=E8=BD=BD=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- JavaScript/musicRequest.js | 62 +++++++++++++++++++++++++++----------- server.js | 29 +++++++++++++++--- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/JavaScript/musicRequest.js b/JavaScript/musicRequest.js index b362fb8..5e15325 100644 --- a/JavaScript/musicRequest.js +++ b/JavaScript/musicRequest.js @@ -1,3 +1,13 @@ + +function arrayBufferToBase64(buffer) { + let binary = ''; + const bytes = new Uint8Array(buffer); + const len = bytes.byteLength; + for (let i = 0; i < len; i++) { + binary += String.fromCharCode(bytes[i]); + } + return btoa(binary); // 将二进制字符串转为 Base64 +} async function pollTaskResult(getUrl, resultDiv, player, apiKey, maxTries = 60, interval = 3000) { for (let i = 0; i < maxTries; i++) { await new Promise(r => setTimeout(r, interval)); @@ -20,26 +30,44 @@ async function pollTaskResult(getUrl, resultDiv, player, apiKey, maxTries = 60, } const data = await res.json(); - + // 扩展状态判断,兼容不同API响应格式 const status = data.status?.toLowerCase() || data.task_status; - if (status === "succeeded" && data.output?.file_url ) { - resultDiv.innerHTML = "音乐生成成功!"; - player.src = data.output?.file_url ; - player.style.display = "block"; - player.load(); + if (status === "success" && data.output?.file_url) { + // resultDiv.innerHTML = "音乐生成成功!"; + // player.src = data.output?.file_url ; + // player.style.display = "block"; + // player.load(); + resultDiv.innerHTML = "正在下载音乐"; + fetch('download', { + method: "POST", + headers: { + "Content-Type": "application/json", + }, body: JSON.stringify({ url: data.output.file_url }) + }).then(async (data) => { + let buf = await data.arrayBuffer(); + console.log(buf); + resultDiv.innerHTML = "音乐生成成功!"; + player.src = 'data:audio/mpeg;base64,' + arrayBufferToBase64(buf); + player.style.display = "block"; + player.load(); + }).catch(e => { + player.style.display = "none"; + resultDiv.innerHTML = "加载失败"; + console.error(e); + }); return; - } else if (data.status === "failed") { + } else if (data.status === "failure") { resultDiv.innerHTML = "音乐生成失败:" + (data.message || "未知错误"); return; } else if (["waiting", "processing"].includes(data.status)) { - resultDiv.innerHTML = `生成中(${i+1}/${maxTries}次尝试)...`; + resultDiv.innerHTML = `生成中(${i + 1}/${maxTries}次尝试)...`; continue; // 明确继续轮询中间状态 } - + } catch (e) { // 优化错误处理 - console.error(`轮询失败 [尝试 ${i+1}]:`, e); + console.error(`轮询失败 [尝试 ${i + 1}]:`, e); if (i === maxTries - 1) { resultDiv.innerHTML = `最终失败: ${e.message}`; } @@ -88,7 +116,7 @@ async function generateMusic() { //▼▼▼ 修改请求地址为本地后端服务 ▼▼▼ const response = await fetch('http://localhost:3001/api/music/generate', { - //▲▲▲ 修改结束 ▲▲▲ + //▲▲▲ 修改结束 ▲▲▲ method: 'POST', headers: { "Content-Type": "application/json", @@ -116,15 +144,15 @@ async function generateMusic() { // 在generateMusic()函数中添加加载状态控制 document.getElementById('loadingIndicator').style.display = 'block'; document.getElementById('generateMusicBtn').disabled = true; - + // 在成功/失败时添加状态恢复 document.getElementById('loadingIndicator').style.display = 'none'; document.getElementById('generateMusicBtn').disabled = false; - + // 添加下载功能 - document.getElementById('downloadBtn').addEventListener('click', function() { + document.getElementById('downloadBtn').addEventListener('click', function () { const audioSrc = document.getElementById('musicPlayer').src; - if(audioSrc) { + if (audioSrc) { const a = document.createElement('a'); a.href = audioSrc; a.download = '生成的音乐.mp3'; @@ -132,9 +160,9 @@ async function generateMusic() { } }); pollTaskResult(data.urls.get, resultDiv, player, apiKey); - } else if (data.output?.file_url ) { + } else if (data.output?.file_url) { resultDiv.innerHTML = "音乐生成成功!"; - player.src = data.output?.file_url ; + player.src = data.output?.file_url; player.style.display = "block"; player.load(); } else { diff --git a/server.js b/server.js index 6236ae0..b072de3 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,6 @@ const express = require('express'); const cors = require('cors'); +const https = require('https'); const app = express(); app.use(cors()); @@ -19,7 +20,7 @@ app.use((req, res, next) => { // 响应日志中间件 app.use((req, res, next) => { const originalSend = res.send; - res.send = function(body) { + res.send = function (body) { console.log('\n===== 发送响应 ====='); console.log('状态码:', res.statusCode); console.log('响应体:', body); @@ -67,11 +68,11 @@ app.post('/api/music/generate', async (req, res) => { data = JSON.parse(text); } catch (parseError) { console.log('解析JSON失败:', parseError); - return res.status(500).json({ - error: `Gitee AI返回非JSON内容(状态码${response.status}): ${text}` + return res.status(500).json({ + error: `Gitee AI返回非JSON内容(状态码${response.status}): ${text}` }); } - + res.json(data); } catch (e) { console.error('请求Gitee AI出错:', e); @@ -79,6 +80,26 @@ app.post('/api/music/generate', async (req, res) => { } }); +app.post('/download', async (req, res) => { + if (!(req.body?.url)) { + res.sendStatus(400); + return; + } + https.get(req.body?.url, (fileres) => { + res.writeHead(fileres.statusCode, { + 'Content-Type': fileres.headers['content-type'] || 'audio/mpeg', + 'Content-Length': fileres.headers['content-length'], + 'Content-Disposition': 'inline; filename="music.mp3"', + }); + + // 管道转发音频流 + fileres.pipe(res); + }).on('error', (err) => { + console.error('远程请求错误:', err.message); + res.writeHead(500); + res.end('服务器内部错误'); + }); +}); app.listen(3001, () => { console.log('Node转发服务已启动,端口3001'); }); \ No newline at end of file -- Gitee