news 2026/4/16 20:04:46

<!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/16 12:28:30

Kimi类大模型缺语音?集成Sambert-Hifigan补全多模态交互闭环

Kimi类大模型缺语音&#xff1f;集成Sambert-Hifigan补全多模态交互闭环 &#x1f399;️ 为何需要为Kimi类大模型补全语音能力&#xff1f; 当前以Kimi为代表的大语言模型在文本理解与生成方面已达到行业领先水平&#xff0c;具备强大的上下文感知、长文本处理和逻辑推理能力。…

作者头像 李华
网站建设 2026/4/16 10:55:50

避坑大全:LLaMA Factory微调Mistral时的12个常见错误

避坑大全&#xff1a;LLaMA Factory微调Mistral时的12个常见错误 如果你正在使用LLaMA Factory框架对Mistral模型进行微调&#xff0c;可能会遇到各种环境配置和参数设置的问题。本文将总结12个最常见的错误及其解决方案&#xff0c;帮助你顺利完成模型微调任务。这类任务通常需…

作者头像 李华
网站建设 2026/4/16 14:50:18

HTML5语音合成新方案:前端+后端分离调用Sambert-Hifigan服务

HTML5语音合成新方案&#xff1a;前端后端分离调用Sambert-Hifigan服务 引言&#xff1a;中文多情感语音合成的现实需求 随着智能客服、有声阅读、虚拟主播等应用场景的普及&#xff0c;传统单一语调的语音合成已无法满足用户对自然度和情感表达的需求。尤其在中文场景下&#…

作者头像 李华
网站建设 2026/4/16 12:31:04

CRNN模型持续学习:适应新出现的字体样式

CRNN模型持续学习&#xff1a;适应新出现的字体样式 &#x1f4d6; 项目背景与OCR技术演进 光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;是计算机视觉领域中一项基础而关键的技术&#xff0c;其目标是从图像中自动提取可读文本。随着数字化进程加速…

作者头像 李华
网站建设 2026/4/16 11:06:24

HTOP vs 传统工具:系统监控效率提升300%的秘诀

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个性能对比测试工具&#xff0c;量化比较HTOP与top/htop/glances等工具在以下维度&#xff1a;1) 启动时间 2) 信息刷新延迟 3) 关键指标覆盖率 4) 交互操作步骤数。使用C实…

作者头像 李华