This topic explains how to use the Java SDK for Intelligent Speech Interaction short-phrase speech recognition, covering installation and code examples.
Usage notes
-
Before you use the SDK, read the API reference.
-
Starting from version 2.1.0, nls-sdk-short-asr is renamed to nls-sdk-recognizer. When upgrading, remove nls-sdk-short-asr and add the corresponding callback methods as indicated by the compiler prompts.
Download and install
-
Download the latest SDK from the Maven repository.
<dependency> <groupId>com.alibaba.nls</groupId> <artifactId>nls-sdk-recognizer</artifactId> <version>2.2.1</version> </dependency>Unzip the file and run
mvn packagein the pom directory. This generates an executable JAR file namednls-example-recognizer-2.0.0-jar-with-dependencies.jarin thetargetdirectory. Copy this JAR package to your target server to quickly validate the service or run performance tests. -
Validate the service.
Run the following command and provide the required parameters when prompted. A log file named
nls.logis generated in thelogsdirectory where the command was executed.java -cp nls-example-recognizer-2.0.0-jar-with-dependencies.jar com.alibaba.nls.client.SpeechRecognizerDemo -
Run a performance test.
Run the following command and provide the required parameters when prompted. The Alibaba Cloud service URL is
wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1. Use a PCM audio file with a 16 kHz sample rate. Select a concurrency level based on your purchased plan.java -jar nls-example-recognizer-2.0.0-jar-with-dependencies.jarImportantRunning a test with a concurrency of more than 2 will incur charges.
Key interfaces
-
NlsClient: The voice processing client. Use this client for short-phrase speech recognition, real-time speech recognition, and speech synthesis. This client is thread-safe. We recommend creating only one global instance.
-
SpeechRecognizer: Handles short-phrase speech recognition. Use this class to set request parameters and send audio data. This class is not thread-safe.
-
SpeechRecognizerListener: Listens for recognition results. This class is not thread-safe.
For more information, see the Java API reference.
Notes on using the SDK:
-
Creating an
NlsClientobject is resource-intensive, but the instance is reusable. We recommend aligning the lifecycle of theNlsClientinstance with your application's lifecycle. -
A
SpeechRecognizerobject is not reusable. You must create a newSpeechRecognizerobject for each recognition task. For example, processing N audio files requires NSpeechRecognizerobjects. -
Do not reuse a
SpeechRecognizerListenerinstance across multipleSpeechRecognizerobjects, as this makes it impossible to distinguish between recognition tasks. -
If your application also uses Netty, ensure its version is 4.1.17.Final or later.
Code example
-
The audio file in the example uses a 16000 Hz sample rate. For accurate results, go to the console and set the model for the project associated with your AppKey to the General model. If you use a different audio file, select a model that supports its scenario. For more information about model settings, see Manage projects.
-
The example uses the SDK's built-in default public endpoint URL for the short-phrase speech recognition service. If you are using an Alibaba Cloud ECS instance in the China (Shanghai) region and want to use the internal endpoint URL, set the internal URL when you create the NlsClient object:
client = new NlsClient("ws://nls-gateway-cn-shanghai-internal.aliyuncs.com/ws/v1", accessToken); -
Before calling the API, you must configure environment variables for your access credentials. For Intelligent Speech Interaction, the environment variable names for the AccessKey ID, AccessKey Secret, and AppKey are ALIYUN_AK_ID, ALIYUN_AK_SECRET, and NLS_APP_KEY, respectively.
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.SpeechRecognizer;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerListener;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This example demonstrates how to:
* - Call the API for short-phrase speech recognition.
* - Dynamically obtain an access token. For details, 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 SpeechRecognizerDemo {
private static final Logger logger = LoggerFactory.getLogger(SpeechRecognizerDemo.class);
private String appKey;
NlsClient client;
public SpeechRecognizerDemo(String appKey, String id, String secret, String url) {
this.appKey = appKey;
// Create a global NlsClient instance. By default, it connects to the public Alibaba Cloud service endpoint.
// Obtain an access token. In a production environment, make sure to get a new token before it expires.
AccessToken accessToken = new AccessToken(id, secret);
try {
accessToken.apply();
System.out.println("get token: " + accessToken.getToken() + ", 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 SpeechRecognizerListener getRecognizerListener(int myOrder, String userParam) {
SpeechRecognizerListener listener = new SpeechRecognizerListener() {
// This callback is fired when an intermediate recognition result is available.
// It is triggered only if setEnableIntermediateResult is set to true.
@Override
public void onRecognitionResultChanged(SpeechRecognizerResponse response) {
// getName() gets the event name, getStatus() gets the status code, and getRecognizedText() gets the transcribed text.
System.out.println("name: " + response.getName() + ", status: " + response.getStatus() + ", result: " + response.getRecognizedText());
}
// This callback is fired when the recognition is complete.
@Override
public void onRecognitionCompleted(SpeechRecognizerResponse response) {
// getName() gets the event name, getStatus() gets the status code, and getRecognizedText() gets the transcribed text.
System.out.println("name: " + response.getName() + ", status: " + response.getStatus() + ", result: " + response.getRecognizedText());
}
@Override
public void onStarted(SpeechRecognizerResponse response) {
System.out.println("myOrder: " + myOrder + "; myParam: " + userParam + "; task_id: " + response.getTaskId());
}
@Override
public void onFail(SpeechRecognizerResponse response) {
// The task_id is a unique identifier for the communication between the client and the server. Provide this task_id when reporting issues.
System.out.println("task_id: " + response.getTaskId() + ", status: " + response.getStatus() + ", status_text: " + response.getStatusText());
}
};
return listener;
}
// Calculates the audio duration equivalent to a given binary data size.
// The sample rate must be 8000 or 16000.
public static int getSleepDelta(int dataSize, int sampleRate) {
// Only 16-bit sampling is supported.
int sampleBytes = 16;
// Only single-channel audio is supported.
int soundChannel = 1;
return (dataSize * 10 * 8000) / (160 * sampleRate);
}
public void process(String filepath, int sampleRate) {
SpeechRecognizer recognizer = null;
try {
// Pass a custom user parameter.
String myParam = "user-param";
int myOrder = 1234;
SpeechRecognizerListener listener = getRecognizerListener(myOrder, myParam);
recognizer = new SpeechRecognizer(client, listener);
recognizer.setAppKey(appKey);
// Set the audio encoding format. For OPUS files, set this to InputFormatEnum.OPUS.
recognizer.setFormat(InputFormatEnum.PCM);
// Set the audio sample rate.
if(sampleRate == 16000) {
recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
} else if(sampleRate == 8000) {
recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_8K);
}
// Set whether to return intermediate recognition results.
recognizer.setEnableIntermediateResult(true);
// Set whether to enable voice activity detection (VAD).
recognizer.addCustomedParam("enable_voice_detection",true);
// This method serializes the preceding parameters into JSON, sends them to the server, and waits for confirmation.
long now = System.currentTimeMillis();
recognizer.start();
logger.info("ASR start latency : " + (System.currentTimeMillis() - now) + " ms");
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);
recognizer.send(b, len);
// This example simulates a real-time audio stream by reading from a local file.
// A sleep is added because reading from a file is faster than real-time audio capture.
// No sleep is needed when capturing audio in real time.
// In getSleepDelta, use 8000 for 8 kHz audio.
int deltaSleep = getSleepDelta(len, sampleRate);
Thread.sleep(deltaSleep);
}
// Notify the server that audio data transmission is complete and wait for the server to finish processing.
now = System.currentTimeMillis();
// Calculate the actual latency. The recognition result is typically returned after the stop() method completes.
logger.info("ASR wait for complete");
recognizer.stop();
logger.info("ASR stop latency : " + (System.currentTimeMillis() - now) + " ms");
fis.close();
} catch (Exception e) {
System.err.println(e.getMessage());
} finally {
// Close the connection.
if (null != recognizer) {
recognizer.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");
SpeechRecognizerDemo demo = new SpeechRecognizerDemo(appKey, id, secret, url);
// This example uses a local file to simulate sending real-time streaming data.
demo.process("./nls-sample-16k.wav", 16000);
//demo.process("./nls-sample.opus", 16000);
demo.shutdown();
}
}