You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Mary TTS 5.2库兼容JDK 11?

如何让Mary TTS 5.2库兼容JDK 11?

我需要借助CDI Bean将接收到的土耳其语文本转换为语音,用于网页上点击触发的语音按钮。问题在于Mary TTS仅兼容JDK 8,但我的项目采用Jakarta规范且使用JDK 11。从Mary TTS官网下载后用JDK 8运行效果良好,但无法在项目中正常使用。

CDI Bean代码

protected int bytesRead = 0;

public void guvenlikKodSeslendir() {
    try {
        // 创建MaryTTS接口
        MaryInterface maryTts = new LocalMaryInterface();

        // 加载土耳其语区域设置
        maryTts.setLocale(new Locale("tr"));

        // 设置要使用的语音模型
        maryTts.setVoice("dfki-pavoque-neutral");

        // 设置要朗读的文本
        String text = "Merhaba, dünya!";

        // 朗读文本并获取音频流数据
        AudioInputStream audio = maryTts.generateAudio(str);

        // 创建用于播放音频流的SourceDataLine
        try (SourceDataLine line = AudioSystem.getSourceDataLine(audio.getFormat())) {
            line.open(audio.getFormat());
            line.start();
            byte[] buffer = new byte[4096];
            int bytesRead = 0;
            while ((bytesRead = audio.read(buffer)) != -1) {
                line.write(buffer, 0, bytesRead);
            }
            line.drain();
            line.stop();
        }
    } catch (IOException | LineUnavailableException | MaryConfigurationException | SynthesisException e) {
        e.printStackTrace();
    }
}

注:代码中的str会由Facelet页面的内容替换,此处为清晰起见保留占位。

启动Mary TTS服务器时的错误(JDK 11环境)

我下载Mary TTS 5.2版本后,启动bin文件夹中的marytts-server.bat文件(电脑同时安装了JDK 11,未修改路径变量),控制台显示如下警告:

Java version "11.0.18" 2023-01-17 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.18+9-LTS-195)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.18+9-LTS-195, mixed mode)
MARY server 5.2 starting as a HTTP server...WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass$3$1 (file:/C:/Users/MFC/Documents/marytts-5.2/lib/marytts-client-5.2-jar-with-dependencies.jar) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.reflection.CachedClass$3$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
  started in 4.966 s on port 59125

使用JDK 8启动时不会出现上述警告。

测试示例类代码

为排查问题,我编写了一个带main方法的测试类:

package tr.com.fatih.beans;

import java.io.IOException;
import java.util.Locale;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import marytts.LocalMaryInterface;
import marytts.exceptions.MaryConfigurationException;
import marytts.exceptions.SynthesisException;

public class MaryTTSExample {
    public static void main(String[] args) {
        try {
            LocalMaryInterface maryTts = new LocalMaryInterface();
            maryTts.setLocale(new Locale("tr"));
            maryTts.setVoice("dfki-pavoque-neutral");
            String text = "Merhaba, bu bir deneme metnidir.";
            AudioInputStream audio = maryTts.generateAudio(text);
            try (SourceDataLine line = AudioSystem.getSourceDataLine(audio.getFormat())) {
                line.open(audio.getFormat());
                line.start();
                byte[] buffer = new byte[4096];
                int bytesRead = 0;
                while ((bytesRead = audio.read(buffer)) != -1) {
                    line.write(buffer, 0, bytesRead);
                }
                line.drain();
                line.stop();
            }
        } catch (IOException | IllegalArgumentException | LineUnavailableException | MaryConfigurationException | SynthesisException e) {
            e.printStackTrace();
        }
    }
}

运行示例类的错误输出

在NetBeans中运行该类时,控制台输出如下错误:

marytts.exceptions.MaryConfigurationException: Cannot start MARY server
    at marytts.LocalMaryInterface.<init>(LocalMaryInterface.java:66)
    at tr.com.fatih.beans.MaryTTSExample.main(MaryTTSExample.java:16)
