C++ SDK

Updated at:

Use the SDK for C++ to stream audio and receive intermediate results and final sentence-level results. The Linux x86_64 examples use version 3.3.0b.

Quick start

Prepare a Linux build environment, obtain the SDK, configure credentials, and run the complete example. For request parameters and response events, see Real-time speech recognition API reference.

The discontinued API 2.0 has different definitions from API 3.1 used in this example.

Prepare the environment

The minimum Linux build tool versions are CMake 3.0, glibc 2.5, and GCC 4.8.5.

The example uses Linux x86_64, GCC 10.2.1, and glibc 2.32.

Obtain and install the SDK

Source repository

Obtain the source code from the SDK GitHub repository. The default branch may differ from the downloadable package. Follow the readme.md for the version being built.

git clone --depth 1 https://github.com/aliyun/alibabacloud-nls-cpp-sdk

Downloadable packages

Build the source package to generate libraries. Precompiled platform packages contain libraries and header files.

SDK package

Platform

MD5

alibabacloud-nls-cpp-sdk3.3.0b-master_cbcac53.zip

SDK source code

7257c0998654e611cf2e8ca9867670ef

NlsCppSdk_Linux-x86_64_3.3.0b_cbcac53.tar.gz

Linux x86_64

9a93df607f26f1558bc1043a425af6d1

NlsCppSdk_Linux-aarch64_3.1.15_fa30fba.tar.gz

Linux aarch64

76c34a3ab397d7285963a139b9270ff4

alibabacloud-nls-cpp-sdk<version>-master_<github commit id>.zip is a source package; NlsCppSdk_<platform>_<version>_<github commit id>.tar.gz is a precompiled platform package. See the included readme.md for instructions.

Build and integrate

Build from source

Run the following command in the source root directory to generate SDK libraries and examples, including srDemo (short sentence recognition), stDemo (real-time speech recognition), syDemo (speech synthesis), and daDemo (voice interaction).

./scripts/build_linux.sh

The generated headers and libraries are in build/install/NlsSdk3.X_LINUX. In the build/demo directory, run ./stDemo to display usage instructions for the packaged example.

Precompiled packages

Extract the SDK package for the CPU architecture, and select a Debug or Release package. Use the same C++ ABI as the application. CXX11 packages use _GLIBCXX_USE_CXX11_ABI=1.

Important

In the Linux x86_64 Release CXX11 package for version 3.3.0b, demo/build_linux_demo.sh still specifies ABI=0. When using this package, set the example build option to ABI=1 to avoid linker errors.

Configure credentials

Before running the example, set the following environment variables for the process. The AppKey and AccessKey must belong to the account used to access the service. Do not hard-code credentials or write them to logs.

Environment variable

Description

NLS_APPKEY_ENV

The AppKey of the project.

NLS_AK_ENV

AccessKey ID.

NLS_SK_ENV

AccessKey secret.

export NLS_APPKEY_ENV='<appkey>'
export NLS_AK_ENV='<accesskey-id>'
export NLS_SK_ENV='<accesskey-secret>'

When running the example in an IDE, also set these variables in its run configuration. The example obtains a token through NlsToken, caches the token and its expiration time, and refreshes it shortly before expiration. Concurrent requests can share a valid token.

Sample code

The complete example initializes the client, obtains a token, handles asynchronous events, sends audio, and releases resources. Use test0.wav from the SDK package and place it in the working directory. The concurrent example also uses test1.wav.

The sample audio has a sample rate of 16000 Hz, and the project uses the Universal model in the console. For other audio, select a model that supports the audio's use case. For model configuration, see Manage projects.

The example waits for the started event before sending audio, stops sending after a failure event, and propagates failures as a nonzero process exit code. On success, TranscriptionCompleted is followed by the channel-closed event.

#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <ctime>
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <sys/time.h>
#include <errno.h>
#include <atomic>
#include "nlsClient.h"
#include "nlsEvent.h"
#include "nlsToken.h"
#include "speechTranscriberRequest.h"

#define FRAME_SIZE 3200
#define SAMPLE_RATE 16000

using namespace AlibabaNlsCommon; 
using AlibabaNls::NlsClient; 
using AlibabaNls::NlsEvent; 
using AlibabaNls::LogDebug; 
using AlibabaNls::LogInfo; 
using AlibabaNls::LogError;
using AlibabaNls::SpeechTranscriberRequest;

struct ParamStruct {
  std::string fileName;
  std::string appkey; 
  std::string token;
  int result = -1; 
};

struct ParamCallBack {
 public:
  ParamCallBack() {
    pthread_mutex_init(&mtxWord, NULL);
    pthread_cond_init(&cvWord, NULL);
  };
  ~ParamCallBack() {
    pthread_mutex_destroy(&mtxWord);
    pthread_cond_destroy(&cvWord);
  };

  std::atomic<bool> started{false}, closed{false}, failed{false}, completed{false};
  int userId;
  char userInfo[8];
  pthread_mutex_t mtxWord;
  pthread_cond_t cvWord;
};

std::string g_akId = "";
std::string g_akSecret = "";
std::string g_token = "";
long g_expireTime = -1;
int g_sync_timeout = 0;
struct timeval tv;
struct timeval tv1;

int generateToken(std::string akId, std::string akSecret,
                  std::string* token, long* expireTime) {
  NlsToken nlsTokenRequest;
  nlsTokenRequest.setAccessKeyId(akId); 
  nlsTokenRequest.setKeySecret(akSecret); 

  int ret = nlsTokenRequest.applyNlsToken();
  if (ret < 0) {

    printf("generateToken Failed, error code:%d msg:%s\n",
        ret, nlsTokenRequest.getErrorMsg());
    return ret;
  }
  *token = nlsTokenRequest.getToken();
  *expireTime = nlsTokenRequest.getExpireTime();
  return 0;
}

