Java SDK
This topic describes how to install the real-time speech recognition SDK for Java and use a complete example to stream audio and obtain recognition results.
Prerequisites
Before you use the SDK, read the real-time speech recognition API overview.
Starting from version 2.1.0, nls-sdk-long-asr was renamed nls-sdk-transcriber. When you upgrade, remove nls-sdk-long-asr and add the required callbacks as prompted by the compiler.
Download and install the SDK
-
<dependency> <groupId>com.alibaba.nls</groupId> <artifactId>nls-sdk-transcriber</artifactId> <version>2.2.1</version> </dependency>After you extract the demo, run
mvn packagein the pom directory. The command generates the executable JAR file nls-example-transcriber-2.0.0-jar-with-dependencies.jar in the target directory. You can copy the JAR file to the target server for functional validation and stress testing. -
Validate the service.
Run the following command and provide the required parameters as prompted. The logs/nls.log file is generated in the directory where the command runs.
java -cp nls-example-transcriber-2.0.0-jar-with-dependencies.jar com.alibaba.nls.client.SpeechTranscriberDemo -
Run a stress test.
Run the following command and provide the required parameters as prompted. The service URL is
wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1.Use a PCM audio file with a sample rate of 16 kHz. Set the concurrency based on the service capacity that you purchased.
java -jar nls-example-transcriber-2.0.0-jar-with-dependencies.jarImportantCharges are incurred if the stress test uses more than two concurrent calls.
Key classes
NlsClient: A speech processing client used for short sentence recognition, real-time speech recognition, and speech synthesis tasks. The client is thread-safe. We recommend that you create only one instance for an application.
SpeechTranscriber: A real-time speech recognition class used to configure request parameters and send requests and audio data. The class is not thread-safe.
SpeechTranscriberListener: A real-time speech recognition result listener. The class is not thread-safe.
For more information, see the Java API reference.
Considerations for SDK calls:
NlsClient uses the Netty framework. Creating an NlsClient object consumes time and resources, but the object can be reused. Align the creation and shutdown of NlsClient with the lifecycle of the application.
A SpeechTranscriber object cannot be reused. Each recognition task requires a separate SpeechTranscriber object. For example, to run recognition tasks for N audio files, create N SpeechTranscriber objects.
Each SpeechTranscriberListener object corresponds to one SpeechTranscriber object. Do not use the same SpeechTranscriberListener object for multiple SpeechTranscriber objects. Otherwise, the recognition tasks cannot be distinguished.
The SDK for Java depends on Netty. If the application also depends on Netty, use Netty 4.1.17.Final or later.
Sample code
-
The sample audio has a sample rate of 16,000 Hz. In the console, set the model of the project associated with the AppKey to Universal Model to obtain correct recognition results. If you use other audio, select a model that supports the corresponding audio scenario. For more information about model settings, see Manage projects.
-
The sample uses the public service URL by default. To access the service from an ECS instance in the China (Shanghai) region over an internal network, specify the following internal URL 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, configure environment variables for the access credentials. Set the AccessKey ID, AccessKey secret, and AppKey in ALIYUN_AK_ID, ALIYUN_AK_SECRET, and NLS_APP_KEY, respectively.
The sample connects to
wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1by default. To use another service URL, set the NLS_GATEWAY_URL environment variable.
The sample obtains a token dynamically at runtime. For more information, see Obtain a token.
The value of max_sentence_silence ranges from 200 to 6000 milliseconds.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import com.alibaba.nls.client.AccessToken;
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 speech recognition API.
* Simulate a real-time audio stream by using a local file.
* Measure 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 one NlsClient instance for the lifecycle of the application.
AccessToken accessToken = new AccessToken(id, secret);
try {
accessToken.apply();
System.out.println("get token: " + ", expire time: " + accessToken.getExpireTime());
client = new NlsClient(url, accessToken.getToken());
} catch (IOException e) {
e.printStackTrace();
}
}
private static SpeechTranscriberListener getTranscriberListener() {
SpeechTranscriberListener listener = new SpeechTranscriberListener() {
// This callback is triggered when an intermediate result is available.
// The callback is triggered only if setEnableIntermediateResult is set to true.
@Override
public void onTranscriptionResultChange(SpeechTranscriberResponse response) {
System.out.println("task_id: " + response.getTaskId() +
", name: " + response.getName() +
// The status code 20000000 indicates a successful request.
", status: " + response.getStatus() +
// The sentence index starts from 1.
", index: " + response.getTransSentenceIndex() +
// The current recognition result.
", result: " + response.getTransSentenceText() +
// The duration of processed audio in milliseconds.
", time: " + response.getTransSentenceTime());
}
@Override
public void onTranscriberStart(SpeechTranscriberResponse response) {
// task_id uniquely identifies communication between the client and server.
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());
}
// This callback is triggered when the server detects the end of a sentence.
@Override
public void onSentenceEnd(SpeechTranscriberResponse response) {
System.out.println("task_id: " + response.getTaskId() +
", name: " + response.getName() +
// The status code 20000000 indicates a successful request.
", status: " + response.getStatus() +
// The sentence index starts from 1.
", index: " + response.getTransSentenceIndex() +
// The current recognition result.
", result: " + response.getTransSentenceText() +
// The confidence score.
", confidence: " + response.getConfidence() +
// The sentence start time.
", begin_time: " + response.getSentenceBeginTime() +
// The duration of 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 uniquely identifies communication between the client and server.
System.out.println("task_id: " + response.getTaskId() + ", status: " + response.getStatus() + ", status_text: " + response.getStatusText());
}
};
return listener;
}
// Calculate the audio duration that corresponds to the binary data size.
// sampleRate supports 8000 or 16000.
public static int getSleepDelta(int dataSize, int sampleRate) {
// Only 16-bit sampling is supported.
int sampleBytes = 16;
// Only mono audio 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);
// Set the input audio format.
transcriber.setFormat(InputFormatEnum.PCM);
// Set the input audio sample rate.
transcriber.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
// Specify whether to return intermediate recognition results.
transcriber.setEnableIntermediateResult(false);
// Specify whether to add punctuation to recognition results.
transcriber.setEnablePunctuation(true);
// Specify whether to normalize recognition results, such as converting words to numbers.
transcriber.setEnableITN(false);
// Set the VAD sentence silence threshold. The default value is 800 ms.
//transcriber.addCustomedParam("max_sentence_silence", 600);
// Specify whether to use semantic sentence detection.
//transcriber.addCustomedParam("enable_semantic_sentence_detection",false);
// Specify whether to filter disfluencies.
//transcriber.addCustomedParam("disfluency",true);
// Specify whether to enable word-level information.
//transcriber.addCustomedParam("enable_words",true);
// Set the VAD noise threshold. Valid values range from -1 to +1.
// A value closer to -1 increases the probability that noise is treated as speech.
// A value closer to +1 increases the probability that speech is treated as noise.
// This is an advanced parameter. Test the recognition results after each adjustment.
//transcriber.addCustomedParam("speech_noise_threshold",0.3);
// Set the ID of a trained custom language model.
//transcriber.addCustomedParam("customization_id","custom-language-model-id");
// Set the ID of a trained custom hotword vocabulary.
//transcriber.addCustomedParam("vocabulary_id","custom-vocabulary-id");
// Serialize the parameters to JSON, send them to the server, and wait 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);
// Reading a local file is faster than a real-time stream, so the sample pauses between packets.
// For a live stream, remove the pause. For 8 kHz audio, pass 8000 as the second argument.
int deltaSleep = getSleepDelta(len, 16000);
Thread.sleep(deltaSleep);
}
// Notify the server that all audio data is sent and wait for processing to complete.
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 sample uses a local file to simulate a real-time audio stream.
// In production, capture or receive an 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();
}
}