Java SDK

更新时间:
复制 MD 格式

The Intelligent Speech Interaction (ISI) SDK for Java lets you integrate text-to-speech (TTS) synthesis into your Java application. This page covers installation, key classes, and a runnable code sample.

Prerequisites

Before you begin, ensure that you have:

  • An Alibaba Cloud account with ISI enabled

  • An appKey from your ISI project

  • An AccessKey ID and AccessKey secret

For an overview of how the SDK works, see Overview.

Install the SDK

Add the following dependency to your pom.xml:

<dependency>
    <groupId>com.alibaba.nls</groupId>
    <artifactId>nls-sdk-tts</artifactId>
    <version>2.1.6</version>
</dependency>
The SDK depends on Netty. If your project already uses Netty, make sure the version is 4.1.17.Final or later.

Run the demo package

The demo package includes a prebuilt JAR for quick service validation and stress testing.

Step 1: Download and build

Download the nls-sdk-java-demo package, then decompress it. From the directory containing pom.xml, run:

mvn package

This generates nls-example-tts-2.0.0-jar-with-dependencies.jar in the target directory. Copy the JAR to your target server.

Step 2: Validate the service

Run the following command and set the parameters as prompted. Logs are written to logs/nls.log in the working directory.

java -cp nls-example-tts-2.0.0-jar-with-dependencies.jar com.alibaba.nls.client.SpeechSynthesizerDemo

Step 3: Run stress testing (optional)

java -jar nls-example-tts-2.0.0-jar-with-dependencies.jar

Set the service endpoint to wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1. Set the maximum concurrent calls based on your purchased resources.

Important

Concurrent calls exceeding two are billed. Check your resource quota before running stress tests.

Key classes

ClassThread-safeDescription
NlsClientYesThe speech processing client. Handles short sentence recognition, real-time speech recognition, and speech synthesis. Create one instance globally and reuse it.
SpeechSynthesizerNoSets request parameters and sends synthesis requests. Create a new instance for each synthesis task.
SpeechSynthesizerListenerNoReceives synthesis results. One listener corresponds to one SpeechSynthesizer—do not share a listener across multiple synthesizers.

SpeechSynthesizerListener implements two abstract methods:

/**
 * Receive synthesized audio data in binary format.
 */
abstract public void onMessage(ByteBuffer message);

/**
 * Called when the synthesis task completes.
 */
abstract public void onComplete(SpeechSynthesizerResponse response);

For the full API reference, see Java API overview.

Lifecycle and threading rules

  • `NlsClient` lifecycle: NlsClient is built on Netty and is expensive to create. Create it once at application startup and shut it down when the application exits.

  • `SpeechSynthesizer` per task: Each synthesis task requires its own SpeechSynthesizer instance. To synthesize N texts, create N SpeechSynthesizer objects.

  • Token refresh: Tokens expire. Call accessToken.getExpireTime() to check expiration and obtain a new token before the current one expires.

Sample code

The sample below synthesizes speech from a text string and writes the audio to a WAV file. To reduce latency in production, consider using stream playback—playback starts as soon as the first audio chunk arrives, without waiting for the full synthesis to complete.

Important

Pass your AccessKey ID and secret as command-line arguments or environment variables. Do not hardcode credentials in source code.

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.OutputFormatEnum;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizer;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerListener;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Demonstrates:
 *   - Calling the ISI speech synthesis API
 *   - Obtaining a token dynamically
 *   - Receiving synthesized audio in streaming mode
 *   - Measuring first packet latency
 */
public class SpeechSynthesizerDemo {
    private static final Logger logger = LoggerFactory.getLogger(SpeechSynthesizerDemo.class);
    private static long startTime;
    private String appKey;
    NlsClient client;