unsigned int getSendAudioSleepTime(int dataSize,
                                   int sampleRate,
                                   int compressRate) { 

  const int sampleBytes = 16;     
  const int soundChannel = 1;     
  int bytes = (sampleRate * sampleBytes * soundChannel) / 8;     
  int bytesMs = bytes / 1000;     
  int sleepMs = (dataSize * compressRate) / bytesMs;
  return sleepMs; 
}

void onTranscriptionStarted(NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;

  printf("onTranscriptionStarted: %d\n", tmpParam->userId);

  printf("onTranscriptionStarted: status code=%d, task id=%s\n",
      cbEvent->getStatusCode(), cbEvent->getTaskId());

  pthread_mutex_lock(&(tmpParam->mtxWord));
  tmpParam->started = true;
  pthread_cond_signal(&(tmpParam->cvWord));
  pthread_mutex_unlock(&(tmpParam->mtxWord));
} 

void onSentenceBegin(NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;

  printf("onSentenceBegin: %d\n", tmpParam->userId);
  printf("onSentenceBegin: status code=%d, task id=%s, index=%d, time=%d\n",
      cbEvent->getStatusCode(), cbEvent->getTaskId(),
      cbEvent->getSentenceIndex(), 
      cbEvent->getSentenceTime() 
  );

}

void onSentenceEnd(NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;

  printf("onSentenceEnd: %d\n", tmpParam->userId);
  printf("onSentenceEnd: status code=%d, task id=%s, index=%d, time=%d, begin_time=%d, result=%s\n",
      cbEvent->getStatusCode(),
      cbEvent->getTaskId(),
      cbEvent->getSentenceIndex(), 
      cbEvent->getSentenceTime(), 
      cbEvent->getSentenceBeginTime(), 
      cbEvent->getResult()    
  );

}

void onTranscriptionResultChanged(NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;

  printf("onTranscriptionResultChanged: %d\n", tmpParam->userId);
  printf("onTranscriptionResultChanged: status code=%d, task id=%s, index=%d, time=%d, result=%s\n",
      cbEvent->getStatusCode(),
      cbEvent->getTaskId(),
      cbEvent->getSentenceIndex(), 
      cbEvent->getSentenceTime(), 
      cbEvent->getResult()    
  );

}

void onTranscriptionCompleted(NlsEvent* cbEvent, void* cbParam) {
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
  tmpParam->completed = true;

  printf("onTranscriptionCompleted: %d\n", tmpParam->userId);
  printf("onTranscriptionCompleted: status code=%d, task id=%s\n",
      cbEvent->getStatusCode(),
      cbEvent->getTaskId());
}

void onTaskFailed(NlsEvent* cbEvent, void* cbParam) { 
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
  pthread_mutex_lock(&tmpParam->mtxWord);
  tmpParam->failed = true;
  pthread_cond_broadcast(&tmpParam->cvWord);
  pthread_mutex_unlock(&tmpParam->mtxWord); 

  printf("onTaskFailed: %d\n", tmpParam->userId); 
  printf("onTaskFailed: status code=%d, task id=%s, error message=%s\n", 
      cbEvent->getStatusCode(), 
      cbEvent->getTaskId(), 
      cbEvent->getErrorMessage()
  );     

}

void onChannelClosed(NlsEvent* cbEvent, void* cbParam) {     
  ParamCallBack* tmpParam = (ParamCallBack*)cbParam;     

  printf("onChannelClosed: %d, %s\n", tmpParam->userId, tmpParam->userInfo); 
  printf("onChannelClosed: response=%s\n", cbEvent->getAllResponse());

  pthread_mutex_lock(&(tmpParam->mtxWord));
  tmpParam->closed = true;
  pthread_cond_broadcast(&(tmpParam->cvWord));
  pthread_mutex_unlock(&(tmpParam->mtxWord));
}

