news 2026/4/21 12:35:53

<!doctype html>页面如何嵌入TTS?JavaScript调用Flask API实现网页合成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
<!doctype html>页面如何嵌入TTS?JavaScript调用Flask API实现网页合成

🎙️ 如何在 HTML 页面中嵌入 TTS?JavaScript 调用 Flask API 实现网页语音合成

📝 引言:让网页“开口说话”——中文多情感语音合成的落地需求

随着智能客服、在线教育、无障碍阅读等场景的普及,文本转语音(Text-to-Speech, TTS)已成为提升用户体验的重要技术手段。尤其在中文语境下,用户对语音的自然度、情感表达和响应速度提出了更高要求。

传统的TTS服务多依赖第三方云平台,存在数据隐私、网络延迟和成本控制等问题。而基于开源模型如ModelScope 的 Sambert-Hifigan,我们可以在本地部署高质量的中文多情感语音合成服务,并通过Flask 提供 Web API,前端使用标准 HTML + JavaScript 调用,实现完全自主可控的语音生成功能。

本文将带你从零开始,构建一个完整的网页端 TTS 系统: - 后端:基于 ModelScope 的 Sambert-Hifigan 模型封装为 Flask 接口 - 前端:纯 HTML5 页面通过 AJAX 调用 API 实现语音合成与播放 - 集成:解决依赖冲突、优化推理性能、支持长文本合成

最终效果:用户在浏览器输入中文文本 → 点击按钮 → 后台生成.wav音频 → 前端自动播放或提供下载。


🔧 技术架构解析:Sambert-Hifigan + Flask + JavaScript 三位一体

✅ 核心组件分工明确

| 组件 | 角色 | 技术栈 | |------|------|--------| |Sambert-Hifigan 模型| 语音合成引擎 | ModelScope 开源模型,支持中文多情感 | |Flask 服务| 后端接口层 | Python + Flask + PyTorch | |HTML/JS 页面| 用户交互界面 | HTML5 + JavaScript (Fetch API) + Bootstrap |

该架构具备以下优势: -前后端分离:便于维护与扩展 -可复用性强:API 可被多个前端调用(Web、App、小程序) -离线可用:无需联网即可完成语音合成 -情感丰富:支持喜怒哀乐等多种情绪风格(具体情感类型取决于模型训练配置)

💡 关键突破点
本项目已修复datasets(2.13.0)numpy(1.23.5)scipy(<1.13)的版本冲突问题,确保环境稳定运行,避免因依赖不兼容导致的崩溃。


🧩 后端实现:基于 ModelScope 的 Flask API 封装

我们将使用 ModelScope 提供的sambert-hifigan-tts-chinese模型,将其封装为一个 RESTful API 接口,接收文本并返回音频文件路径或二进制流。

1. 安装依赖(已优化版本兼容性)

pip install modelscope flask torch numpy==1.23.5 scipy==1.12.0 datasets==2.13.0

⚠️ 特别注意:scipy>=1.13会导致librosa加载失败,因此必须限制版本;numpy版本过高也会引发onnxruntime兼容问题。

2. 创建 Flask 应用:app.py

from flask import Flask, request, jsonify, send_file from modelscope.pipelines import pipeline from modelscope.utils.constant import Tasks import os import uuid app = Flask(__name__) OUTPUT_DIR = "outputs" os.makedirs(OUTPUT_DIR, exist_ok=True) # 初始化 TTS pipeline tts_pipeline = pipeline(task=Tasks.text_to_speech, model='damo/speech_sambert-hifigan_tts_zh-cn_16k') @app.route('/tts', methods=['POST']) def text_to_speech(): data = request.get_json() text = data.get('text', '').strip() if not text: return jsonify({'error': '请输入有效文本'}), 400 # 生成唯一文件名 filename = f"{uuid.uuid4().hex}.wav" output_path = os.path.join(OUTPUT_DIR, filename) try: # 执行语音合成 result = tts_pipeline(input=text, output_wav_path=output_path) return jsonify({ 'message': '语音合成成功', 'audio_url': f'/audio/{filename}' }) except Exception as e: return jsonify({'error': str(e)}), 500 @app.route('/audio/<filename>') def serve_audio(filename): path = os.path.join(OUTPUT_DIR, filename) if os.path.exists(path): return send_file(path, mimetype='audio/wav') return '音频未找到', 404 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=False)

3. API 接口说明

