This topic describes how to use the Java software development kit (SDK) for Alibaba Cloud Intelligent Speech Interaction, including installation instructions and sample code.
Prerequisites
Before you use the SDK, read the API reference. For more information, see API reference.
Starting with version 2.1.0, nls-sdk-long-asr is renamed to nls-sdk-transcriber. When you upgrade, make sure to delete nls-sdk-long-asr and add the corresponding callback methods as prompted during compilation.
Download and installation
Download the latest version of the SDK from the Maven server.
<dependency> <groupId>com.alibaba.nls</groupId> <artifactId>nls-sdk-transcriber</artifactId> <version>2.2.1</version> </dependency>After you decompress the demo, run the
mvn packagecommand in the pom directory. An executable JAR file named nls-example-transcriber-2.0.0-jar-with-dependencies.jar is generated in the target directory. You can copy the JAR file to the destination server for quick service validation and stress testing.Validate the service.
Run the following command and provide the parameters as prompted. After the command is run, the logs/nls.log file is generated in the directory where you ran the command.
java -cp nls-example-transcriber-2.0.0-jar-with-dependencies.jar com.alibaba.nls.client.SpeechTranscriberDemoPerform stress testing.
Run the following command and provide the parameters as prompted. Set the Alibaba Cloud service URL parameter to
wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1. Use PCM audio files with a 16 kHz sample rate. Select the number of concurrent calls based on your purchased resources.java -jar nls-example-transcriber-2.0.0-jar-with-dependencies.jarImportantCharges are incurred if you perform stress testing with more than two concurrent streams.
Key interfaces
NlsClient: The speech processing client. This client processes tasks for short sentence recognition, real-time speech recognition, and speech synthesis. This client is thread-safe. We recommend that you create only one global instance.
SpeechTranscriber: The real-time speech recognition class. This class is used to set request parameters and send requests and audio data. This class is not thread-safe.
SpeechTranscriberListener: The real-time speech recognition result listener that listens for recognition results. This class is not thread-safe.
For more information, see Java API reference.
Notes on SDK calls:
NlsClient uses the Netty framework. Creating an NlsClient object consumes time and resources, but the created object can be reused. We recommend that you align the creation and shutdown of the NlsClient object with your application's lifecycle.
The SpeechTranscriber object cannot be reused. One recognition task corresponds to one SpeechTranscriber object. For example, to perform N recognition tasks for N audio files, you must create N SpeechTranscriber objects.
A SpeechTranscriberListener object and a SpeechTranscriber object have a one-to-one relationship. Do not use the same SpeechTranscriberListener object for different SpeechTranscriber objects. Otherwise, you cannot distinguish between recognition tasks.
The Java SDK depends on the Netty network library. If your application also depends on Netty, upgrade the Netty version to 4.1.17.Final or later.
Sample code
The audio file used in the example has a sample rate of 16,000 Hz. To obtain correct recognition results, set the model for the project that corresponds to the appkey to Universal in the console. If you use other audio files, set the model to one that supports your audio scenario. For more information about how to set a model, see Manage projects.
The example uses the default public endpoint of the SDK. To use the internal endpoint on an Alibaba Cloud ECS instance in the China (Shanghai) region, set the internal endpoint when you create the NlsClient object:
client = new NlsClient("ws://nls-gateway-cn-shanghai-internal.aliyuncs.com/ws/v1", accessToken);Before you call the API operation, configure environment variables to load your access credentials. The environment variables for the AccessKey ID, AccessKey secret, and the Intelligent Speech Interaction AppKey are ALIYUN_AK_ID, ALIYUN_AK_SECRET, and NLS_APP_KEY.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriber;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriberListener;
import com.alibaba.nls.client.protocol.asr.SpeechTranscriberResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This example demonstrates how to:
* Call the real-time ASR API operation.
* Dynamically obtain a token. For details about how to obtain a token, see https://help.aliyun.com/document_detail/450514.html
* Simulate sending a real-time stream from a local file.
* Calculate the recognition latency.
*/
public class SpeechTranscriberDemo {
private String appKey;
private NlsClient client;
private static final Logger logger = LoggerFactory.getLogger(SpeechTranscriberDemo.class);
public SpeechTranscriberDemo(String appKey, String id, String secret, String url) {
this.appKey = appKey;
// Create a global NlsClient instance. The default endpoint is the public endpoint of the Alibaba Cloud service.
// Obtain a token. In a real-world application, make sure to obtain a new token before the current one expires.
AccessToken accessToken = new AccessToken(id, secret);
try {
accessToken.apply();
System.out.println("get token: " + ", expire time: " + accessToken.getExpireTime());
if(url.isEmpty()) {
client = new NlsClient(accessToken.getToken());
}else {
client = new NlsClient(url, accessToken.getToken());
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static SpeechTranscriberListener getTranscriberListener() {
SpeechTranscriberListener listener = new SpeechTranscriberListener() {
// Intermediate recognition result. This message is returned only when setEnableIntermediateResult is set to true.
@Override
public void onTranscriptionResultChange(SpeechTranscriberResponse response) {
System.out.println("task_id: " + response.getTaskId() +
", name: " + response.getName() +
// A status code of "20000000" indicates a successful recognition.
", status: " + response.getStatus() +
// The sentence number, which increments starting from 1.
", index: " + response.getTransSentenceIndex() +
// The current recognition result.
", result: " + response.getTransSentenceText() +
// The duration of the processed audio in milliseconds.
", time: " + response.getTransSentenceTime());
}
@Override
public void onTranscriberStart(SpeechTranscriberResponse response) {
// task_id is the unique identifier for the communication between the client and the server. If you encounter an issue, provide this task_id.
System.out.println("task_id: " + response.getTaskId() + ", name: " + response.getName() + ", status: " + response.getStatus());
}
@Override
public void onSentenceBegin(SpeechTranscriberResponse response) {
System.out.println("task_id: " + response.getTaskId() + ", name: " + response.getName() + ", status: " + response.getStatus());
}
// A sentence is recognized. The server intelligently segments sentences and returns this message when it detects the end of a sentence.
@Override
public void onSentenceEnd(SpeechTranscriberResponse response) {
System.out.println("task_id: " + response.getTaskId() +
", name: " + response.getName() +
// A status code of "20000000" indicates a successful recognition.
", status: " + response.getStatus() +
// The sentence number, which increments starting from 1.
", index: " + response.getTransSentenceIndex() +
// The current recognition result.
", result: " + response.getTransSentenceText() +
// Confidence level
", confidence: " + response.getConfidence() +
// Start time
", begin_time: " + response.getSentenceBeginTime() +
// The duration of the processed audio in milliseconds.
", time: " + response.getTransSentenceTime());
}
// Recognition is complete.
@Override
public void onTranscriptionComplete(SpeechTranscriberResponse response) {
System.out.println("task_id: " + response.getTaskId() + ", name: " + response.getName() + ", status: " + response.getStatus());
}
@Override
public void onFail(SpeechTranscriberResponse response) {
// task_id is the unique identifier for the communication between the client and the server. If you encounter an issue, provide this task_id.
System.out.println("task_id: " + response.getTaskId() + ", status: " + response.getStatus() + ", status_text: " + response.getStatusText());
}
};
return listener;
}
// Calculate the equivalent audio duration based on the size of the binary data.
// sampleRate: 8000 or 16000 is supported.
public static int getSleepDelta(int dataSize, int sampleRate) {
// Only 16-bit sampling is supported.
int sampleBytes = 16;
// Only a single channel is supported.
int soundChannel = 1;
return (dataSize * 10 * 8000) / (160 * sampleRate);
}
public void process(String filepath) {
SpeechTranscriber transcriber = null;
try {
// Create an instance and establish a connection.
transcriber = new SpeechTranscriber(client, getTranscriberListener());
transcriber.setAppKey(appKey);
// The audio encoding format of the input.
transcriber.setFormat(InputFormatEnum.PCM);
// The audio sample rate of the input.
transcriber.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
// Specifies whether to return intermediate recognition results.
transcriber.setEnableIntermediateResult(false);
// Specifies whether to generate and return punctuation marks.
transcriber.setEnablePunctuation(true);
// Specifies whether to normalize the result. For example, convert "one hundred" to "100".
transcriber.setEnableITN(false);
// Set the VAD sentence segmentation parameter. Default value: 800 ms. Valid values: 200 ms to 6000 ms.
//transcriber.addCustomedParam("max_sentence_silence", 600);
// Specifies whether to enable semantic sentence segmentation.
//transcriber.addCustomedParam("enable_semantic_sentence_detection",false);
// Specifies whether to enable filtering of filler words, which is also known as disfluency detection.
//transcriber.addCustomedParam("disfluency",true);
// Specifies whether to enable word-level mode.
//transcriber.addCustomedParam("enable_words",true);
// Set the VAD noise threshold. The value can range from -1 to +1, such as -0.9, -0.8, 0.2, or 0.9.
// A value closer to -1 increases the probability of audio being classified as speech, which may cause more noise to be misidentified as speech.
// A value closer to +1 increases the probability of audio being classified as noise, which may cause more speech segments to be rejected as noise.
// This is an advanced parameter. Adjust it with caution and perform thorough testing.
//transcriber.addCustomedParam("speech_noise_threshold",0.3);
// Set the ID of the custom language model after training.
//transcriber.addCustomedParam("customization_id","your_custom_language_model_id");
// Set the ID of the custom hotword model after training.
//transcriber.addCustomedParam("vocabulary_id","your_custom_hotword_model_id");
// This method serializes the preceding parameter settings into JSON format, sends them to the server, and waits for confirmation.
transcriber.start();
File file = new File(filepath);
FileInputStream fis = new FileInputStream(file);
byte[] b = new byte[3200];
int len;
while ((len = fis.read(b)) > 0) {
logger.info("send data pack length: " + len);
transcriber.send(b, len);
// This example simulates obtaining and sending a real-time audio stream by reading a local file. Because the file is read quickly, a sleep interval is required here.
// If you obtain a real-time audio stream, you do not need to set a sleep interval. If the audio sample rate is 8k, set the second parameter to 8000.
int deltaSleep = getSleepDelta(len, 16000);
Thread.sleep(deltaSleep);
}
// Notify the server that the audio data has been sent and wait for the server to finish processing.
long now = System.currentTimeMillis();
logger.info("ASR wait for complete");
transcriber.stop();
logger.info("ASR latency : " + (System.currentTimeMillis() - now) + " ms");
} catch (Exception e) {
System.err.println(e.getMessage());
} finally {
if (null != transcriber) {
transcriber.close();
}
}
}
public void shutdown() {
client.shutdown();
}
public static void main(String[] args) throws Exception {
String appKey = System.getenv().get("NLS_APP_KEY");
String id = System.getenv().get("ALIYUN_AK_ID");
String secret = System.getenv().get("ALIYUN_AK_SECRET");
String url = System.getenv().getOrDefault("NLS_GATEWAY_URL", "wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1");
// This example uses a local file to simulate sending real-time stream data. In a real-world application, you can capture or receive a real-time audio stream and send it to the ASR server.
String filepath = "nls-sample-16k.wav";
SpeechTranscriberDemo demo = new SpeechTranscriberDemo(appKey, id, secret, url);
demo.process(filepath);
demo.shutdown();
}
}