void* pthreadFunction(void* arg) {
  int sleepMs = 0;
  int ret = 0;
  ParamCallBack *cbParam = NULL;

  cbParam = new ParamCallBack();
  cbParam->userId = rand() % 100;
  strcpy(cbParam->userInfo, "User.");

  ParamStruct *tst = (ParamStruct *) arg; 
  if (tst == NULL) {
    printf("arg is not valid\n"); 
    delete cbParam;
    return NULL;
  } 

  std::ifstream fs;
  fs.open(tst->fileName.c_str(), std::ios::binary | std::ios::in);
  if (!fs) {
    printf("Cannot open %s\n", tst->fileName.c_str());
    delete cbParam;
    return NULL;
  }
  
  SpeechTranscriberRequest* request =
      NlsClient::getInstance()->createTranscriberRequest();
  if (request == NULL) {
    printf("createTranscriberRequest failed\n");
    delete cbParam;
    return NULL;
  }

  request->setOnTranscriptionStarted(onTranscriptionStarted, cbParam);

  request->setOnTranscriptionResultChanged(onTranscriptionResultChanged, cbParam);

  request->setOnTranscriptionCompleted(onTranscriptionCompleted, cbParam);

  request->setOnSentenceBegin(onSentenceBegin, cbParam);

  request->setOnSentenceEnd(onSentenceEnd, cbParam);

  request->setOnTaskFailed(onTaskFailed, cbParam);

  request->setOnChannelClosed(onChannelClosed, cbParam);

  request->setAppKey(tst->appkey.c_str());

  request->setToken(tst->token.c_str());

  request->setUrl("wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1");
  request->setFormat("opus");

  request->setSampleRate(SAMPLE_RATE);

  request->setIntermediateResult(true);

  request->setPunctuationPrediction(true);

  request->setInverseTextNormalization(true);

  struct timespec outtime;
  struct timeval now;
  
  ret = request->start();
  if (ret < 0) {
    printf("start() failed. may be can not connect server. please check network or firewalld\n");
    NlsClient::getInstance()->releaseTranscriberRequest(request); 
    delete cbParam;
    return NULL;
  } else {
    if (g_sync_timeout == 0) {

      printf("wait started callback.\n");

      gettimeofday(&now, NULL);
      outtime.tv_sec = now.tv_sec + 5;
      outtime.tv_nsec = now.tv_usec * 1000;
      pthread_mutex_lock(&(cbParam->mtxWord));
      while (!cbParam->started && !cbParam->failed && !cbParam->closed) {
      if (ETIMEDOUT == pthread_cond_timedwait(&(cbParam->cvWord), &(cbParam->mtxWord), &outtime)) {
        printf("start timeout.\n");
        pthread_mutex_unlock(&(cbParam->mtxWord));
        request->cancel();
        NlsClient::getInstance()->releaseTranscriberRequest(request);
        delete cbParam;
        return NULL;
      }
      }
      pthread_mutex_unlock(&(cbParam->mtxWord));
    } else {
      
    }
  }

  while (cbParam->started && !cbParam->failed && !cbParam->closed && !fs.eof()) {
    uint8_t data[FRAME_SIZE] = {0};
    fs.read((char *) data, sizeof(uint8_t) * FRAME_SIZE); 
    size_t nlen = fs.gcount();
    if (nlen <= 0) {
      continue;
    }

    ret = request->sendAudio(data, nlen, ENCODER_OPUS); 
    if (ret < 0) {

      printf("send data fail.\n");
      cbParam->failed = true; 
      break;
    } 

    sleepMs = getSendAudioSleepTime(nlen, SAMPLE_RATE, 1); 
    
    usleep(sleepMs * 1000);
  } 

  printf("sendAudio done.\n");

  fs.close();

  ret = cbParam->failed || cbParam->closed ? -1 : request->stop();
  if (ret == 0) {
      if (g_sync_timeout == 0) {

        printf("wait closed callback.\n");

        gettimeofday(&now, NULL);
        outtime.tv_sec = now.tv_sec + 5;
        outtime.tv_nsec = now.tv_usec * 1000;

        pthread_mutex_lock(&(cbParam->mtxWord));
        while (!cbParam->closed) {
        if (ETIMEDOUT == pthread_cond_timedwait(&(cbParam->cvWord), &(cbParam->mtxWord), &outtime)) {
          printf("stop timeout\n");
          pthread_mutex_unlock(&(cbParam->mtxWord));
          NlsClient::getInstance()->releaseTranscriberRequest(request);
          delete cbParam;
          return NULL;
        }
        }
        pthread_mutex_unlock(&(cbParam->mtxWord));
      } else {
        
      }
  } else {
    printf("stop ret is %d\n", ret);
    cbParam->failed = true;
    if (!cbParam->closed) request->cancel();
  }

  NlsClient::getInstance()->releaseTranscriberRequest(request);
  tst->result = (!cbParam->failed && cbParam->completed) ? 0 : -1;
  delete cbParam;
  return NULL;
}

int speechTranscriberFile(const char* appkey) {

  std::time_t curTime = std::time(0);
  if (g_expireTime - curTime < 10) {
    printf("the token will be expired, please generate new token by AccessKey-ID and AccessKey-Secret.\n");
    if (generateToken(g_akId, g_akSecret, &g_token, &g_expireTime) < 0) {
      return -1;
    } 
  }

  ParamStruct pa;
  pa.token = g_token;
  pa.appkey = appkey;
  pa.fileName = "test0.wav";

  pthread_t pthreadId;
  if (pthread_create(&pthreadId, NULL, &pthreadFunction, (void *)&pa) != 0) return -1;
  pthread_join(pthreadId, NULL);
  return pa.result;
}

#define AUDIO_FILE_NUMS 2
#define AUDIO_FILE_NAME_LENGTH 32
int speechTranscriberMultFile(const char* appkey) {

  std::time_t curTime = std::time(0);
  if (g_expireTime - curTime < 10) {
    printf("the token will be expired, please generate new token by AccessKey-ID and AccessKey-Secret.\n");
    if (generateToken(g_akId, g_akSecret, &g_token, &g_expireTime) < 0) {
      return -1;
    }
  }

  char audioFileNames[AUDIO_FILE_NUMS][AUDIO_FILE_NAME_LENGTH] = {
      "test0.wav", 
      "test1.wav"
  };
  ParamStruct pa[AUDIO_FILE_NUMS];
  for (int i = 0; i < AUDIO_FILE_NUMS; i ++) {
    pa[i].token = g_token; 
    pa[i].appkey = appkey;
    pa[i].fileName = audioFileNames[i]; 
  } 

  std::vector<pthread_t> pthreadId(AUDIO_FILE_NUMS);
  int created = 0;
  for (; created < AUDIO_FILE_NUMS; ++created) {
    if (pthread_create(&pthreadId[created], NULL, &pthreadFunction, &pa[created]) != 0) break;
  }
  int result = created == AUDIO_FILE_NUMS ? 0 : -1;
  for (int j = 0; j < created; ++j) {
    pthread_join(pthreadId[j], NULL);
    if (pa[j].result != 0) result = -1;
  }
  return result;
}

