Ver Fonte

修改同域接口访问,避免跨域问题

sequoia00 há 1 mês atrás
pai
commit
b2e9683fd7
2 ficheiros alterados com 95 adições e 70 exclusões
  1. 26 0
      main_server.py
  2. 69 70
      static/web/viewer.html

+ 26 - 0
main_server.py

@@ -778,6 +778,32 @@ class TextToSpeechRequest(BaseModel):
     speed: float = 1.0
 
 
+@app.post("/generate")
+async def generate_proxy(request: TextToSpeechRequest):
+    user_input = request.user_input.strip()
+    if not user_input:
+        raise HTTPException(status_code=400, detail="输入文本为空")
+
+    async def stream_generator() -> AsyncGenerator[bytes, None]:
+        try:
+            async with aiohttp.ClientSession() as session:
+                async with session.post(
+                    "http://141.140.15.30:8028/generate",
+                    headers={"Content-Type": "application/json"},
+                    json={"text": user_input, "voice": request.voice, "speed": request.speed},
+                ) as response:
+                    if response.status != 200:
+                        raise HTTPException(status_code=500, detail="TTS API 请求失败")
+
+                    async for chunk in response.content.iter_any():
+                        yield chunk
+        except Exception as e:
+            logger.error(f"generate proxy error: {str(e)}")
+            raise HTTPException(status_code=500, detail=str(e))
+
+    return StreamingResponse(stream_generator(), media_type="application/x-ndjson")
+
+
 @app.post("/text-to-speech/")
 async def text_to_speech(request: TextToSpeechRequest):
     user_input = request.user_input.strip()

+ 69 - 70
static/web/viewer.html

@@ -1812,74 +1812,73 @@
                     queue.splice(index, 0, chunk);
                 }
 
-                // 开始转换(发送完整文本,让TTS API处理分割)
-                async function startConversion(fullText) {
-                    const loadingIndicator = document.getElementById('loading-indicator');
-                    try {
-                        stopCurrentPlayback(false);
-                        const response = await fetch('http://141.140.15.30:8028/generate', {
-                            method: 'POST',
-                            headers: { 'Content-Type': 'application/json' },
-                            body: JSON.stringify({ text: fullText, voice: "af_heart", speed: 1.0 })
-                        });
-
-                        if (!response.ok) throw new Error(`服务器错误: ${response.status}`);
-
-                        const reader = response.body.getReader();
-                        activeStreamReader = reader;
-                        const decoder = new TextDecoder();
-                        let buffer = '';
-                        const audioQueue = [];
-                        let expectedIndex = 0;
-
-                        const playController = new AbortController();
-                        activePlayController = playController;
-                        const playPromise = playAudioSequentially(audioQueue, playController.signal);
-
-                        while (true) {
-                            const { done, value } = await reader.read();
-                            if (done) break;
-
-                            buffer += decoder.decode(value, { stream: true });
-                            const lines = buffer.split('\n');
-                            buffer = lines.pop() || '';
-
-                            for (const line of lines) {
-                                if (!line.trim()) continue;
-                                const data = parseStreamData(line);
-                                if (data.error) {
-                                    throw new Error(data.error);
-                                }
-                                if (data.audio) {
-                                    insertInOrder(audioQueue, createAudioChunk(data));
-                                }
-                            }
-                        }
-
-                        // 处理剩余缓冲
-                        if (buffer.trim()) {
-                            const data = parseStreamData(buffer.trim());
-                            if (data.audio) {
-                                insertInOrder(audioQueue, createAudioChunk(data));
-                            }
-                        }
-
-                        audioQueue.push(null); // 结束信号
-                        await playPromise;
-                        activePlayController = null;
-                        activeStreamReader = null;
-
-                    } catch (error) {
-                        activePlayController = null;
-                        activeStreamReader = null;
-                        if (error.name === 'AbortError') {
-                            return;
-                        }
-                        console.error(error);
-                        loadingIndicator.textContent = `错误: ${error.message}`;
-                        loadingIndicator.style.display = 'block';
-                    }
-                }
+                // 开始转换(同域代理,保持流式逐句播放)
+                async function startConversion(fullText) {
+                    const loadingIndicator = document.getElementById('loading-indicator');
+                    try {
+                        stopCurrentPlayback(false);
+                        const response = await fetch('/generate', {
+                            method: 'POST',
+                            headers: { 'Content-Type': 'application/json' },
+                            body: JSON.stringify({ user_input: fullText, voice: "af_heart", speed: 1.0 })
+                        });
+
+                        if (!response.ok) throw new Error(`服务器错误: ${response.status}`);
+
+                        const reader = response.body.getReader();
+                        activeStreamReader = reader;
+                        const decoder = new TextDecoder();
+                        let buffer = '';
+                        const audioQueue = [];
+                        let expectedIndex = 0;
+
+                        const playController = new AbortController();
+                        activePlayController = playController;
+                        const playPromise = playAudioSequentially(audioQueue, playController.signal);
+
+                        while (true) {
+                            const { done, value } = await reader.read();
+                            if (done) break;
+
+                            buffer += decoder.decode(value, { stream: true });
+                            const lines = buffer.split('\n');
+                            buffer = lines.pop() || '';
+
+                            for (const line of lines) {
+                                if (!line.trim()) continue;
+                                const data = parseStreamData(line);
+                                if (data.error) {
+                                    throw new Error(data.error);
+                                }
+                                if (data.audio) {
+                                    insertInOrder(audioQueue, createAudioChunk(data));
+                                }
+                            }
+                        }
+
+                        if (buffer.trim()) {
+                            const data = parseStreamData(buffer.trim());
+                            if (data.audio) {
+                                insertInOrder(audioQueue, createAudioChunk(data));
+                            }
+                        }
+
+                        audioQueue.push(null);
+                        await playPromise;
+                        activePlayController = null;
+                        activeStreamReader = null;
+
+                    } catch (error) {
+                        activePlayController = null;
+                        activeStreamReader = null;
+                        if (error.name === 'AbortError') {
+                            return;
+                        }
+                        console.error(error);
+                        loadingIndicator.textContent = `错误: ${error.message}`;
+                        loadingIndicator.style.display = 'block';
+                    }
+                }
 
                 // 监听文本选择
                 document.addEventListener('DOMContentLoaded', () => {
@@ -1900,7 +1899,7 @@
                             loadingIndicator.textContent = '正在转换选中文本...';
                             loadingIndicator.style.display = 'block';
 
-                            await startConversion(selectedText);
+                            await startConversion(selectedText);
                         } catch (error) {
                             console.error(error);
                             loadingIndicator.textContent = `错误: ${error.message}`;
@@ -1944,7 +1943,7 @@
                             return;
                         }
 
-                        await startConversion(fullText);
+                        await startConversion(fullText);
                     } catch (error) {
                         console.error(error);
                         loadingIndicator.textContent = `错误: ${error.message}`;