Caused by: java.lang.Exception: Problem starting module Synthesis
    at marytts.server.Mary.startModules(Mary.java:151)
    at marytts.server.Mary.startup(Mary.java:297)
    at marytts.server.Mary.startup(Mary.java:204)
    at marytts.util.MaryRuntimeUtils.ensureMaryStarted(MaryRuntimeUtils.java:72)
    at marytts.LocalMaryInterface.<init>(LocalMaryInterface.java:64)
    ... 1 more
Caused by: marytts.exceptions.MaryConfigurationException: Cannot build unit selection voice 'dfki-ot'
    at marytts.unitselection.UnitSelectionVoice.<init>(UnitSelectionVoice.java:218)
    at marytts.unitselection.UnitSelectionSynthesizer.startup(UnitSelectionSynthesizer.java:94)
    at marytts.modules.Synthesis.startupSynthesizers(Synthesis.java:73)
    at marytts.modules.Synthesis.startup(Synthesis.java:65)
    at marytts.server.Mary.startModules(Mary.java:149)
    ... 5 more
Caused by: marytts.exceptions.NoSuchPropertyException: Cannot read file `voices\dfki-ot\halfphoneFeatures_ac.mry'. Check property `voice.dfki-ot.featureFile' in configuration files
    at marytts.server.MaryProperties.needFilename(MaryProperties.java:389)
    at marytts.unitselection.UnitSelectionVoice.<init>(UnitSelectionVoice.java:107)
    ... 9 more
Exception in thread "Thread-1" java.lang.IllegalStateException: MARY system is not running
    at marytts.server.Mary.shutdown(Mary.java:371)
    at marytts.server.Mary$2.run(Mary.java:290)

解决方案

1. 服务器模式调用(推荐方案)

Mary TTS 5.2在JDK 11下直接运行本地接口会触发反射限制和配置问题,最稳定的做法是用JDK 8启动独立的Mary TTS服务器,再在JDK 11项目中通过远程客户端调用:

  • 步骤1:用JDK 8启动服务器
    修改marytts-server.bat,指定JDK 8的Java路径,例如:

    "C:\Program Files\Java\jdk1.8.0_381\bin\java" -jar lib/marytts-server-5.2.jar
    

    确保服务器正常启动后,会在端口59125监听请求。

  • 步骤2:修改CDI Bean为远程调用
    替换LocalMaryInterface为RemoteMaryInterface,通过HTTP连接到服务器:

public void guvenlikKodSeslendir() {
try {
// 连接到本地运行的Mary TTS服务器
MaryInterface maryTts = new RemoteMaryInterface("http://localhost:59125");
maryTts.setLocale(new Locale("tr"));
maryTts.setVoice("dfki-pavoque-neutral");
// 替换为Facelet页面传入的文本
String text = "Merhaba, dünya!";
AudioInputStream audio = maryTts.generateAudio(text);

// 音频播放逻辑保持不变
    try (SourceDataLine line = AudioSystem.getSourceDataLine(audio.getFormat())) {
        line.open(audio.getFormat());
        line.start();
        byte[] buffer = new byte[4096];
        int bytesRead = 0;
        while ((bytesRead = audio.read(buffer)) != -1) {
            line.write(buffer, 0, bytesRead);
        }
        line.drain();
        line.stop();
    }
} catch (Exception e) {
    e.printStackTrace();
}

}

这种方式完全隔离了JDK版本差异,稳定性最高。

### 2. 本地运行的兼容修复(不推荐)
如果必须在JDK 11下本地运行Mary TTS,需要解决两个核心问题:
- **解决反射访问限制**:在项目的JVM启动参数中添加:

--add-opens java.base/java.lang=ALL-UNNAMED

允许Groovy框架的反射操作。
- **解决语音文件缺失**:确保Mary TTS的`voices`目录完整,或者在代码启动前设置Mary的基础路径:
```java
System.setProperty("mary.base", "C:/Users/MFC/Documents/marytts-5.2");

不过这种方法可能会遇到更多JDK模块化带来的兼容性问题,不如服务器模式可靠。

3. 升级Mary TTS版本

检查Mary TTS官方是否发布了支持JDK 11的更新版本,若有则直接升级依赖包,替换5.2版本,从根源解决兼容性问题。


内容的提问来源于stack exchange,提问作者Mehmet Fatih ÇİN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 04:47:40