int main(int argc, char* argv[]) {
  const char* appkeyEnv = getenv("NLS_APPKEY_ENV");
  const char* akEnv = getenv("NLS_AK_ENV");
  const char* skEnv = getenv("NLS_SK_ENV");
  if (!appkeyEnv || !*appkeyEnv || !akEnv || !*akEnv || !skEnv || !*skEnv) {
    std::cerr << "Set NLS_APPKEY_ENV, NLS_AK_ENV, and NLS_SK_ENV." << std::endl;
    return EXIT_FAILURE;
  }
  std::string appkey = appkeyEnv;
  g_akId = akEnv;
  g_akSecret = skEnv;

  int ret = NlsClient::getInstance()->setLogConfig(
      "log-transcriber", LogError, 10, 3);
  if (ret < 0) {
    printf("set log failed.\n");
    NlsClient::releaseInstance();
    return EXIT_FAILURE;
  }

  if (g_sync_timeout > 0) {
    NlsClient::getInstance()->setSyncCallTimeout(g_sync_timeout);
  }

  NlsClient::getInstance()->startWorkThread(1);

  int result = speechTranscriberFile(appkey.c_str());
  // To transcribe two files concurrently, replace the preceding call with:
  // int result = speechTranscriberMultFile(appkey.c_str());

  NlsClient::releaseInstance();

  return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
Note

This example does not enable the preconnection pool. In the Linux x86_64 Release CXX11 precompiled package for version 3.3.0b, enabling the preconnection pool (for example, by calling setPreconnectedPool(2)) may cause an invalid memory free and terminate the process. Do not enable the preconnection pool when using this precompiled package. To use a preconnection pool, build a Debug library from source.

Add the SDK include and lib directories to the project's compiler and linker settings. With NlsSdk3.X_LINUX in the current directory, compile the example file demo.cpp with the following command:

g++ -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=1 demo.cpp   -I NlsSdk3.X_LINUX/include -L NlsSdk3.X_LINUX/lib   -lalibabacloud-idst-speech -lpthread -o demo
export LD_LIBRARY_PATH="$PWD/NlsSdk3.X_LINUX/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"

Usage notes

  • The example calculates sending intervals for 16000 Hz, 16-bit, mono audio. For 8 kHz PCM, wait 100 ms after sending 1600 bytes; for 16 kHz PCM, wait 100 ms after sending 3200 bytes. In OPUS/OPU mode, the input to the SDK is still PCM. The recommendation is 640 bytes followed by a 20 ms wait. Send live recordings at the capture rate; rate limiting is needed when simulating a live recording with a file.

  • sendAudio: stop sending audio if the return value is negative. After TranscriptionCompleted or TaskFailed, the SDK closes the channel. Do not continue sending audio.

  • In asynchronous mode, a return from start() does not indicate successful startup. Wait for a started or failure event. A return from stop() does not indicate that the interaction has ended. Wait for the channel-closed event. Call setSyncCallTimeout to enable synchronous mode.

  • SDK multithreading uses one thread per audio source, not multiple threads sending the same source. The example provides single-file and two-file concurrent entry points. Release the global client only after all requests have ended. releaseInstance() is not thread-safe.

Free users cannot exceed two concurrent connections. For fewer than 200 concurrent requests, one worker thread is recommended. See the SDK readme.md for recommendations at higher concurrency.

The sentence silence threshold is the silence duration after an utterance. Its valid range is 200–2000 ms, with a default of 800 ms. Semantic sentence detection overrides silence-based sentence detection and requires intermediate results to be enabled.

Use setPayloadParam to pass custom or advanced parameters as a JSON string, such as {"vad_model":"farfield"}.

Internal network access

For internal network access from an Alibaba Cloud ECS instance in Shanghai, set the following URL after creating the SpeechTranscriberRequest.

request->setUrl("ws://nls-gateway-cn-shanghai-internal.aliyuncs.com/ws/v1");

Key interfaces

NlsClient

NlsClient is the client for short sentence recognition, real-time speech recognition, and speech synthesis. It is thread-safe. We recommend creating one global instance.

Method

Available since

Description

getInstance

2.x

Gets or creates the NlsClient instance.

setLogConfig

2.x

Sets the log file and storage path.

Supported log levels are LogDebug, LogInfo, LogWarning, and LogError. The size of each log file and the number of rotating files can be configured.

setDirectHost

3.x

Sets the server IPv4 address directly, bypassing DNS resolution. Call this method before startWorkThread.

setAddrInFamily

3.1.12

Sets the socket address family. The default is AF_INET, which returns only IPv4 address information. Call this method before startWorkThread.

setUseSysGetAddrInfo

3.1.13

Switches to the system resolver if libevent DNS resolution cannot resolve the address. Call this method before startWorkThread.

setSyncCallTimeout

3.1.17

Sets the synchronous call timeout in milliseconds. The default is 0, which disables synchronous mode.

In synchronous mode:

  • start() blocks until it receives a server result

  • stop() blocks until the close() callback is triggered

setPreconnectedPool

3.3.0

Sets a preconnection pool for each domain URL.

  • Effects:

    Creates persistent connections for a domain URL and automatically reuses connections after requests end

    • Reduces connection time before each request

    • Significantly reduces first-packet latency

  • Conflicts with long-connection mode and disables that mode if it is enabled.

  • Do not use for Tingwu workloads

  • Call this method before startWorkThread.

startWorkThread

3.x

Starts worker threads. The default is 1. A value of -1 starts as many threads as there are CPU cores and is recommended for high concurrency. This method initializes NlsClient and must be called.

releaseInstance

3.x

Destroys the NlsClient instance.

getVersion

2.x

Gets the SDK version.

createTranscriberRequest

2.x

Creates a real-time speech recognition request. This method is thread-safe and supports high concurrency.

releaseTranscriberRequest

2.x

Destroys a real-time speech recognition request. Call this method after the request's closed event.

Add exception handling and release the request when an error occurs. Otherwise, resource leaks can disrupt operation, for example by preventing recognition results from being returned.

NlsToken

NlsToken obtains access tokens. Use getExpireTime to obtain the expiration timestamp and refresh the token shortly before expiration. Requesting a new token does not automatically invalidate an existing token that has not expired.

Method

Description

setAccessKeyId

Sets the Alibaba Cloud account's AccessKey ID.

setKeySecret

Sets the Alibaba Cloud account's AccessKey secret.

setDomain

Sets the domain. Optional.

setServerVersion

Sets the API version. Optional.

setServerResourcePath

Sets the service resource path. Optional.

setRegionId

Sets the service region ID. Optional.

setAction

Sets the action. Optional.

applyNlsToken

Requests a token.

getToken

Gets the token.

getExpireTime

Gets the token expiration timestamp in seconds.

getErrorMsg

Gets the error message.

NlsEvent

NlsEvent provides request status codes, server results, and failure information.

Method

Description

getStatusCode

Gets the status code: 0 or 20000000 for success, or the corresponding error code for failure.

getErrorMessage

Gets the error message for a failed NlsRequest operation in the TaskFailed callback.

getTaskId

Gets the task ID.

getAllResponse

Gets the recognition result returned by the server.

getResult

Gets intermediate and final recognition results.

getSentenceIndex

Gets the sentence index for real-time speech recognition.

getSentenceTime

Gets the current position in the processed audio, in milliseconds.

getSentenceBeginTime

Gets the time of the corresponding SentenceBegin event, in milliseconds.

SpeechTranscriberRequest

SpeechTranscriberRequest represents a real-time recognition request for long audio. See speechTranscriberRequest.h for the interface definitions.

Method

Available since

Description

setOnTaskFailed

2.x

Sets the failure callback.

setOnTranscriptionStarted

2.x

Sets the callback for the start of real-time recognition.

setOnSentenceBegin

2.x

Sets the sentence-start callback.

setOnSentenceEnd

2.x

Sets the sentence-end callback.

setOnTranscriptionResultChanged

2.x

Sets the callback for intermediate recognition results.

setOnTranscriptionCompleted

2.x

Sets the callback for completion of the service.

setOnChannelClosed

2.x

Sets the channel-closed callback.

setOnMessage

3.1.16

Sets an optional callback for all server response messages, which the application must parse. Call setEnableOnMessage to enable it.

setAppKey

2.x

Sets the AppKey.

setToken

2.x

Sets the authentication token. Every request must be authenticated with setToken before it can be used.

setUrl

2.x

Sets the service URL.

setIntermediateResult

2.x

Specifies whether to return intermediate recognition results.

Default: false.

setPunctuationPrediction

2.x

Specifies whether to add punctuation during postprocessing.

Default: false.

setInverseTextNormalization

2.x

Specifies whether to normalize numbers during postprocessing.

Default: false.

setFormat

2.x

Sets the audio encoding: PCM (default), OPUS (recommended), or OPU.

setSampleRate

2.x

Sets the audio sample rate.

Supports 16000 and 8000 Hz. Default: 16000 Hz.

setSemanticSentenceDetection

2.x

Specifies whether to use semantic sentence detection.

setMaxSentenceSilence

2.x

Sets the VAD threshold.

setCustomizationId

2.x

Sets the custom model.

setVocabularyId

2.x

Sets the hotword vocabulary ID for the current request.If hotwords are configured in both the console and the SDK, the SDK configuration takes precedence and overrides the console configuration.

setTimeout

2.x

Sets the connection timeout. Default: 5000 ms.

setSessionId

2.x

Sets the session ID.

setOutputFormat

2.x

Sets the output text encoding to UTF-8 or GBK.

setPayloadParam

2.x

Sets parameters as a JSON string.

setContextParam

2.x

Sets custom parameters as a JSON string.

AppendHttpHeaderParam

2.x

Sets custom HTTP headers for the WebSocket handshake.

setSendTimeout

3.1.14

Sets the send timeout. Default: 5000 ms.

setRecvTimeout

3.1.14

Sets the receive timeout. Default: 15000 ms. Takes effect only when enabled with setEnableRecvTimeout.

setEnableRecvTimeout

3.1.16

Enables the receive timeout. The default is false (disabled). When enabled, a prolonged absence of server responses triggers an error.

getOutputFormat

3.1.16

Gets the configured output text encoding.

setEnableOnMessage

3.1.16

Enables the server-message callback.

getTaskId

3.1.17

Gets the task_id of the current request.

start

2.x

Starts the SpeechTranscriberRequest.

stop

2.x

Stops real-time recognition normally, confirming closure with the server.

cancel

2.x

Closes real-time recognition directly, without confirming closure with the server.

control

2.x

Requests an update to recognition parameters on the server.

sendAudio

2.x

Sends audio data. The recommended size per call is 640–16384 bytes.

SDK package files

  • scripts/build_linux.sh: sample Linux build script in the SDK source.

  • CMakeLists.txt: CMake project file for the Linux SDK example.

  • demo: integration examples in the SDK package. The Linux examples are listed below.

    File

    Description

    speechRecognizerDemo.cpp

    Short sentence recognition example.

    speechSynthesizerDemo.cpp

    Speech synthesis example.

    speechTranscriberDemo.cpp

    Real-time speech recognition example.

    fileTransferDemo.cpp

    Recording file recognition example.

  • resource: sample audio in the SDK source for functional testing.

    File

    Description

    • test0.wav

    • test1.wav

    • test2.wav

    • test3.wav

    Test audio files with a 16 kHz sample rate and 16-bit samples.

  • include: SDK header files, as listed below.

    File

    Description

    nlsClient.h

    SDK client instance.

    nlsEvent.h

    Callback events.

    nlsGlobal.h

    Global SDK header.

    nlsToken.h

    SDK access token instance.

    iNlsRequest.h

    Base NLS request header.

    speechRecognizerRequest.h

    Short sentence recognition.

    speechSynthesizerRequest.h

    Speech synthesis and long-text speech synthesis.

    speechTranscriberRequest.h

    Real-time audio stream recognition.

    FileTrans.h

    Recording file recognition.

  • lib: SDK libraries.

  • readme.md: SDK instructions.

  • release.log: Release notes.

  • version: Version number.

C++ SDK error codes

Status code

Status message

Cause

Solution

0

Success

Success

-10

DefaultError

Default error

Not currently used.

-11

JsonParseFailed

Invalid JSON format

Check whether the input string is valid JSON.

-12

JsonObjectError

Invalid JSON object

Try again.

-13

MallocFailed

Malloc failed

Check whether sufficient memory is available.

-14

ReallocFailed

Realloc failed

Check whether sufficient memory is available.

-15

InvalidInputParam

Invalid input parameter

Not currently used.

-50

InvalidLogLevel

Invalid log level

Check the configured log level.

-51

InvalidLogFileSize

Invalid log file size

Check the log file size parameter.

-52

InvalidLogFileNum

Invalid log file count

Check the log file count parameter.

-100

EncoderExistent

The NLS encoder already exists

Try again.

-101

EncoderInexistent

The NLS encoder does not exist

Reinitialize the encoder.

-102

OpusEncoderCreateFailed

Failed to create the Opus encoder

Reinitialize the encoder.

-103

OggOpusEncoderCreateFailed

Failed to create the OggOpus encoder

Reinitialize the encoder.

-104

InvalidEncoderType

Invalid encoder type

OPUS may have been disabled at compile time but is being used. Check ENCODER_TYPE.

-150

EventClientEmpty

The main worker thread pointer is null because it has been released

Reinitialize by calling startWorkThread().

-151

SelectThreadFailed

Failed to select a worker thread because worker threads have not been initialized

Reinitialize by calling startWorkThread().

-160

StartCommandFailed

Failed to send the start command

Try again.

-161

InvokeStartFailed

The request state is invalid for start

Check whether the request has not been created or has already completed.

-162

InvokeSendAudioFailed

The request state is invalid for sendAudio

Check whether the request has started (the started callback has been received) or has already completed.

-163

InvalidOpusFrameSize

Invalid Opus frame length; the default is 640 bytes

In OPU encoding mode, sendAudio accepts only 640 bytes per frame.

-164

InvokeStopFailed

The request state is invalid for stop

Check whether the request has not started (the started callback has not been received) or has already completed.

-165

InvokeCancelFailed

The request state is invalid for cancel

Check whether the request has not started (the started callback has not been received) or has already completed.

-166

InvokeStControlFailed

The request state is invalid for stControl

Check whether the request has not started (the started callback has not been received) or has already completed.

-200

NlsEventEmpty

The NLS event is null

Internal SDK error: the NlsEvent frame is missing.

-201

NewNlsEventFailed

Failed to create NlsEvent

Internal SDK error: failed to create the NlsEvent frame.

-202

NlsEventMsgEmpty

The message in the NLS event is empty

parseJsonMsg() found an empty message string during parsing.

-203

InvalidNlsEventMsgType

Invalid message type in the NLS event

Internal SDK error: the event type in the NlsEvent frame is invalid.

-204

InvalidNlsEventMsgStatusCode

Invalid message status code in the NLS event

Internal SDK error: the event message status in the NlsEvent frame is invalid.

-205

InvalidNlsEventMsgHeader

Invalid message header in the NLS event

Internal SDK error: the event message header in the NlsEvent frame is invalid.

-250

CancelledExitStatus

cancel has been called

Not currently used.

-251

InvalidWorkStatus

Invalid working state

Internal SDK error: the internal state of the current request is invalid.

-252

InvalidNodeQueue

Invalid NodeQueue in workThread

Internal SDK error: the pending request is invalid. Release the current request and try again.

-300

InvalidRequestParams

Invalid request input parameter

The data passed to sendAudio is empty.

-301

RequestEmpty

The request pointer is null

Internal SDK error: the current request has been released. Release the current request and try again.

-302

InvalidRequest

Invalid request

Internal SDK error: the current request has been released. Release the current request and try again.

-303

SetParamsEmpty

The input parameter is empty

Check whether the input parameter is empty.

-350

GetHttpHeaderFailed

Failed to obtain the HTTP header

Internal SDK error. Check the logs for details.

-351

HttpGotBadStatus

Invalid HTTP state

Internal SDK error. Check the logs for details.

-352

WsResponsePackageFailed

Failed to parse the WebSocket response

Internal SDK error. Check the logs for details.

-353

WsResponsePackageEmpty

The parsed WebSocket response is empty

Internal SDK error. Check the logs for details.

-354

WsRequestPackageEmpty

The WebSocket request is empty

Internal SDK error. Check the logs for details.

-355

UnknownWsFrameHeadType

Unknown WebSocket frame header type

Internal SDK error. Check the logs for details.

-356

InvalidWsFrameHeaderSize

Invalid WebSocket frame header size

Internal SDK error. Check the logs for details.

-357

InvalidWsFrameHeaderBody

Invalid WebSocket frame header body

Internal SDK error. Check the logs for details.

-358

InvalidWsFrameBody

Invalid WebSocket frame body

Internal SDK error. Check the logs for details.

-359

WsFrameBodyEmpty

The frame data is empty, commonly because malformed data was received

Internal SDK error. Check the logs for details.

-400

NodeEmpty

The node pointer is null

Release the current request and try again.

-401

InvaildNodeStatus

Invalid node state

Internal SDK error. Release the current request and try again.

-402

GetAddrinfoFailed

Failed to resolve the address through DNS

Internal SDK error. Check whether DNS is available in the current environment.

-403

ConnectFailed

Failed to connect to the network

Check whether the network is available.

-404

InvalidDnsSource

DNS is unavailable on the current device

Internal SDK error. Check whether DNS is available in the current environment.

-405

ParseUrlFailed

Invalid URL

Check whether the configured URL is valid.

-406

SslHandshakeFailed

SSL handshake failed

Internal SDK error. Check network availability and try again.

-407

SslCtxEmpty

SSL_CTX is null

Internal SDK error. Check network availability and try again.

-408

SslNewFailed

SSL_new failed

Internal SDK error. Check network availability and try again.

-409

SslSetFailed

Failed to set SSL parameters

Internal SDK error. Check network availability and try again.

-410

SslConnectFailed

SSL_connect failed

Internal SDK error. Check network availability and try again.

-411

SslWriteFailed

Failed to send data over SSL

Internal SDK error. Check network availability and try again.

-412

SslReadSysError

A SYSCALL error occurred while receiving data over SSL

Internal SDK error. Check network availability and try again.

-413

SslReadFailed

Failed to receive data over SSL

Internal SDK error. Check network availability and try again.

-414

SocketFailed

Failed to create a socket

Internal SDK error. Check network availability and try again.

-415

SetSocketoptFailed

Failed to set socket parameters

Internal SDK error. Check network availability and try again.

-416

SocketConnectFailed

Failed to establish a socket connection

Internal SDK error. Check network availability and try again.

-417

SocketWriteFailed

Failed to send data through the socket

Internal SDK error. Check network availability and try again.

-418

SocketReadFailed

Failed to receive data through the socket

Internal SDK error. Check network availability and try again.

-430

NlsReceiveFailed

Failed to receive NLS frame data

Internal SDK error. Check network availability and try again.

-431

NlsReceiveEmpty

The received NLS frame data is empty

Internal SDK error. Check network availability and try again.

-432

ReadFailed

Failed to receive data

Internal SDK error. Check network availability and try again.

-433

NlsSendFailed

Failed to send NLS data

Internal SDK error. Check network availability and try again.

-434

NewOutputBufferFailed

Failed to create a buffer

Internal SDK error. Check whether sufficient memory is available.

-435

NlsEncodingFailed

Failed to encode audio

Internal SDK error. Release the current request and try again.

-436

EventEmpty

The event is null

Internal SDK error. Release the current request and try again.

-437

EvbufferTooMuch

Too much data in evbuffer

Internal SDK error: the send buffer is full (maximum 320000 for 16 kHz audio and 160000 for 8 kHz audio). Check whether audio is sent too frequently or too much data is sent at once.

-438

EvutilSocketFailed

Failed to set evutil parameters

Internal SDK error. Release the current request and try again.

-439

InvalidExitStatus

Invalid exit state

Check whether the current request has already been canceled.

-450

InvalidAkId

Invalid AccessKey ID for the Alibaba Cloud account

Check whether the AccessKey ID is empty.

-451

InvalidAkSecret

Invalid AccessKey secret for the Alibaba Cloud account

Check whether the AccessKey secret is empty.

-452

InvalidAppKey

Invalid project AppKey

Check whether the project AppKey is empty.

-453

InvalidDomain

Invalid domain

Check whether the input domain is empty.

-454

InvalidAction

Invalid action

Check whether the input action is empty.

-455

InvalidServerVersion

Invalid ServerVersion

Check whether the input ServerVersion is empty.

-456

InvalidServerResource

Invalid ServerResource

Check whether the input ServerResource is empty.

-457

InvalidRegionId

Invalid RegionId

Check whether the input RegionId is empty.

-500

InvalidFileLink

Invalid recording file URL

The recording file URL for transcription is empty.

-501

ErrorStatusCode

Invalid status code

Recording file transcription returned an error. For more information, see the error code.

-502

IconvOpenFailed

Failed to allocate a conversion descriptor

Conversion between UTF-8 and GBK failed.

-503

IconvFailed

Encoding conversion failed

Conversion between UTF-8 and GBK failed.

-504

ClientRequestFaild

The account client request failed

Recording file transcription failed.

-999

NlsMaxErrorCode

Other status codes

Status message

Cause

Solution

10000001

NewSslCtxFailed

SSL: couldn't create a context!

Reinitialize the encoder.

10000002

DefaultErrorCode

return of SSL_read: error:00000000:lib(0):func(0):reason(0)

Try again.

return of SSL_read: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init

10000003

SysErrorCode

System error.

Troubleshoot based on the error message returned by the system.

10000004

EmptyUrl

URL: The url is empty.

The input URL is empty. Specify a valid URL.

10000005

InvalidWsUrl

Could not parse WebSocket url:

The input URL format is invalid. Specify a valid URL.

10000007

JsonStringParseFailed

JSON: Json parse failed.

The JSON format is invalid. Check the logs for details.

10000008

UnknownWsHeadType

WEBSOCKET: unkown head type.

Failed to connect to the network. Check local DNS resolution and the URL.

10000009

HttpConnectFailed

HTTP: connect failed.

Failed to connect to the server. Check the network and try again.

10000010

MemNotEnough

Insufficient memory.

Check whether sufficient memory is available.

10000015

SysConnectFailed

connect failed.

Failed to connect to the network. Check local DNS resolution and the URL.

10000100

HttpGotBadStatusWith403

Got bad status host=xxxxx line=HTTP/1.1 403 Forbidden

The connection was rejected. Check the account and, in particular, whether the token has expired.

10000101

EvSendTimeout

Send timeout. socket error:

The libevent send event timed out. Check for time-consuming tasks in callbacks or excessive concurrency that prevents events from being processed promptly.

10000102

EvRecvTimeout

Recv timeout. socket error:

The libevent receive event timed out. Check for time-consuming tasks in callbacks or excessive concurrency that prevents events from being processed promptly.

10000103

EvUnknownEvent

Unknown event:

Unknown libevent event. Try again.

10000104

OpNowInProgress

Operation now in progress

The connection is in progress. Try again.

10000105

BrokenPipe

Broken pipe

The pipe cannot keep up with processing. Try again.

10000110

TokenHasExpired

Gateway:ACCESS_DENIED:The token 'xxx' has expired!

Refresh the token.

10000111

TokenIsInvalid

Meta:ACCESS_DENIED:The token 'xxx' is invalid!

Check whether the token is valid.

10000112

NoPrivilegeToVoice

Gateway:ACCESS_DENIED:No privilege to this voice! (voice: zhinan, privilege: 0)

The voice cannot be used with the current permissions.

10000113

MissAuthHeader

Gateway:ACCESS_DENIED:Missing authorization header!

Check account permissions and whether concurrency is within the limit.

10000120

Utf8ConvertError

utf8ToGbk failed

UTF-8 conversion failed, commonly due to a system issue. Try again.

20000000

SuccessStatusCode

Success

Server response status codes

For service status codes, see API reference.

FAQ

Troubleshooting scenarios

How do I resolve {"TaskFailed":"connect failed."} {"channeclClosed": "nls request finished."} when calling the real-time speech recognition API with the C++ SDK?

  • This issue occasionally occurs in C++ SDK 3.0 and earlier and does not require special attention. In 3.1 and later, it may be caused by the network in the runtime environment. Check the local network.

  • If no TaskId is returned, the connection was closed during connection establishment. Repeated API calls are not required for real-time speech interaction and are subject to concurrency and timeout limits. Exceeding the concurrency limit returns a limit error. A WebSocket connection is automatically closed if no audio is sent for more than 10 seconds, but a TaskId is returned in that case.

How do I resolve status_text:Gateway:IDLE_TIMEOUT:Websocket session is idle for too long time, the last directive is 'StartTranscription'! during real-time speech recognition with the C++ SDK?

  1. The connection is closed automatically after an idle timeout because no data has been sent to the server for more than 10 seconds. Also check that the URI is correct: wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1. If this occurs, add a retry mechanism to send the request again.

  2. A sudden influx of requests to the server may also prevent an instance from processing requests promptly. Retry the request.

How do I resolve error 10000002 when creating multiple recognition channels with the C++ real-time speech recognition SDK integrated into MRCP?

Error code 10000002 is the SDK default error code. For the underlying error, see Resource temporarily unavailable. This generally occurs when no data is sent after connection establishment, causing a WebSocket timeout. The next command sent is StartTranscription.

Can I use a GCC version later than 5.0 with C++ SDK 3.0 and later for speech synthesis and speech recognition?

Yes. GCC 4.8.5 and later are supported on Linux. GCC 4.8.5, 5.5.0, and 8.4.0 have been verified to compile and run successfully.

Why can't I link to the framework?

The framework contains both Objective-C and C++ code. Call it from a file with the .mm extension, and ensure that the project header and library paths are configured correctly.

How do I resolve the DNS resolution error "ali-recog-skd.log:AliSpeech_C++SDK(ERROR): GetInetAddressByHostname:252 DNS: resolved timeout.ali-recog-skd.log:AliSpeech_C++SDK(ERROR): start:76 start failed: DNS: resolved timeout..unimrcpserver_current.log: [ERROR] [[./ali/AliRecogChannel.cpp:772,onTaskFailed]]Ali Task start failed Msg :DNS: resolved timeout., start finised." for a C++ SDK ASR request?

  • Earlier versions (3.0 and earlier): this issue is more likely under high concurrency or when the device DNS is busy. Upgrade to 3.1.X or restart the request.

  • Later versions (3.0 and later): protection against this issue is implemented. If it still occurs occasionally, DNS is busy on the device. Restart the request.

How do I resolve compilation failures after changing add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) to add_definitions(-D_GLIBCXX_USE_CXX11_ABI=1) in CMakeLists.txt when integrating the new C++ SDK into another project?

