指南

在 Java 中离线实现文字转语音

Java 标准库从未加入语音合成,因此项目只能选择 FreeTTS 或 MaryTTS 等老引擎(与神经网络声音相比听起来很机械),或者按字收费、能看到每段文字的云端 SDK。请注意:Supertonic 3 暂不支持中文,可朗读英语、日语、韩语等 31 种语言。

本指南介绍一种现代替代方案:把免费的 SuperClonica 引擎作为本地 HTTP 服务器运行,用 Java 11 及更新版本内置的 HttpClient 调用。在任何平台上都能获得自然的声音、留在你手里的 WAV 文件,且不按请求收费。

从 Java 发声的方式

引擎不在 JVM 内运行:你的 Java 代码像调用其他服务一样通过 HTTP 与它通信。

  • FreeTTS 和 MaryTTS:纯 Java、离线,但与神经网络声音相比显得机械。
  • 云端 SDK:声音自然,但需要账号、密钥、按字计费,文字还会存到对方服务器上。
  • SuperClonica:本地 HTTP 服务器,支持自然声音、角色声音和自定义声音,只要能运行 Docker 就能离线使用。
  • 它支持 31 种语言,暂不支持中文。

免费试听声音

写代码之前,先打开任意声音页面,输入 30 到 100 个字符的句子,选择语言并点击生成按钮。几秒后就能听到你的应用可以拥有的声音,无需注册。

启动语音服务器

有 NVIDIA 显卡时用 cuda 镜像会更快,但不是必需的。

  • 在任何 CPU 上启动服务器:docker run -d -p 8000:8000 -v superclonica-models:/models superclonica/superclonica:cpu。
  • 首次启动会把约 385 MB 的 Supertonic 3 模型下载到卷中;GET /health 可以告诉你何时就绪。
  • POST /synthesize 接收包含 text、voice、lang、seed 和 normalize 的 JSON,返回 16 位单声道 WAV。
  • voice 可以是 M1–M5、F1–F5 等标准名称,也可以是声音文件的 JSON 内容。

从 Java 调用

借助 java.net.http、java.net.URI 和 java.nio.file,在 Java 11 或更新版本中几行代码就能发出请求:var voice = Files.readString(Path.of("voice.json")); var json = "{\"text\": \"Hello from Java!\", \"lang\": \"en\", \"seed\": 7, \"voice\": " + voice + "}"; var request = HttpRequest.newBuilder(URI.create("http://localhost:8000/synthesize")).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(json)).build(); HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofFile(Path.of("hello.wav"))); 响应会直接写入 WAV 文件。使用标准声音时,发送 "voice": "F1" 代替文件内容。同样的文字、声音和 seed 总是得到同样的音频,所以请缓存重复短语的文件;大型项目中可以用 Jackson 等 JSON 库让请求更整洁。

上线前的好习惯

复用一个 HttpClient,并为请求设置超时。不要把 8000 端口原样暴露到互联网:设置 SUPERCLONICA_API_KEY 并以 Bearer 令牌发送,或把服务器放在私有网络中。如果同时到达的请求很多,用 SUPERCLONICA_LANES 运行更多模型副本,并在你的硬件上实测:在我们的测试中,短句在 RTX 5070 Ti 上耗时 0.12 秒,在四个 CPU 线程上耗时 0.43 秒。