如何在Coqui-AI TTS Server的JavaScript API调用中实现speaker_wav参数(XTTS语音克隆场景)
如何在Coqui-AI TTS Server的JavaScript API调用中实现speaker_wav参数(XTTS语音克隆场景)
看起来你在Coqui TTS Server上用XTTS做语音克隆时,卡在了API调用传参这块——终端命令行能用,但JS里试了各种方式都没搞定,还怕每次调用重新加载模型耗时间对吧?我来帮你理清楚问题出在哪,一步步解决:
一、先修正服务器端的代码问题
你自己修改了Flask路由,但有几个关键小错误,导致参数传了也没生效:
- 拼写错误:
langauge_name应该是language_name - XTTS的语音克隆参数是
speaker_wav,不是原代码里的style_wav(style_wav是给其他模型用的) - 要确保服务器能正确读取你传的音频文件路径
给你修正后的完整路由代码:
@app.route("/api/tts", methods=["GET", "POST"]) def tts(): with lock: # 从请求的查询参数、表单或请求头里捞参数,兼容多种传参方式 text = request.headers.get("text") or request.values.get("text", "") speaker_wav = request.headers.get("speaker_wav") or request.values.get("speaker_wav", "") language_idx = request.headers.get("language_idx") or request.values.get("language_idx", "en") print(f" > 待合成文本: {text}") print(f" > 参考语音路径: {speaker_wav}") print(f" > 语言标识: {language_idx}") # 注意XTTS的synthesizer.tts参数对应:用speaker_wav而不是style_wav wavs = synthesizer.tts( text=text, language_name=language_idx, speaker_wav=speaker_wav ) out = io.BytesIO() synthesizer.save_wav(wavs, out) return send_file(out, mimetype="audio/wav")
二、正确的JavaScript API调用方式
你之前试了各种传参方式没成,核心原因是要匹配服务器端的参数读取逻辑(request.values能读取FormData、URL编码表单和query string的参数),下面给你两种最靠谱的JS调用方案:
方案1:用FormData传参(推荐,后续要传文件内容也兼容)
async function synthesizeVoice() { const formData = new FormData(); formData.append('text', 'Testing, 1 2 3...'); // 重点:这里的路径必须是**服务器操作系统能直接访问的绝对路径**,不是客户端本地路径! // Windows路径记得用双反斜杠转义,或者换成正斜杠 formData.append('speaker_wav', 'C:\\Users\\perso\\Downloads\\Phonetic Sentence\\Converted\\speaker.wav'); formData.append('language_idx', 'en'); try { const response = await fetch('http://localhost:5002/api/tts', { method: 'POST', body: formData }); if (!response.ok) throw new Error(`API请求失败: ${response.status}`); // 处理返回的音频文件 const audioBlob = await response.blob(); const audioUrl = URL.createObjectURL(audioBlob); const audio = new Audio(audioUrl); audio.play(); } catch (error) { console.error('调用出错:', error); } }
方案2:用URL编码的表单数据
如果不想用FormData,也可以用传统的表单编码方式:
async function synthesizeVoice() { const params = new URLSearchParams(); params.append('text', 'Testing, 1 2 3...'); params.append('speaker_wav', 'C:\\Users\\perso\\Downloads\\Phonetic Sentence\\Converted\\speaker.wav'); params.append('language_idx', 'en'); try { const response = await fetch('http://localhost:5002/api/tts', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params }); if (!response.ok) throw new Error(`API请求失败: ${response.status}`); const audioBlob = await response.blob(); const audioUrl = URL.createObjectURL(audioBlob); const audio = new Audio(audioUrl); audio.play(); } catch (error) { console.error('调用出错:', error); } }
方案3:用GET请求(参数放URL查询串)
如果要兼容GET方式,记得对特殊路径字符做编码:
async function synthesizeVoice() { const customText = 'Testing, 1 2 3...'; // 对Windows路径的特殊字符做URL编码 const speakerWavPath = encodeURIComponent('C:\\Users\\perso\\Downloads\\Phonetic Sentence\\Converted\\speaker.wav'); const languageIdx = 'en'; const apiUrl = `http://localhost:5002/api/tts?text=${encodeURIComponent(customText)}&speaker_wav=${speakerWavPath}&language_idx=${languageIdx}`; try { const response = await fetch(apiUrl); if (!response.ok) throw new Error(`API请求失败: ${response.status}`); const audioBlob = await response.blob(); const audioUrl = URL.createObjectURL(audioBlob); const audio = new Audio(audioUrl); audio.play(); } catch (error) { console.error('调用出错:', error); } }
三、解决模型重复加载的问题
你担心的“每次调用重新加载模型”的问题,其实用TTS Server已经完美解决了!你的bat文件启动服务器时,已经一次性加载了XTTS v2模型,后续所有API调用都是复用这个已经加载好的模型实例,完全没有终端命令那种每次启动都要加载模型的等待时间——只要你的bat启动的服务器一直运行,就不用再担心这个问题。
确认你的bat文件没问题(你现在的写法是对的,再贴一遍方便你核对):
set TORCH_FORCE_NO_WEIGHTS_ONLY_LOAD=1 echo TORCH_FORCE_NO_WEIGHTS_ONLY_LOAD=%TORCH_FORCE_NO_WEIGHTS_ONLY_LOAD% "C:\Users\perso\miniconda3\envs\TTS\Scripts\tts-server.exe" --model_path "C:\Users\perso\AppData\Local\tts\tts_models--multilingual--multi-dataset--xtts_v2" --config_path "C:\Users\perso\AppData\Local\tts\tts_models--multilingual--multi-dataset--xtts_v2\config.json"
四、常见问题排查
- 服务器找不到音频文件:
speaker_wav必须是服务器能直接访问的绝对路径,不能是客户端本地路径!Windows路径记得用双反斜杠或者正斜杠,比如把C:\xxx改成C:/xxx或者C:\\xxx - 参数没传进去:看TTS Server的终端日志,确认打印出来的
speaker_wav、text、language_idx是你传的正确值 - 跨域问题:如果你的前端和TTS Server不在同一端口,要给Flask加跨域支持:安装
pip install flask-cors,然后在服务器代码开头加:from flask_cors import CORS app = Flask(__name__) CORS(app) # 生产环境可以限制允许的域名,比如CORS(app, resources={r"/api/*": {"origins": "http://your-frontend-domain.com"}}) - 模型不匹配:确保启动服务器时指定的是XTTS v2的模型路径,不是其他TTS模型
内容来源于stack exchange
相关产品推荐
相关产品推荐