In addition to CMakeLists.txt, update this parameter throughout the project, including config/linux.thirdparty.debug.cmake and config/linux.thirdparty.release.cmake. Search all directories for _GLIBCXX_USE_CXX11_ABI and update it.

What is the difference between the earlier NlsSdkCpp2.0 and the newer NlsSdkCpp3.X?

NlsSdkCpp2.0 uses one thread per request and synchronous interfaces.

NlsSdkCpp3.X uses the third-party libevent library to handle events centrally, provides higher concurrency performance, and uses asynchronous interfaces by default. From 3.1.17, synchronous calls can be enabled with setSyncCallTimeout.

Does the C++ SDK support the C11 standard? How do I resolve SDK linking failures?

The application and SDK must use the same _GLIBCXX_USE_CXX11_ABI. The default build script for the 3.3.0b source selects the ABI based on the GCC major version. The CXX11 precompiled package uses ABI=1 and cannot be mixed directly with an ABI=0 application.

How do I resolve "nls-gateway-cn-shanghai.aliyuncs.com dns failed: nodename nor servname provided, or not known" when the C++ SDK demo works but integration into a project fails?

  1. The SDK checks all enabled protocol families (IPv4 and IPv6) on the device when resolving DNS. nls-gateway-cn-shanghai.aliyuncs.com does not support IPv6 and returns a resolution error, causing SDK DNS resolution to fail and exit. Disable IPv6 on the device, or use setAddrInFamily in 3.1.12 and later to configure the address family.

  2. Upgrade to 3.1.12 or later.