| 接口 | 方法 | 参数 | 返回值 | |------|------|------|--------| |/tts| POST | JSON:{ "text": "你好,欢迎使用语音合成服务" }|{ "audio_url": "/audio/xxx.wav" }| |/audio/<filename>| GET | 文件名 | WAV 音频流 |


💻 前端开发:HTML + JavaScript 实现网页嵌入式 TTS

接下来我们编写一个简洁美观的 HTML 页面,允许用户输入文本并触发语音合成。

1. 完整 HTML 页面代码:index.html

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>中文多情感语音合成</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <style> body { padding: 40px; background-color: #f8f9fa; } .container { max-width: 700px; margin: 0 auto; } .form-control { border-radius: 8px; } .btn-primary { border-radius: 8px; } .alert { border-radius: 8px; } </style> </head> <body> <div class="container"> <h2 class="mb-4 text-center">🎙️ 中文多情感语音合成</h2> <p class="text-muted text-center mb-4">基于 ModelScope Sambert-Hifigan 模型,支持长文本合成</p> <div class="card shadow-sm"> <div class="card-body"> <div class="mb-3"> <label for="textInput" class="form-label">输入中文文本:</label> <textarea id="textInput" class="form-control" rows="4" placeholder="请输入要合成的中文内容..."></textarea> </div> <button id="synthesizeBtn" class="btn btn-primary w-100">开始合成语音</button> <div id="loading" class="text-center mt-3 d-none"> <div class="spinner-border text-primary" role="status"> <span class="visually-hidden">加载中...</span> </div> <small class="text-muted ms-2">语音生成中,请稍候...</small> </div> <div id="result" class="mt-4 d-none"> <h6>🎧 听一听:</h6> <audio id="audioPlayer" controls class="w-100"></audio> <a id="downloadLink" class="btn btn-outline-secondary mt-2 w-100" download>⬇️ 下载音频文件</a> </div> <div id="errorAlert" class="alert alert-danger mt-3 d-none"></div> </div> </div> </div> <script> const textInput = document.getElementById('textInput'); const synthesizeBtn = document.getElementById('synthesizeBtn'); const loading = document.getElementById('loading'); const result = document.getElementById('result'); const audioPlayer = document.getElementById('audioPlayer'); const downloadLink = document.getElementById('downloadLink'); const errorAlert = document.getElementById('errorAlert'); // 清除状态 function clearStatus() { errorAlert.classList.add('d-none'); result.classList.add('d-none'); loading.classList.add('d-none'); } // 发起语音合成请求 async function callTTS() { const text = textInput.value.trim(); if (!text) { showError('请输入有效的中文文本!'); return; } clearStatus(); loading.classList.remove('d-none'); try { const response = await fetch('http://localhost:5000/tts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text }) }); const data = await response.json(); if (response.ok && data.audio_url) { const audioUrl = data.audio_url; audioPlayer.src = audioUrl; downloadLink.href = audioUrl; result.classList.remove('d-none'); } else { showError(data.error || '语音合成失败'); } } catch (err) { showError('无法连接到后端服务,请检查 Flask 是否正在运行。'); } finally { loading.classList.add('d-none'); } } // 显示错误信息 function showError(msg) { errorAlert.textContent = msg; errorAlert.classList.remove('d-none'); } // 绑定事件 synthesizeBtn.addEventListener('click', callTTS); textInput.addEventListener('keypress', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); callTTS(); } }); </script> </body> </html>

2. 功能亮点说明

  • 响应式设计:基于 Bootstrap 实现移动端友好布局
  • 一键合成:点击按钮或按回车(非 Shift+Enter)即可提交
  • 实时反馈:显示加载动画与错误提示
  • 播放+下载:支持<audio>控件播放,同时提供.wav下载链接
  • 跨域处理建议:若前后端分离部署,需在 Flask 中启用 CORS(可通过flask-cors插件)

🛠️ 部署与调试:常见问题与解决方案

❌ 问题1:ModuleNotFoundError: No module named 'modelscope'

原因:未正确安装 ModelScope 包
解决

pip install modelscope -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html

❌ 问题2:OSError: [WinError 126] 找不到指定模块(Windows)

原因:缺少 Visual C++ 运行库或 ONNX Runtime 不兼容
解决

pip uninstall onnxruntime pip install onnxruntime==1.15.1

❌ 问题3:音频无法播放 / 返回 404

检查项: - 输出目录outputs/是否存在且有写权限 -output_wav_path是否正确传入 - 访问/audio/filename.wav路径是否匹配send_file路由

✅ 性能优化建议

  1. 缓存机制:对相同文本做 MD5 哈希,避免重复合成
  2. 异步队列:使用 Celery 或 threading 处理长文本合成,防止阻塞主线程
  3. CPU 优化:关闭不必要的日志输出,减少中间变量拷贝
  4. 压缩音频:可选返回 MP3 格式(需集成pydub+ffmpeg

🔄 使用流程回顾:三步实现网页语音合成

  1. 启动后端服务bash python app.py

    服务监听http://localhost:5000

  2. 打开前端页面在浏览器中访问index.html文件(推荐使用本地服务器,如python -m http.server 8000

  3. 输入文本并合成

  4. 输入任意中文文本
  5. 点击【开始合成语音】
  6. 等待几秒后自动播放音频,支持下载保存


🎯 总结:打造自主可控的中文语音合成系统

本文完整展示了如何将ModelScope 的 Sambert-Hifigan 多情感中文语音合成模型集成到网页应用中,通过Flask 提供 API 接口,前端使用原生 JavaScript 调用,实现了无需第三方依赖的本地化 TTS 解决方案。

✅ 核心价值总结

  • 高保真语音:基于先进的端到端模型,语音自然流畅,支持多种情感表达
  • 环境稳定:已修复关键依赖版本冲突,开箱即用
  • 易于集成:标准 HTTP 接口,适用于 Web、App、IoT 等多种终端
  • 完全自主:数据不出内网,保障隐私安全

🚀 下一步建议

  1. 增加情感选择器:在前端添加下拉菜单,选择“开心”、“悲伤”、“严肃”等情感模式
  2. 支持SSML标记语言:实现语速、停顿、重音等精细控制
  3. 容器化部署:使用 Docker 打包整个服务,便于迁移与发布
  4. 加入身份认证:为 API 添加 Token 验证,防止滥用

📌 最终目标
构建一个企业级、可扩展、高可用的私有语音合成平台,替代昂贵的商业 API。


📚 附录:资源链接

  • ModelScope 模型主页:https://modelscope.cn/models/damo/speech_sambert-hifigan_tts_zh-cn_16k
  • Flask 官方文档:https://flask.palletsprojects.com/
  • Bootstrap CDN:https://getbootstrap.com/

现在就动手试试吧!让你的网页真正“开口说话”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 11:34:31

ZETORA在金融科技中的实际应用案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个金融科技应用&#xff0c;利用ZETORA分析市场数据并生成交易策略。应用应能实时获取股票、加密货币等市场数据&#xff0c;通过机器学习模型预测价格走势&#xff0c;并提…

作者头像 李华
网站建设 2026/4/18 4:44:26

Llama-Factory微调的量化技术:如何加速推理速度

Llama-Factory微调的量化技术&#xff1a;如何加速推理速度 作为一名性能工程师&#xff0c;当你完成大模型微调后&#xff0c;最头疼的问题可能就是推理速度太慢。这时候&#xff0c;量化技术就是你的救星。本文将手把手教你如何通过Llama-Factory实现模型量化&#xff0c;显著…

作者头像 李华
网站建设 2026/4/17 20:34:52

Mouse Without Borders vs 传统KVM:效率对比实测

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个Mouse Without Borders性能测试工具&#xff0c;功能包括&#xff1a;1.精确测量设备切换延迟&#xff1b;2.网络带宽占用监控&#xff1b;3.CPU/内存使用率记录&#xff…

作者头像 李华
网站建设 2026/4/18 3:53:54

AI如何智能优化你的网速测试工具开发

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个基于AI的在线网速测试工具&#xff0c;能够自动检测用户的网络延迟、下载速度和上传速度。要求工具能根据历史数据预测网络波动&#xff0c;并提供优化建议。前端使用Reac…

作者头像 李华
网站建设 2026/4/19 13:13:39

懒人必备!用LLaMA Factory一键微调ChatGLM3实战指南

懒人必备&#xff01;用LLaMA Factory一键微调ChatGLM3实战指南 作为一名在校大学生&#xff0c;我在课程项目中经常需要使用开源大模型。但很快发现一个问题&#xff1a;ChatGLM3等模型的默认回答风格与我的项目需求不符&#xff0c;而实验室的GPU资源又非常紧张。经过一番探索…

作者头像 李华
网站建设 2026/4/18 4:10:56

如何用AI分析ALIBABAPROTECT.EXE的行为模式

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个AI工具&#xff0c;用于监控和分析ALIBABAPROTECT.EXE的运行行为。功能包括&#xff1a;实时进程监控、CPU/内存占用分析、网络连接检测、行为模式学习&#xff08;如文件…

作者头像 李华