背景介绍
在我们的项目 「景音随行」 中,需要为每个景点提供自动语音讲解功能。即将景点的文字描述即时转成自然流畅的语音,让游客能够沉浸式体验景区文化。
项目背景有几个关键限制条件:
服务器资源有限(1核2G)
支持多语种:简体中文、繁体中文、英文
语音质量高:尽量自然,不要太电子感
调用简洁:Java Web 系统集成
延迟低:适合同步播放或快速生成音频文件
开源 TTS 框架调研与对比
我们初步调研了以下几个主流开源 TTS 项目:
最终选择:edge-tts
经过测试,edge-tts
在 音质、速度、资源占用 之间达到了非常好的平衡:
📦 体积小:仅依赖 Python + edge-tts 库
🎤 音质好:微软官方 Neural 系列音色
🌍 多语言支持:中文、英文、甚至更多小语种
🚀 启动快:冷启动 < 1s
💻 低资源运行:无 GPU 要求,1G 内存也能跑
技术实现方案
我们的整体思路是:
Java Web 项目调用Python脚本,动态生成语音 MP3 二进制流,直接返回前端播放。
整体架构图:
[Java Controller]
↓
[PythonTTSBridge (ProcessBuilder)]
↓
[Python 脚本 (edge-tts)]
↓
[MP3字节流输出]
↓
[浏览器或小程序播放]
核心代码实现
1. Java 调用 Python:PythonTTSBridge.java
package com.xxx.integration;
import java.io.*;
import java.util.concurrent.*;
public class PythonTTSBridge {
private static final ExecutorService pool = Executors.newFixedThreadPool(10);
private static final String PYTHON_PATH = "/usr/bin/python3";
private static final String SCRIPT_PATH = "/opt/soundJourney/tts/tts.py";
public static Future<byte[]> generateSpeech(String text, String langCode) {
return pool.submit(() -> {
ProcessBuilder pb = new ProcessBuilder(
PYTHON_PATH, SCRIPT_PATH, text, langCode
);
Process process = pb.start();
try (InputStream in = process.getInputStream()) {
byte[] audio = in.readAllBytes();
process.waitFor(10, TimeUnit.SECONDS);
return audio;
} catch (Exception e) {
throw new RuntimeException("TTS生成失败", e);
} finally {
process.destroy();
}
});
}
}
2. Controller 层暴露接口
@RestController
@RequestMapping("/api/tts")
public class TTSController {
@PostMapping(produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<byte[]> tts(@RequestParam String text, @RequestParam String langCode) throws Exception {
byte[] mp3Bytes = PythonTTSBridge.generateSpeech(text, langCode).get(12, TimeUnit.SECONDS);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"speech.mp3\"")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(mp3Bytes);
}
}
3. Python TTS 脚本:/opt/soundJourney/tts/tts.py
#!/usr/bin/env python3
import sys
import asyncio
import edge_tts
import tempfile
import os
def log(*args):
print("[TTS LOG]", *args, file=sys.stderr)
if len(sys.argv) != 3:
log("参数错误,应为:文本 langCode")
sys.exit(1)
text, lang_code = sys.argv[1], sys.argv[2]
voice_map = {
"1": "zh-CN-XiaoxiaoNeural",
"2": "zh-TW-HsiaoChenNeural",
"3": "en-US-JennyNeural",
}
voice = voice_map.get(lang_code)
if not voice:
log(f"不支持的语言类型: {lang_code}")
sys.exit(1)
async def synthesize():
try:
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
tmp_path = tmp_file.name
communicate = edge_tts.Communicate(text=text, voice=voice)
await communicate.save(tmp_path)
with open(tmp_path, "rb") as f:
sys.stdout.buffer.write(f.read())
sys.stdout.flush()
os.remove(tmp_path)
except Exception as e:
log("语音合成失败:", str(e))
sys.exit(1)
asyncio.run(synthesize())
现有成果
支持简体中文、繁体中文、英文三种语言
端到端延迟稳定在 1-2秒 内
服务器资源占用率低于 15% CPU / 200MB内存
支持高并发请求,后台线程池统一管理
下一步优化建议
最后总结
edge-tts
给了我们一个快速、轻量、易集成的文本转语音方案,尤其适合资源受限的场景。
整个方案没有引入任何重量级模型,不需要GPU,却依然可以做到效果自然、体验良好。
希望这篇文章能帮到同样想在项目中引入 TTS 功能的开发者们!