    public SpeechSynthesizerDemo(String appKey, String accessKeyId, String accessKeySecret) {
        this.appKey = appKey;
        // Create NlsClient once. The default endpoint is the ISI Internet access URL.
        // Refresh the token before it expires; use accessToken.getExpireTime() to check.
        AccessToken accessToken = new AccessToken(accessKeyId, accessKeySecret);
        try {
            accessToken.apply();
            System.out.println("token: " + accessToken.getToken()
                + ", expires: " + accessToken.getExpireTime());
            client = new NlsClient(accessToken.getToken());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public SpeechSynthesizerDemo(String appKey, String accessKeyId, String accessKeySecret, String url) {
        this.appKey = appKey;
        AccessToken accessToken = new AccessToken(accessKeyId, accessKeySecret);
        try {
            accessToken.apply();
            System.out.println("token: " + accessToken.getToken()
                + ", expires: " + accessToken.getExpireTime());
            client = url.isEmpty()
                ? new NlsClient(accessToken.getToken())
                : new NlsClient(url, accessToken.getToken());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static SpeechSynthesizerListener getSynthesizerListener() {
        SpeechSynthesizerListener listener = null;
        try {
            listener = new SpeechSynthesizerListener() {
                File f = new File("tts_test.wav");
                FileOutputStream fout = new FileOutputStream(f);
                private boolean firstRecvBinary = true;

                @Override
                public void onComplete(SpeechSynthesizerResponse response) {
                    // onComplete fires when all audio data has been received.
                    // Use this event to measure full synthesis latency.
                    System.out.println("name: " + response.getName()
                        + ", status: " + response.getStatus()
                        + ", output: " + f.getAbsolutePath());
                }

                @Override
                public void onMessage(ByteBuffer message) {
                    try {
                        if (firstRecvBinary) {
                            // Record first packet latency—the time from request to first audio chunk.
                            // Starting playback at this point minimizes perceived latency.
                            firstRecvBinary = false;
                            long now = System.currentTimeMillis();
                            logger.info("first packet latency: " + (now - SpeechSynthesizerDemo.startTime) + " ms");
                        }
                        byte[] bytesArray = new byte[message.remaining()];
                        message.get(bytesArray, 0, bytesArray.length);
                        fout.write(bytesArray);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onFail(SpeechSynthesizerResponse response) {
                    // Record the task ID when filing a support ticket—it uniquely identifies
                    // the interaction between your client and the server.
                    System.out.println("task_id: " + response.getTaskId()
                        + ", status: " + response.getStatus()
                        + ", error: " + response.getStatusText());
                }
            };
        } catch (Exception e) {
            e.printStackTrace();
        }
        return listener;
    }

    public void process() {
        SpeechSynthesizer synthesizer = null;
        try {
            // Create a new SpeechSynthesizer for each synthesis task.
            synthesizer = new SpeechSynthesizer(client, getSynthesizerListener());
            synthesizer.setAppKey(appKey);
            synthesizer.setFormat(OutputFormatEnum.WAV);           // audio format: WAV
            synthesizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K); // sample rate: 16 kHz
            synthesizer.setVoice("siyue");                         // voice
            synthesizer.setPitchRate(100);                         // pitch rate: -500 to 500, default 0
            synthesizer.setSpeechRate(100);                        // speech rate: -500 to 500, default 0
            synthesizer.setText("Welcome to use the Alibaba Cloud intelligent speech synthesis service. "
                + "You can say what's the weather like in Beijing tomorrow.");
            synthesizer.addCustomedParam("enable_subtitle", false); // subtitle: disabled by default;
                                                                    // not all voices support it

            // Serialize parameters to JSON and send to the server.
            long start = System.currentTimeMillis();
            synthesizer.start();
            logger.info("start latency: " + (System.currentTimeMillis() - start) + " ms");
            SpeechSynthesizerDemo.startTime = System.currentTimeMillis();

            synthesizer.waitForComplete();
            logger.info("total latency: " + (System.currentTimeMillis() - start) + " ms");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (synthesizer != null) {
                synthesizer.close();
            }
        }
    }

    public void shutdown() {
        client.shutdown();
    }

    public static void main(String[] args) throws Exception {
        // Replace placeholders with your actual values.
        // Usage: <app-key> <AccessKey ID> <AccessKey secret> [endpoint]
        String appKey  = "Your appkey";
        String id      = "Your AccessKey ID";
        String secret  = "Your AccessKey secret";
        String url     = ""; // Default: wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1

        if (args.length == 3) {
            appKey = args[0];
            id     = args[1];
            secret = args[2];
        } else if (args.length == 4) {
            appKey = args[0];
            id     = args[1];
            secret = args[2];
            url    = args[3];
        } else {
            System.err.println("Usage: <app-key> <AccessKey ID> <AccessKey secret> [endpoint]");
            System.exit(-1);
        }

        SpeechSynthesizerDemo demo = new SpeechSynthesizerDemo(appKey, id, secret, url);
        demo.process();
        demo.shutdown();
    }
}

Replace the following placeholders with your actual values:

PlaceholderDescriptionExample
Your appkeyappKey from your ISI projectFj7x...
Your AccessKey IDAlibaba Cloud AccessKey IDLTAI5t...
Your AccessKey secretAlibaba Cloud AccessKey secretxXxXxX...

Next steps

  • To synthesize long texts without waiting for the full result, enable stream playback in your onMessage handler.

  • For all SDK classes and parameters, see the Java API overview.