javajava-8jbossjboss6.xjavasound

Java 8 - javax.sound.sampled.UnsupportedAudioFileException Error on JBoss Server


In an application I developed with Java 8, I am trying to convert a .wav audio file received in Base64 format to PCM_SIGNED format. The code works fine in the local environment, but I get the following error on JBoss EAP 6.4:

java.lang.RuntimeException: Audio processing failed
       at com.assistt.voicecloneservice.service.AudioConverter.convertBase64ToPcmSigned(AudioConverter.java:42)
       at com.assistt.voicecloneservice.service.AudioProcessingService.processAndUploadAndInsert(AudioProcessingService.java:35)
       at com.assistt.voicecloneservice.api.TtsTextCheckService.doPost(TtsTextCheckService.java:57)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:295)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:231)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:149)
       at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:169)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:150)
       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:97)
       at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:559)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:102)
       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344)
       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:854)
       at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:653)
       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:926)
       at java.lang.Thread.run(Thread.java:750)
Caused by: javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input stream
       at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1121)
       at com.assistt.voicecloneservice.service.AudioConverter.convertBase64ToPcmSigned(AudioConverter.java:20)
       ... 18 more

The method I get error is as follows:

public void convertBase64ToPcmSigned(String base64Audio) throws Exception {
    byte[] audioByte = Base64.getDecoder().decode(base64Audio);

    try (InputStream inputStream = new ByteArrayInputStream(audioByte);
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

        // Get AudioInputStream from the input stream
        AudioInputStream inputAudioStream = AudioSystem.getAudioInputStream(inputStream);

        // Define the target audio format
        AudioFormat sourceFormat = inputAudioStream.getFormat();
        AudioFormat targetFormat = new AudioFormat(
                AudioFormat.Encoding.PCM_SIGNED,  // PCM_SIGNED format
                8000.0f,                          // Sample rate
                16,                               // Sample size in bits
                1,                                // Channels (Mono)
                2,                                // Frame size
                8000.0f,                          // Frame rate
                false                             // Big-endian
        );

        AudioInputStream convertedAudioStream = AudioSystem.getAudioInputStream(targetFormat, inputAudioStream);

        File outputFile = new File("output.wav");
        AudioSystem.write(convertedAudioStream, AudioFileFormat.Type.WAVE, outputFile);

    } catch (UnsupportedAudioFileException | IOException e) {
        throw new RuntimeException("Audio processing failed", e);
    }
}

My pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.assistt</groupId>
    <artifactId>VoiceCloneService</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20210307</version>
        </dependency>
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.55</version>
        </dependency>


    </dependencies>

</project>

I manually converted the base64 part to a wav file myself and it came out with the following properties.

Encoding       : PCM_SIGNED  
Sample Rate    : 40000.0 Hz  
Sample Size    : 16 bits  
Channels       : 1  
Frame Size     : 2 bytes  
Frame Rate     : 40000.0 frames/second  
Big Endian     : false  

The error only occurs in JBoss EAP 6.4 environment. When I test locally, the files are processed and converted correctly.

What points should I check or what alternative solutions should I try to solve this problem? Is there any special configuration required to process audio files in JBoss environment?

I tried the following code to first convert the Base64 format data to a .wav file and then process it file-based:

File file = new File(sourceFilePath);
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));

if (!inputStream.markSupported()) {
    return;
}

AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(inputStream);
AudioFormat sourceFormat = audioInputStream.getFormat();

AudioFormat targetFormat = new AudioFormat(
        AudioFormat.Encoding.ALAW,
        8000,
        8,
        sourceFormat.getChannels(),
        1,
        8000,
        false
);

AudioInputStream convertedAudioInputStream = AudioSystem.getAudioInputStream(targetFormat, audioInputStream);

AudioSystem.write(convertedAudioInputStream, AudioFileFormat.Type.WAVE, new File(destinationFilePath));

inputStream.close();
audioInputStream.close();
convertedAudioInputStream.close();

I got the following error on this line: AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(inputStream);

javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file
    at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1189)
    at com.assistt.voicecloneservice.service.AudioConverter.convertBase64ToPcmSigned(AudioConverter.java:34)
    ...

Solution

  • After some effort I found the solution to the problem. JBoss manages libraries and packages with its own module structure. So, even “standard Java libraries” sometimes need an additional module definition. I didn't have sound and main folders under /opt/jboss-eap-6.4/modules/system/layers/base/javax

    1. First I added the sound/main folders under javax. Then I created a file called module.xml here.
    <?xml version="1.0" encoding="UTF-8"?>
    <module xmlns="urn:jboss:module:1.1" name="javax.sound">
        <properties>
            <property name="jboss.api" value="private"/>
        </properties>
        <dependencies>
            <system export="true">
                <paths>
                    <path name="javax/sound/sampled"/>
                    <path name="com/sun/media/sound"/>
                </paths>
            </system>
            <module name="javax.api" export="true"/>
            <module name="sun.jdk" export="true"/>
        </dependencies>
    </module>
    

    In doing so, we are in a way telling JBoss “I need the classes inside the javax.sound package, I also need access to sub-packages like com.sun.media.sound and javax.sound.sampled.

    2.In the WEB-INF folder of your application , add a jboss-deployment-structure.xml file:

    <?xml version="1.0" encoding="UTF-8"?>
    <jboss-deployment-structure>
        <deployment>
            <dependencies>
                <module name="javax.sound" export="true"/>
                <module name="sun.jdk" export="true"/>
            </dependencies>
        </deployment>
    </jboss-deployment-structure>
    

    It is not enough to define a module in JBoss; you also need to specify that the application should refer to this module (dependency). Jboss adds these to the classloader.

    After these steps the UnsupportedAudioFileException error was resolved.