From e3a88acf9b149f35acf22a3d219c3eb981ec219d Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Sat, 1 Aug 2026 11:58:20 +0800 Subject: [PATCH] Revert "feat: migrate TTS generation to frontend to utilize local browser proxy" This reverts commit 5e600bb75d82e89509ef88fb2792e454f77ae5b1. --- CloudServer/public/generator.html | 88 ++++++++++++--------------- CloudServer/public/tempbroadcast.html | 59 ++---------------- CloudServer/server.js | 19 ------ 3 files changed, 45 insertions(+), 121 deletions(-) diff --git a/CloudServer/public/generator.html b/CloudServer/public/generator.html index 6ccd947..78f7aab 100644 --- a/CloudServer/public/generator.html +++ b/CloudServer/public/generator.html @@ -857,48 +857,14 @@ } async function _generateSingleTTS(text, reference_id) { - try { - // Client-side fetch to use local browser's proxy - const fishRes = await fetch('https://api.fish.audio/v1/tts', { - method: 'POST', - headers: { - 'Authorization': 'Bearer 233f3a9bcc204b20a1979d59d33cc649', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - text: text, - reference_id: reference_id, - model: TTS_MODEL, - format: "wav" - }) - }); - - if (!fishRes.ok) { - let msg = 'Fish Audio API Error'; - try { msg = await fishRes.text(); } catch(e){} - throw new Error(`[${fishRes.status}] ${msg}`); - } - - const audioBlob = await fishRes.blob(); - - // Upload the blob to the server as a temporary file - const formData = new FormData(); - formData.append('audio', audioBlob, 'temp.wav'); - - const uploadRes = await fetch('/api/tts/upload_temp', { - method: 'POST', - body: formData - }); - - const data = await uploadRes.json(); - if (!data.success) throw new Error(data.message); - return data; - } catch (err) { - if (err.name === 'TypeError' && err.message === 'Failed to fetch') { - throw new Error('网络请求失败或跨域被拦截(CORS)。如果启用了本地代理,请确保浏览器能够通过代理正常访问外网接口。'); - } - throw err; - } + const res = await fetch('/api/tts/generate', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ text, reference_id, model: TTS_MODEL }) + }); + const data = await res.json(); + if (!data.success) throw new Error(data.message); + return data; } async function _importSingleAudio(code, zhTemp, jaTemp) { @@ -1175,20 +1141,46 @@ status.textContent = "Generating Chinese audio..."; try { - // Generate Chinese via Client-Side Fetch - const dataZh = await _generateSingleTTS(zhText, ZH_REFERENCE_ID); + // Generate Chinese via Server-Side Proxy + const resZh = await fetch('/api/tts/generate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + text: zhText, + reference_id: ZH_REFERENCE_ID, + model: TTS_MODEL + }) + }); + + const dataZh = await resZh.json(); + if (!dataZh.success) throw new Error("ZH TTS failed: " + dataZh.message); status.textContent = "Generating Japanese audio..."; - // Generate Japanese via Client-Side Fetch - const dataJa = await _generateSingleTTS(jaText, JA_REFERENCE_ID); + // Generate Japanese via Server-Side Proxy + const resJa = await fetch('/api/tts/generate', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + text: jaText, + reference_id: JA_REFERENCE_ID, + model: TTS_MODEL + }) + }); + + const dataJa = await resJa.json(); + if (!dataJa.success) throw new Error("JA TTS failed: " + dataJa.message); // Success zhTempFile = dataZh.tempName; - jaTempFile = dataJa.tempName; + jaTempFile = dataJa.jaTempName || dataJa.enTempName || dataJa.tempName; document.getElementById('zh-audio').src = dataZh.url; - document.getElementById('en-audio').src = dataJa.url; + document.getElementById('en-audio').src = dataJa.jaUrl || dataJa.enUrl || dataJa.url; document.getElementById('preview-section').style.display = 'block'; status.textContent = "Generation complete!"; diff --git a/CloudServer/public/tempbroadcast.html b/CloudServer/public/tempbroadcast.html index 6883116..5347e58 100644 --- a/CloudServer/public/tempbroadcast.html +++ b/CloudServer/public/tempbroadcast.html @@ -322,51 +322,6 @@ .replaceAll("'", "'"); } - async function _generateTTSLocal(text, reference_id) { - try { - // Client-side fetch to use local browser's proxy - const fishRes = await fetch('https://api.fish.audio/v1/tts', { - method: 'POST', - headers: { - 'Authorization': 'Bearer 233f3a9bcc204b20a1979d59d33cc649', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - text: text, - reference_id: reference_id, - model: TTS_MODEL, - format: "wav" - }) - }); - - if (!fishRes.ok) { - let msg = 'Fish Audio API Error'; - try { msg = await fishRes.text(); } catch(e){} - throw new Error(`[${fishRes.status}] ${msg}`); - } - - const audioBlob = await fishRes.blob(); - - // Upload the blob to the server as a temporary file - const formData = new FormData(); - formData.append('audio', audioBlob, 'temp.wav'); - - const uploadRes = await fetch('/api/tts/upload_temp', { - method: 'POST', - body: formData - }); - - const data = await uploadRes.json(); - if (!data.success) throw new Error(data.message); - return data; - } catch (err) { - if (err.name === 'TypeError' && err.message === 'Failed to fetch') { - throw new Error('网络请求失败或跨域被拦截。如果启用了本地代理,请确保浏览器能访问外网接口。'); - } - throw err; - } - } - async function composeTempBroadcast() { const text = document.getElementById("tb_text").value.trim(); if (!text) { @@ -376,24 +331,20 @@ document.getElementById("btn_publish").disabled = true; document.getElementById("btn_compose").disabled = true; document.getElementById("build_badge").textContent = "合成中…"; - setStatus("合成临时广播中(1/2: 生成语音)…"); + setStatus("合成临时广播中…"); try { - // 1. 本地生成 TTS 并上传获得临时文件名 - const ttsData = await _generateTTSLocal(text, ZH_REFERENCE_ID); - - setStatus("合成临时广播中(2/2: 服务端混音)…"); - // 2. 告诉服务端进行混音合并 - const resp = await fetch("/api/temp-broadcast/build", { + const resp = await fetch("/api/temp-broadcast/compose", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ - contentTempName: ttsData.tempName, + text, + reference_id: ZH_REFERENCE_ID, + model: TTS_MODEL, prefixName: "lsts" }) }); const data = await resp.json(); if (!data || !data.success) throw new Error(data?.message || "合成失败"); - const preview = document.getElementById("preview_area"); preview.style.display = "block"; state.broadcastId = data.broadcastId; diff --git a/CloudServer/server.js b/CloudServer/server.js index 1941086..e5b47b0 100644 --- a/CloudServer/server.js +++ b/CloudServer/server.js @@ -2464,25 +2464,6 @@ async function generateTtsWavToTemp(text, reference_id, model = DEFAULT_TTS_MODE return { tempName, tempPath, url: `/uploads/${tempName}` }; } -app.post('/api/tts/upload_temp', upload.single('audio'), (req, res) => { - try { - if (!req.file) return res.status(400).json({ success: false, message: 'No audio file uploaded' }); - - const tempName = `temp_${Date.now()}_${Math.floor(Math.random() * 1000)}.wav`; - const tempPath = path.join(uploadDir, tempName); - - fs.renameSync(req.file.path, tempPath); - - res.json({ - success: true, - tempName: tempName, - url: `/uploads/${tempName}` - }); - } catch (e) { - res.status(500).json({ success: false, message: e.message }); - } -}); - app.post('/api/tts/generate', express.json(), async (req, res) => { const text = String(req.body?.text || '').trim(); const reference_id = String(req.body?.reference_id || '').trim();