Voices能够让Java应用程序快速实现文本到语音转换
来源: InfoQ - 后端
Voices是一个开源的文本转语音项目,专为运行在Java 17或更新版本的应用程序设计的。这个库不需要外部API或手动安装的软件,可以根据字典或OpenVoice"为不同语言生成音频文件。
Henry Coles"是Voices和Pitest的创建者以及Arcmutate"的变更测试负责人,他在2025年9月的Bluesky"上介绍了Voices,其最新版本在2025年10月下旬发布,版本号为0.0.8。
Voices使用ONNX Runtime",这是一个跨平台的AI引擎,可以加速训练和推理,支持来自各种深度学习框架的模型,如TensorFlow和PyTorch。该运行时在可能的情况下会利用硬件加速器,并支持各种硬件和操作系统配置。
这里演示的例子需要多个库,以下的POM文件配置可以与Maven一起使用:
0.0.8
chorus
org.pitest.voices
0.0.8
alba
org.pitest.voices
0.0.8
en_uk
org.pitest.voices
1.22.0
onnxruntime
com.microsoft.onnxruntime
其他的构建工具,如Gradle,也可以用来运行这里展示的样例。
可以通过替换上述依赖项来使用en_us字典,以取代en_uk字典。onnxruntime可以被onnxruntime_gpu替换以进行GPU加速。Chorus类可以用来管理语音模型和管理资源。建议在应用程序中使用单个Chorus实例,因为加载模型的成本较高。以下示例演示了将英文文本转换为InfoQ_English音频文件的过程:
ChorusConfig config = chorusConfig(EnUkDictionary.en_uk());
try (Chorus chorus = new Chorus(config)) {
Voice alba = chorus.voice(Alba.albaMedium());
Audio audio = alba.say("This is the InfoQ article about the Voices library");
Path path = Paths.get("InfoQ_English");
audio.save(path);
}
前面的示例使用了在构建时通过Maven依赖项检索到的模型。其他模型也可以在运行时通过以下Maven依赖项检索进来:
0.0.8
model-downloader
org.pitest.voices
现在,可以通过以下类的工厂方法使用模型:
org.pitest.voices.download.Models
org.pitest.voices.download.UsModels
org.pitest.voices.download.NonEnglishModels
以下示例使用NonEnglishModels类中的荷兰nlNLRonnie模型将荷兰文的文本转换为荷兰语音频文件:
Model nlModel = NonEnglishModels.nlNLRonnie();
ChorusConfig config = chorusConfig(EnUkDictionary.en_uk());
try (Chorus chorus = new Chorus(config)) {
Voice alba = chorus.voice(nlModel);
Audio audio = alba.say("Dit is een Nederlandse tekst Scheveningen");
Path path = Paths.get("Dutch");
audio.save(path);
}
另外,还可以使用OpenVoice"来改善生成的语音,而不需要字典。然而,它需要更多的计算能力,并且模型大小为50MB,明显大于3MB的字典文件。以下依赖项启用了Maven对OpenVoice的支持:
0.0.8
openvoice-phonemizer
org.pitest.voices
声明依赖项后,可以使用OpenVoiceSupplier模型:
ChorusConfig config = chorusConfig(Dictionaries.empty()).withModel(new OpenVoiceSupplier());
try (Chorus chorus = new Chorus(config)) {
Voice alba = chorus.voice(Alba.albaMedium());
Audio audio = alba.say("This is the InfoQ article about the Voices library");
Path path = Paths.get("InfoQ_English_OpenVoice");
audio.save(path);
}
OpenVoice还支持英国或美国英语以及荷兰语等语言的语音,如下例所示:
Model nlModel = NonEnglishModels.nlNLRonnie();
ChorusConfig config = chorusConfig(Dictionaries.empty())
.withModel(new OpenVoiceSupplier());
try (Chorus chorus = new Chorus(config)) {
Voice alba = chorus.voice(nlModel);
Audio audio = alba.say("Dit is een Nederlandse tekst Scheveningen");
Path path = Paths.get("Dutch_OpenVoice");
audio.save(path);
}
通过从类路径中删除onnxruntime并添加onnxruntime_gpu 依赖项(例如,通过Maven pom.xml),该库还允许在GPU上运行模型,以取代CPU。接下来,应该使用gpuChorusConfig而不是“正常”的chorusConfig:
ChorusConfig config = gpuChorusConfig(EnUkDictionary.en_uk());
默认情况下,会使用GPU 0,没有其他选项;另外,可以使用在ChorusConfig类中定义的withCudaOptions()方法进行配置。
当库在文本中遇到Markdown符号时,即#、---、em或en破折号",会添加暂停。
与其他配置一样,可以使用ChorusConfig类来更改暂停的默认设置。
其他一些文本转语音的解决方案(如Sherpa Onnx"和MaryTTS"),从Maven等构建工具中获取较为困难,或者产生的声音质量较低。
InfoQ联系了Henry Coles,以了解更多关于Voices的信息。
InfoQ:您能想象在什么场景下声音最常见吗?您能分享一些这些库真正发挥作用的样例吗?
Henry Coles:最初,代码是编辑小说的工具的一部分。我只能猜测它可能在其他地方有用,但当你需要快速生成听起来相当自然的语音,并且不想依赖外部服务时,它就非常合适。
InfoQ:是什么激发了您创建Voices库?
Coles: 我需要从Java生成语音,而大多数现代文本转语音(Text to Speech,TTS)库都是用Python编写的。最初,我将piper"作为HTTP服务运行,但这很不方便,所以开始寻找从Java运行piper模型的方法。
InfoQ:是什么让您决定创建一个新库,而不是与现有的解决方案合作?
Coles: 现有的Java TTS解决方案是很久以前建立的,按照现代标准听起来很机械。它们很难改进。相比之下,运行piper ONNX模型非常简单,但是它缺少一个部分:将文本转换为音素(phonemes)"的Java代码。我找不到任何Java phonemiser,所以我不得不自己实现一个。
InfoQ:在构建声音时,您面临了哪些挑战,您是如何克服它们的?有没有您非常纠结关键设计决策?
Coles:主要挑战是我对语言学一无所知。开发过程也与我通常的工作方式完全不同。这主要是一个移植项目,即将TypeScript逻辑翻译成Java。测试本质上都是别人的逻辑,由于没有明确的“正确”答案,这进一步复杂化了。英语不能通过简单的规则进行音素化(需要通过字典处理特殊情况),所以对于某些输入,输出总是错误的,这是一个将该类场景识别出来的问题。我最终得到了一个非常手动化的开发循环,生成音频并通过耳朵进行评分,然后添加测试用例以捕获特定输入的回归。
InfoQ:您希望改进库的哪一部分呢?
Coles:我想清理API。当前的API是为了快速满足单一用例而创建的,如果进行一些前期思考,我可能会创建出更好的东西。
InfoQ:未来有计划添加功能吗?
Coles:如果有机会的话,我会考虑改进它处理暂停和设置语音节奏的方式。
InfoQ:您推荐使用库的应用程序应该采用哪种自动化测试方法?也许使用语音转文本解决方案,以便比较输入和输出?
Henry:我建议适度测试输出。一些检查音频是否产生以及一切是否正确连接的测试是很有意义的,但库的功能不是客户端应用程序控制的,所以它们应该主要关注检查输入到边界。
更多信息和示例可以在GitHub"上找到。
查看英文原文:Voices Enables Fast Text-to-Speech for Java Applications"