How do I resolve "[dnsEventCallback:465]Node:0x7f087c001030 ai_canonname: nls-gateway-cn-shanghai.aliyuncs.com.gds.alibabadns.com[dnsEventCallback:477]Node:0x7f087c001030 IpV4:106.15.XX.XX[connectProcess:1329]Node:0x7f087c001030 sockFd:41[connectProcess:1347]Node:0x7f087c001030 new Socket ip:106.15.XX.XX port:443 Fd:41.[socketConnect:1458]Node:0x7f087c001030 Connect failed:Network is unreachable. retry..." when the C++ SDK demo works but project integration fails?

This indicates that the network is unreachable. The logs show that the connection to the IP address resolved by DNS failed, and a ping test confirms that the network is unreachable. Local DNS interception causes the SDK's libevent library to obtain an incorrect IP address through its evdns_getaddrinfo function.

Solutions:

  • Before 3.1.12, manually replace evdns_getaddrinfo() with the system getaddrinfo().

  • In version 3.1.12, modify add_definitions(-DNLS_USE_NATIVE_GETADDRINFO) in CMakeLists.txt.

  • In 3.1.12 and later, use setDirectHost() to set a correct IP address resolved outside the SDK.

  • This issue is resolved in 3.1.13 and later. If it still occurs at runtime, call setUseSysGetAddrInfo(true).

What error occurs if the text passed to the C++ SDK for speech synthesis is not UTF-8 encoded?

If the input text is not UTF-8 encoded and contains Chinese characters, the speech synthesis SDK start call fails with Socket recv failed, errorCode: 0. Error code 0 indicates that the server has closed the connection. Check whether the input text is UTF-8 encoded.