在数字时代,信息的传递方式日益多样化,其中,将文字自动转化为语音并保存为文件的需求愈发普遍。无论是为了辅助视觉障碍者阅读,还是为了制作有声读物、自动化通知系统等,这一技术都展现出了巨大的应用潜力。近期,我踏上了一段探索之旅,旨在通过Java调用Windows内置的语音库,实现这一功能。在此过程中,我不仅学习到了如何利用Jacob库这一强大的桥梁,还深刻体会到了技术分享的温暖与力量。
缘起:一次需求的触发
故事的开始,源自我工作中遇到的一个具体需求——将大量文本快速转换为语音文件,以便在不同场景下使用。面对这一挑战,我首先想到的是利用现有的语音合成服务或API,但考虑到成本、定制性以及数据隐私等因素,我决定探索更为直接且成本效益高的解决方案:利用Windows平台自带的语音引擎。
探索:Jacob的魔力
在技术的海洋中,我偶然发现了Jacob(Java COM Bridge)这个宝藏。Jacob是一个开源库,它允许Java程序直接调用COM组件,从而轻松访问Windows系统级的功能,包括但不限于语音合成、文件操作等。这一发现让我眼前一亮,仿佛找到了一把打开Windows语音合成大门的钥匙。
实践:代码编织语音
在查阅了众多资料,并经过多次尝试后,我成功地将Jacob与Windows的SAPI(Speech Application Programming Interface)结合起来,实现了文字到语音的转换,并将结果保存为音频文件。以下是我实现这一功能的方法(基于Jacob 1.18版本):
一、pom.xml引入jar包依赖
<!-- https://mvnrepository.com/artifact/com.jacob/jacob 文字转语音 -->
<dependency>
<groupId>com.hynnet</groupId>
<artifactId>jacob</artifactId>
<version>1.18</version>
</dependency>
二、把jacob-1.18-x64.dll文件复制到jdk安装位置的bin目录下。
不知道的话可以使用下列代码查看
public static void main(String[] args) {
// 获取当前JVM的库路径
String libraryPath = System.getProperty("java.library.path");
// 打印库路径
System.out.println("java.library.path: " + libraryPath);
}
三、在项目中测试运行。
(1)第一个demo:朗读文字
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class TestJacob {
public static void main(String[] args) {
ActiveXComponent sap = new ActiveXComponent("Sapi.SpVoice");
Dispatch sapo = sap.getObject();
try {
// 音量 0-100
sap.setProperty("Volume", new Variant(100));
// 语音朗读速度 -10 到 +10
sap.setProperty("Rate", new Variant(-2));
Variant defalutVoice = sap.getProperty("Voice");
Dispatch dispdefaultVoice = defalutVoice.toDispatch();
Variant allVoices = Dispatch.call(sapo, "GetVoices");
Dispatch dispVoices = allVoices.toDispatch();
Dispatch setvoice = Dispatch.call(dispVoices, "Item", new Variant(1)).toDispatch();
ActiveXComponent voiceActivex = new ActiveXComponent(dispdefaultVoice);
ActiveXComponent setvoiceActivex = new ActiveXComponent(setvoice);
Variant item = Dispatch.call(setvoiceActivex, "GetDescription");
// 执行朗读
Dispatch.call(sapo, "Speak", new Variant("警告,我也不知道怎么肥事"));
} catch (Exception e) {
e.printStackTrace();
} finally {
sapo.safeRelease();
sap.safeRelease();
}
}
}
(2)第二个demo:将文字转为音频文件
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
public class TestJacob {
public static void main(String[] args) {
ActiveXComponent ax = null;
try {
ax = new ActiveXComponent("Sapi.SpVoice");
Dispatch spVoice = ax.getObject();
ax = new ActiveXComponent("Sapi.SpFileStream");
Dispatch spFileStream = ax.getObject();
ax = new ActiveXComponent("Sapi.SpAudioFormat");
Dispatch spAudioFormat = ax.getObject();
//设置音频流格式
Dispatch.put(spAudioFormat, "Type", new Variant(22));
//设置文件输出流格式
Dispatch.putRef(spFileStream, "Format", spAudioFormat);
//调用输出 文件流打开方法,创建一个.wav文件
Dispatch.call(spFileStream, "Open", new Variant("F:\\test.wav"), new Variant(3), new Variant(true));
//设置声音对象的音频输出流为输出文件对象
Dispatch.putRef(spVoice, "AudioOutputStream", spFileStream);
//设置音量 0到100
Dispatch.put(spVoice, "Volume", new Variant(100));
//设置朗读速度
Dispatch.put(spVoice, "Rate", new Variant(-2));
//设置语音库
// Dispatch.put(spVoice, "Voice", 1);
//开始朗读
Dispatch.call(spVoice, "Speak", new Variant("警告,我也不知道怎么肥事"));
//关闭输出文件
Dispatch.call(spFileStream, "Close");
Dispatch.putRef(spVoice, "AudioOutputStream", null);
spAudioFormat.safeRelease();
spFileStream.safeRelease();
spVoice.safeRelease();
ax.safeRelease();
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意:可能遇到的问题
1、 运行的时候报 no jacob-1.18-x64 in java.library.path 错误,这个问题出现的话就是第2步有问题,还有要注意的是得注意报错提示的是什么版本,需要去下载对应的版本才行。
2、报下面这个错误,一般就是电脑没有连音频设备,比如音响或者耳机。
com.jacob.com.ComFailException: Invoke of: Speak
Source:
Description: 没有注册类
3、下面这个错误的话,我也还不清楚是什么问题,但文件已经生成了 那么就可以忽略了,记得捕获异常就行。
com.jacob.com.ComFailException: Invoke of: AudioOutputStream
Source:
Description:
最后,谢谢其他大佬的分享
通过jacob实现文字转语音(附jacob-1.18-x64.dll下载地址)
java使用com.jacob包 在Windows10开发环境运行正常,在Windows server 2008 抛出异常