MaryConfigurationException: MaryTTS and Maven shade plugin build executable jar

79 views Asked by At

I am working on a JavaFX application in Eclipse that uses MaryTTS. In Eclipse the application works fine, but if I generate a runnable jar with Mavens shade plugin I get

marytts.exceptions.MaryConfigurationException: Cannot start MARY server
        at marytts.LocalMaryInterface.<init>(LocalMaryInterface.java:66)
        at de.levin.util.TextToSpeech.<init>(TextToSpeech.java:27)
        at de.levin.ctrl.MainCtrl.initialize(MainCtrl.java:1317)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2655)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
        at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2516)
        at de.levin.sifuSays.App.start(App.java:124)
        at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
        at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
        at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
        at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
        at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
        at java.base/java.lang.Thread.run(Thread.java:1589)
Caused by: java.lang.NullPointerException: Cannot enter synchronized block because the return value of "marytts.config.MaryConfig.getMainConfig()" is null
        at marytts.util.MaryRuntimeUtils.ensureMaryStarted(MaryRuntimeUtils.java:70)
        at marytts.LocalMaryInterface.<init>(LocalMaryInterface.java:64)
        ... 15 more

I checked the implementation in https://github.com/marytts/marytts/blob/master/marytts-runtime/src/main/java/marytts/config/MaryConfig.java and I guess the important line is

private static final ServiceLoader<MaryConfig> configLoader = ServiceLoader.load(MaryConfig.class);

The MaryConfig.class does exist in the jar File that the shade plugin created.

Any idea?

Here are my findings / thoughts: When I was trying to find out was is the issue, I found https://youtrack.jetbrains.com/issue/IDEA-240253 which sounds like a potential root cause also in the shade plugin and I recalled the Warning

[WARNING] maven-shade-plugin has detected that some files are
[WARNING] present in two or more JARs. When this happens, only one
[WARNING] single version of the file is copied to the uber jar.

but when reading the https://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html page, I don't get it - my Maven skills are very limited. So should you agree, that these things belong together, then how do I need to modify my pom.xml?

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>de.levin</groupId>
    <artifactId>sifuSays</artifactId>
    <version>1.0.0</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <repositories>
        <repository>
            <id>jcenter</id>
            <name>jcenter-bintray</name>
            <url>https://jcenter.bintray.com</url>
        </repository>
    </repositories>
    <dependencies>
        <!-- JavaFX -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>19</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>19</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-media</artifactId>
            <version>19</version>
        </dependency>
        <!-- JAXB API only -->
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>4.0.3</version>
            <scope>runtime</scope>
        </dependency>
        <!-- Framegrabber to get image from movies -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.5.9</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>ffmpeg-platform</artifactId>
            <version>6.0-1.5.9</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>flandmark</artifactId>
            <version>1.07-1.5.5</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/de.dfki.mary/marytts -->
        <!-- https://mvnrepository.com/artifact/de.dfki.mary/marytts-common -->
        <dependency>
            <groupId>de.dfki.mary</groupId>
            <artifactId>marytts-common</artifactId>
            <version>5.2.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/de.dfki.mary/voice-dfki-pavoque-neutral-hsmm -->
        <dependency>
            <groupId>de.dfki.mary</groupId>
            <artifactId>voice-dfki-prudence-hsmm</artifactId>
            <version>5.2</version>
        </dependency>
        <dependency>
            <groupId>de.dfki.mary</groupId>
            <artifactId>voice-cmu-slt-hsmm</artifactId>
            <version>5.2.1</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                    <release>11</release>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.8</version>
                <executions>
                    <execution>
                        <!-- Default configuration for running -->
                        <!-- Usage: mvn clean javafx:run -->
                        <id>default-cli</id>
                        <configuration>
                            <mainClass>de.levin.sifuSays.App</mainClass>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>de.levin.sifuSays.AppLauncher</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.5.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <outputFile>${dir}/${project.artifactId}.jar</outputFile>
                            <createDependencyReducedPom>false</createDependencyReducedPom>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>de.levin.sifuSays.AppLauncher</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

In order to build the jar, I call: clean package shade:shade from the Eclipse Maven interface

In case you want to try

package de.levin.util;

import java.io.IOException;

import javax.sound.sampled.AudioInputStream;

import marytts.LocalMaryInterface;
import marytts.MaryInterface;
import marytts.exceptions.MaryConfigurationException;
import marytts.exceptions.SynthesisException;
import marytts.util.data.audio.AudioPlayer;

public class TextToSpeech {

    private AudioPlayer tts;
    private MaryInterface marytts;

    /**
     * Constructor
     */
    public TextToSpeech() {

        try {
            marytts = new LocalMaryInterface();

            marytts.setVoice("dfki-prudence-hsmm");
            marytts.setAudioEffects("Rate(durScale:1.5)+Robot(amount:0)");

        } catch (MaryConfigurationException ex) {
            ex.printStackTrace();
        }
    }



    /**
     * Transform text to speech
     * 
     * @param text
     */
    public void speak(String text) {

        // Stop the previous player
        if (tts != null) {
            tts.cancel();
        }

        try (AudioInputStream audio = marytts.generateAudio(text)) {

            // Player is a thread(threads can only run one time) so it can be
            // used has to be initiated every time
            tts = new AudioPlayer();
            tts.setAudio(audio);
            tts.setDaemon(true);
            tts.start();

        } catch (SynthesisException | IOException ex) {
            ex.printStackTrace();
        } 
    }
}

and I call the methods from another method in another class

TextToSpeech tts = new TextToSpeech();
tts.speak("Take the stretch a little bit deeper");

One last thought: Ialso found this marytts.exceptions.MaryConfigurationException: Cannot start MARY server Not sure whether it relates?!

Thank you in advance!

0

There are 0 answers