C++ SDK
本文介绍如何使用阿里云智能语音服务提供的C++ SDK,包括SDK的安装方法及SDK代码示例。
SDK下载
当前最新版本:3.1.14,支持Linux、Windows及Android平台。发布日期:2022年11月09日。
使用SDK前,请先阅读接口说明,详情请参见接口说明。
该版本C++ SDK API 3.1和上一版本API 2.0(已下线)定义有区别,本文以当前版本为例进行介绍。
可通过以下两种方法获取SDK。
方法一:从GitHub获取最新源码,详细编译和运行方式可见下文,或查看源码中的readme.md。
git clone --depth 1 https://github.com/aliyun/alibabacloud-nls-cpp-sdk
方法二:直接从下文表中选取需要的SDK包进行下载。其中SDK源码包为SDK原始代码,需要通过下文编译方法生成集成所需的库文件。其他对应平台的SDK包内含相关库文件、头文件,无需编译。
最新SDK包 |
平台 |
MD5 |
SDK源码 |
0f0984d7afbd506b84598256edbf444e |
|
Linux x86_64 |
1d09e0b4c9c3d1b5df01c77a3312379b |
|
Linux aarch64 |
76c34a3ab397d7285963a139b9270ff4 |
|
Android |
0107c1ac58c92b94f35f6d98e2cbf6cf |
|
Windows |
9a658492e7dba4977451e74f4c88ebe0 |
其中:
alibabacloud-nls-cpp-sdk<version>-master_<github commit id>.zip为SDK源码包。
NlsCppSdk_<平台>_<版本号>_<github commit id>.tar.gz为对应平台下开发需要的SDK包,详见内部readme.md。
SDK包文件说明
scripts/build_linux.sh:SDK源码中,以Linux平台为例的示例编译脚本。
CMakeLists.txt:SDK源码中,以Linux/Android平台为例的示例代码工程CMakeList文件。
demo目录:SDK包中,集成示例代码,以Linux平台为例,如下表所示。
resource目录:SDK源码中,语音服务范例音频,可用于功能测试,如下表所示。
test0.wav
test1.wav
test2.wav
test3.wav
include:SDK源码中,SDK头文件,如下表所示。
文件名
描述
nlsClient.h
SDK实例。
nlsEvent.h
回调事件说明。
nlsGlobal.h
SDK全局头文件。
nlsToken.h
SDK Access Token实例。
iNlsRequest.h
NLS请求基础头文件。
speechRecognizerRequest.h
一句话识别。
speechSynthesizerRequest.h
语音合成、长文本语音合成。
speechTranscriberRequest.h
实时音频流识别。
FileTrans.h
录音文件识别。
lib:SDK库文件。
readme.md:SDK说明。
release.log:版本说明。
version:版本号。
文件名 |
描述 |
speechRecognizerDemo.cpp |
一句话识别示例。 |
speechSynthesizerDemo.cpp |
语音合成示例。 |
speechTranscriberDemo.cpp |
实时语音识别示例。 |
fileTransferDemo.cpp |
录音文件识别示例。 |
文件名 |
描述 |
|
测试音频(16k采样频率、16bit采样位数的音频文件)。 |
编译运行
Linux平台编译
安装工具的最低版本要求如下:
CMake 3.1
Glibc 2.5
Gcc 4.1.2
在Linux终端运行如下脚本。
进入SDK源码的根目录。
生成SDK库文件和可执行程序:srDemo(一句话识别)、stDemo(实时语音识别)、syDemo(语音合成)、daDemo(语音对话)。
./scripts/build_linux.sh
查看范例使用方式。
cd build/demo ./syDemo
Android平台编译
支持arm64-v8a、armeabi、armeabi-v7a、x86、x86_64编译指令,在SDK源码运行如下编译脚本。
./scripts/build_android.sh #默认增量编译,生成arm64-v8a架构Debug版本
./scripts/build_android.sh all debug arm64-v8a #全量编译,生成arm64-v8a架构Debug版本
./scripts/build_android.sh incr debug arm64-v8a #增量编译,生成arm64-v8a架构Debug版本
./scripts/build_android.sh all release arm64-v8a #全量编译,生成arm64-v8a架构Release版本
./scripts/build_android.sh incr release arm64-v8a #增量编译,生成arm64-v8a架构Release版本
Windows平台编译
推荐直接使用已经编译好的库NlsCppSdk_Windows_<version>_<github commit id>.zip进行集成。若有编译需求,请下载alibabacloud-nls-cpp-sdk<version>-master_<github commit id>.zip并解压到本地,或从GitHub获取最新代码,然后参考其中readme.md的编译步骤。
关键接口
基础接口
NlsClient:语音处理客户端,利用该客户端可以进行一句话识别、实时语音识别和语音合成的语音处理任务。该客户端为线程安全,建议全局仅创建一个实例。
接口名
功能描述
getInstance
获取(创建)NlsClient实例。
setLogConfig
设置日志文件与存储路径。
startWorkThread
启动工作线程数,默认1即启动一个线程,若-1则启动CPU核数的线程数。在高并发的情况下建议选择-1。
releaseInstance
销毁NlsClient对象实例。
getVersion
获取SDK版本号。
CreateSynthesizerRequest
创建一句话识别对象,线程安全,支持高并发请求。
releaseSynthesizerRequest
销毁语音合成对象,需要在当前请求的closed事件后调用。
NlsToken:创建Token对象,用于申请获取TokenId。申请新Token时需要先获取有效时间戳,若超过有效时间则再申请。若在有效时间内多次申请Token会导致TokenId错误而无法使用。
接口名
功能描述
setAccessKeyId
设置阿里云账号AccessKey ID。
setKeySecret
设置阿里云账号AccessKey Secret。
applyNlsToken
申请获取TokenId。
getToken
获取TokenId
getExpireTime
获取Token有效期时间戳(秒)。
NlsEvent:事件对象,您可以从中获取Request状态码、云端返回结果、失败信息等。
接口名
功能描述
getStatusCode
获取状态码,正常情况为0或者20000000,失败时对应失败的错误码。
getErrorMessage
在TaskFailed回调中,获取NlsRequest操作过程中出现失败时的错误信息。
getTaskId
获取任务的TaskId。
getBinaryData
获取云端返回的二进制数据。
getAllResponse
获取云端返回的识别结果。
识别接口
SpeechSynthesizerRequest:语音合成请求对象,用于语音合成及长文本语音合成。
接口名
功能描述
setOnSynthesisCompleted
设置语音合成结束回调函数。
setOnChannelClosed
设置通道关闭回调函数。
setOnTaskFailed
设置错误回调函数。
setOnBinaryDataReceived
设置语音合成二进制音频数据接收回调函数。
setOnMetaInfo
设置文本对应的日志信息接收回调函数。
setAppKey
设置AppKey。
setToken
口令认证。所有的请求都必须通过SetToken方法认证通过,才可以使用。
setUrl
设置服务URL地址。
setText
待合成音频文本内容text设置。
setVoice
发音人voice设置。
setVolume
音量volume设置。
setFormat
输出音频编码格式Format设置。
setSampleRate
音频采样率设置。
setSpeechRate
语速设置。
setPitchRate
语调设置。
setEnableSubtitle
是否开启字幕功能。
start
启动SpeechSynthesizerRequest。
cancel
不会与服务端确认关闭,直接关闭语音合成过程。
C++ SDK错误码
状态码 |
状态消息 |
原因 |
解决方案 |
10000001 |
NewSslCtxFailed |
SSL: couldn't create a context! |
建议重新初始化。 |
10000002 |
DefaultErrorCode |
return of SSL_read: error:00000000:lib(0):func(0):reason(0) |
建议重新尝试。 |
return of SSL_read: error:140E0197:SSL routines:SSL_shutdown:shutdown while in init |
|||
10000003 |
SysErrorCode |
系统错误。 |
根据系统反馈的错误信息进行处理。 |
10000004 |
EmptyUrl |
URL: The url is empty. |
传入的URL为空, 请重新填写正确URL。 |
10000005 |
InvalidWsUrl |
Could not parse WebSocket url: |
传入的URL格式错误, 请重新填写正确URL。 |
10000007 |
JsonStringParseFailed |
JSON: Json parse failed. |
JISO格式异常, 请通过日志查看具体的错误点。 |
10000008 |
UnknownWsHeadType |
WEBSOCKET: unkown head type. |
联网失败,请检查本机DNS解析和URL是否有效。 |
10000009 |
HttpConnectFailed |
HTTP: connect failed. |
与云端连接失败,请检查网络后,重试。 |
10000010 |
MemNotEnough |
内存不足。 |
请检查内存是否充足。 |
10000015 |
SysConnectFailed |
connect failed. |
联网失败,请检查本机DNS解析和URL是否有效。 |
10000100 |
HttpGotBadStatusWith403 |
Got bad status host=xxxxx line=HTTP/1.1 403 Forbidden |
链接被拒,请检查账号特别是token是否过期。 |
10000101 |
EvSendTimeout |
Send timeout. socket error: |
libevent发送event超时,请检查回调中是否有耗时任务,或并发过大导致无法及时处理事件。 |
10000102 |
EvRecvTimeout |
Recv timeout. socket error: |
libevent接收event超时,请检查回调中是否有耗时任务,或并发过大导致无法及时处理事件。 |
10000103 |
EvUnknownEvent |
Unknown event: |
未知的libevent事件,建议重新尝试。 |
10000104 |
OpNowInProgress |
Operation now in progress |
链接正在进行中,建议重新尝试。 |
10000105 |
BrokenPipe |
Broken pipe |
pipe处理不过来,建议重新尝试。 |
10000110 |
TokenHasExpired |
Gateway:ACCESS_DENIED:The token 'xxx' has expired! |
请更新Token。 |
10000111 |
TokenIsInvalid |
Meta:ACCESS_DENIED:The token 'xxx' is invalid! |
请检查token的有效性。 |
10000112 |
NoPrivilegeToVoice |
Gateway:ACCESS_DENIED:No privilege to this voice! (voice: zhinan, privilege: 0) |
此发音人无权使用。 |
10000113 |
MissAuthHeader |
Gateway:ACCESS_DENIED:Missing authorization header! |
请检查账号是否有权限,或并发是否在限度内。 |
10000120 |
Utf8ConvertError |
utf8ToGbk failed |
utf8转码失败,常为系统问题,建议重新尝试。 |
服务端响应状态码
关于服务状态码,请参见服务状态码。
代码示例
示例中使用SDK内置的默认外网访问服务URL,如果您使用阿里云上海ECS且需要使用内网访问URL,则在创建speechSynthesizerRequest的对象中设置内网访问的URL。
request->setUrl("wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1");
示例中将合成的音频保存在文件中,如果您需要播放音频且对实时性要求较高,建议使用流式播放,即边接收语音数据边播放,减少延时,而无需等待合成结束后再处理语音流。
完整示例,参见SDK压缩包中demo目录的speechSynthesizerDemo.cpp文件。
#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 "nlsClient.h"
#include "nlsEvent.h"
#include "nlsToken.h"
#include "speechSynthesizerRequest.h"
using namespace AlibabaNlsCommon;
using AlibabaNls::NlsClient;
using AlibabaNls::NlsEvent;
using AlibabaNls::LogDebug;
using AlibabaNls::LogInfo;
using AlibabaNls::LogError;
using AlibabaNls::TtsVersion;
using AlibabaNls::SpeechSynthesizerRequest;
//自定义线程参数。
struct ParamStruct {
std::string text;
std::string token;
std::string appkey;
std::string audioFile;
};
//自定义事件回调参数。
struct ParamCallBack {
public:
ParamCallBack() {
pthread_mutex_init(&mtxWord, NULL);
pthread_cond_init(&cvWord, NULL);
};
~ParamCallBack() {
pthread_mutex_destroy(&mtxWord);
pthread_cond_destroy(&cvWord);
};
std::string binAudioFile;
std::ofstream audioFile;
pthread_mutex_t mtxWord;
pthread_cond_t cvWord;
};
//全局维护一个服务鉴权Token和其对应的有效期时间戳。
//每次调用服务之前,首先判断Token是否已经过期。
//如果已经过期,则根据AccessKey ID和AccessKey Secret重新生成一个Token,并更新这个全局的token和其有效期时间戳。
//获取Token具体操作,请参见:https://help.aliyun.com/document_detail/450514.html
//说明:只需在Token即将过期时进行重新生成。所有的服务并发可共用一个Token。
std::string g_akId = "";
std::string g_akSecret = "";
std::string g_token = "";
long g_expireTime = -1;
uint64_t getNow() {
struct timeval now;
gettimeofday(&now, NULL);
return now.tv_sec * 1000 * 1000 + now.tv_usec;
}
//根据AccessKey ID和AccessKey Secret重新生成一个token,并获取其有效期时间戳
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;
}
//@brief 在接收到云端返回合成结束消息时,SDK内部线程上报Completed事件。
//@note 上报Completed事件之后,SDK内部会关闭识别连接通道。
//@param cbEvent 回调事件结构,详见nlsEvent.h。
//@param cbParam 回调自定义参数,默认为NULL,可以根据需求自定义参数。
void OnSynthesisCompleted(NlsEvent* cbEvent, void* cbParam) {
ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
// 演示如何打印/使用用户自定义参数示例。
printf("OnSynthesisCompleted: %s\n", tmpParam->binAudioFile.c_str());
// 获取消息的状态码,成功为0或者20000000,失败时对应失败的错误码。
// 当前任务的task id,方便定位问题,作为和服务端交互的唯一标识建议输出。
printf("OnSynthesisCompleted: status code=%d, task id=%s\n", cbEvent->getStatusCode(), cbEvent->getTaskId());
// 获取服务端返回的全部信息。
//printf("OnSynthesisCompleted: all response=%s\n", cbEvent->getAllResponse());
}
//@brief 合成过程发生异常时,SDK内部线程上报TaskFailed事件。
//@note 上报TaskFailed事件之后,SDK内部会关闭识别连接通道。
//@param cbEvent 回调事件结构,详见nlsEvent.h。
//@param cbParam 回调自定义参数,默认为NULL,可以根据需求自定义参数。
void OnSynthesisTaskFailed(NlsEvent* cbEvent, void* cbParam) {
ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
// 演示如何打印/使用用户自定义参数示例。
printf("OnSynthesisTaskFailed: %s\n", tmpParam->binAudioFile.c_str());
// 当前任务的task id。
printf("OnSynthesisTaskFailed: status code=%d, task id=%s, error message=%s\n",
cbEvent->getStatusCode(), cbEvent->getTaskId(), cbEvent->getErrorMessage());
}
//@brief 文本上报服务端后,收到服务端返回的二进制音频数据,SDK内部线程通过BinaryDataRecved事件上报给用户。
//@param cbEvent 回调事件结构,详见nlsEvent.h。
//@param cbParam 回调自定义参数,默认为NULL,可以根据需求自定义参数。
void OnBinaryDataRecved(NlsEvent* cbEvent, void* cbParam) {
ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
// 演示如何打印/使用用户自定义参数示例。
printf("OnBinaryDataRecved: %s\n", tmpParam->binAudioFile.c_str());
const std::vector<unsigned char>& data = cbEvent->getBinaryData(); // getBinaryData() :获取文本合成的二进制音频数据。
printf("OnBinaryDataRecved: status code=%d, task id=%s, data size=%d\n",
cbEvent->getStatusCode(), cbEvent->getTaskId(), data.size());
// 以追加形式将二进制音频数据写入文件。
if (data.size() > 0) {
tmpParam->audioFile.write((char*)&data[0], data.size());
}
}
//@brief 返回tts文本对应的日志信息,增量返回对应的字幕信息。
//@param cbEvent 回调事件结构,详见nlsEvent.h。
//@param cbParam 回调自定义参数,默认为NULL,可以根据需求自定义参数。
void OnMetaInfo(NlsEvent* cbEvent, void* cbParam) {
ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
// 演示如何打印/使用用户自定义参数示例。
printf("OnBinaryDataRecved: %s\n", tmpParam->binAudioFile.c_str());
printf("OnMetaInfo: task id=%s, respose=%s\n", cbEvent->getTaskId(), cbEvent->getAllResponse());
}
//@brief 识别结束或发生异常时,会关闭连接通道,SDK内部线程上报ChannelCloseed事件。
//@param cbEvent 回调事件结构,详见nlsEvent.h。
//@param cbParam 回调自定义参数,默认为NULL,可以根据需求自定义参数。
void OnSynthesisChannelClosed(NlsEvent* cbEvent, void* cbParam) {
ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
// 演示如何打印/使用用户自定义参数示例。
printf("OnSynthesisChannelClosed: %s\n", tmpParam->binAudioFile.c_str());
printf("OnSynthesisChannelClosed: %s\n", cbEvent->getAllResponse());
//通知发送线程, 最终识别结果已经返回, 可以调用stop()
pthread_mutex_lock(&(tmpParam->mtxWord));
pthread_cond_signal(&(tmpParam->cvWord));
pthread_mutex_unlock(&(tmpParam->mtxWord));
}
void* pthreadFunc(void* arg) {
// 0: 从自定义线程参数中获取token, 配置文件等参数.
ParamStruct* tst = (ParamStruct*)arg;
if (tst == NULL) {
std::cout << "arg is not valid." << std::endl;
return NULL;
}
// 1: 初始化自定义回调参数
ParamCallBack* cbParam = new ParamCallBack();
cbParam->binAudioFile = tst->audioFile;
cbParam->audioFile.open(cbParam->binAudioFile.c_str(), std::ios::binary | std::ios::out);
// 创建语音识别SpeechSynthesizerRequest对象.
// 默认为实时短文本语音合成请求, 支持一次性合成300字符以内的文字,
// 其中1个汉字、1个英文字母或1个标点均算作1个字符,
// 超过300个字符的内容将会报错(或者截断).
// 一次性合成超过300字符可考虑长文本语音合成功能.
// 实时短文本语音合成文档详见: https://help.aliyun.com/document_detail/84435.html
// 长文本语音合成文档详见: https://help.aliyun.com/document_detail/130509.html
TtsVersion tts_version = AlibabaNls::ShortTts;
int chars_cnt = NlsClient::getInstance()->calculateUtf8Chars(tst->text.c_str());
if (chars_cnt > 300) {
tts_version = AlibabaNls::LongTts;
}
// 2:创建语音识别SpeechSynthesizerRequest对象
SpeechSynthesizerRequest* request =
NlsClient::getInstance()->createSynthesizerRequest(tts_version);
if (request == NULL) {
printf("createSynthesizerRequest failed.\n");
cbParam->audioFile.close();
delete cbParam;
return NULL;
}
// 设置音频合成结束回调函数
request->setOnSynthesisCompleted(OnSynthesisCompleted, cbParam);
// 设置音频合成通道关闭回调函数
request->setOnChannelClosed(OnSynthesisChannelClosed, cbParam);
// 设置异常失败回调函数
request->setOnTaskFailed(OnSynthesisTaskFailed, cbParam);
// 设置文本音频数据接收回调函数
request->setOnBinaryDataReceived(OnBinaryDataRecved, cbParam);
// 设置字幕信息
request->setOnMetaInfo(OnMetaInfo, cbParam);
request->setAppKey(tst->appkey.c_str());
// 设置账号校验token, 必填参数
request->setToken(tst->token.c_str());
// 设置待合成文本, 必填参数. 文本内容必须为UTF-8编码
// 一次性合成超过300字符可考虑长文本语音合成功能.
// 长文本语音合成文档详见: https://help.aliyun.com/document_detail/130509.html
request->setText(tst->text.c_str());
// 发音人, 包含"xiaoyun", "ruoxi", "xiaogang"等. 可选参数, 默认是xiaoyun
request->setVoice("siqi");
// 访问个性化音色,访问的Voice必须是个人定制音色
//request->setPayloadParam("{\"enable_ptts\":true}");
// 音量, 范围是0~100, 可选参数, 默认50
request->setVolume(50);
// 音频编码格式, 可选参数, 默认是wav. 支持的格式pcm, wav, mp3
request->setFormat("wav");
// 音频采样率, 包含8000, 16000. 可选参数, 默认是16000
request->setSampleRate(16000);
// 语速, 范围是-500~500, 可选参数, 默认是0
request->setSpeechRate(0);
// 语调, 范围是-500~500, 可选参数, 默认是0
request->setPitchRate(0);
// 开启字幕
request->setEnableSubtitle(true);
// 3: start()为异步操作。成功则开始返回BinaryRecv事件。失败返回TaskFailed事件。
int ret = request->start();
if (ret < 0) {
printf("start() failed. may be can not connect server. please check network or firewalld\n");
NlsClient::getInstance()->releaseSynthesizerRequest(request); // start()失败,释放request对象
cbParam->audioFile.close();
delete cbParam;
return NULL;
}
struct timeval now;
struct timespec outtime;
// 4: 通知云端数据发送结束.
// stop()为无意义接口,调用与否都会跑完全程,均需等待closed事件回调.
// cancel()立即停止工作, 且不会有回调返回, 失败返回TaskFailed事件。
//ret = request->cancel();
ret = request->stop();
if (ret == 0) {
printf("wait closed callback.\n");
// 语音服务器存在来不及处理当前请求, 10s内不返回任何回调的问题,
// 然后在10s后返回一个TaskFailed回调, 所以需要设置一个超时机制.
gettimeofday(&now, NULL);
outtime.tv_sec = now.tv_sec + 30;
outtime.tv_nsec = now.tv_usec * 1000;
// 等待closed事件后再进行释放, 否则会出现崩溃
pthread_mutex_lock(&(cbParam->mtxWord));
if (ETIMEDOUT == pthread_cond_timedwait(&(cbParam->cvWord), &(cbParam->mtxWord), &outtime)) {
printf("synthesis timeout.\n");
}
pthread_mutex_unlock(&(cbParam->mtxWord));
}
NlsClient::getInstance()->releaseSynthesizerRequest(request);
cbParam->audioFile.close();
delete cbParam;
return NULL;
}
// 合成单个文本数据
int speechSynthesizerFile(const char* appkey) {
//获取当前系统时间戳,判断token是否过期。
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.text = "今天天气很棒,适合去户外旅行.";
pa.audioFile = "syAudio.wav";
// 启动一个工作线程,用于单次识别。
pthread_t pthreadId;
pthread_create(&pthreadId, NULL, &pthreadFunc, (void *)&pa);
pthread_join(pthreadId, NULL);
return 0;
}
// 合成多个文本数据。
// SDK多线程指一个文本数据对应一个线程,非一个文本数据对应多个线程。
// 示例代码为同时开启2个线程合成2个文件。
// 免费用户并发连接不能超过2个。
#define AUDIO_TEXT_NUMS 2
#define AUDIO_TEXT_LENGTH 64
#define AUDIO_FILE_NAME_LENGTH 32
int speechTranscriberMultFile(const char* appkey) {
//获取当前系统时间戳判断token是否过期。
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;
}
}
const char syAudioFiles[AUDIO_TEXT_NUMS][AUDIO_FILE_NAME_LENGTH] =
{
"syAudio0.wav",
"syAudio1.wav"
};
const char texts[AUDIO_TEXT_NUMS][AUDIO_TEXT_LENGTH] =
{
"今日天气真不错,我想去操作踢足球.",
"明天有大暴雨,还是宅在家里看电影吧."
};
ParamStruct pa[AUDIO_TEXT_NUMS];
for (int i = 0; i < AUDIO_TEXT_NUMS; i ++) {
pa[i].token = g_token;
pa[i].appkey = appkey;
pa[i].text = texts[i];
pa[i].audioFile = syAudioFiles[i];
}
std::vector<pthread_t> pthreadId(AUDIO_TEXT_NUMS); // 启动工作线程,同时识别音频文件。
for (int j = 0; j < AUDIO_TEXT_NUMS; j++) {
pthread_create(&pthreadId[j], NULL, &pthreadFunc, (void *)&(pa[j]));
}
for (int j = 0; j < AUDIO_TEXT_NUMS; j++) {
pthread_join(pthreadId[j], NULL);
}
return 0;
}
int main(int argc, char* argv[]) {
if (argc < 4) {
printf("params is not valid. Usage: ./demo <your appkey> <your AccessKey ID> <your AccessKey Secret>\n");
return -1;
}
std::string appkey = argv[1];
g_akId = argv[2];
g_akSecret = argv[3];
// 根据需要设置SDK输出日志。可选。
// 此处表示SDK日志输出至log-synthesizer.txt。
// LogDebug表示输出所有级别日志,支持LogDebug、LogInfo、LogWarning、LogError。
// 400表示单个文件400MB。50表示50个日志文件循环记录。
int ret = NlsClient::getInstance()->setLogConfig(
"log-synthesizer", LogDebug, 400, 50);
if (ret < 0) {
printf("set log failed.\n");
return -1;
}
// 私有云部署的情况下可进行直连IP的设置
// 必须在startWorkThread()前调用
//NlsClient::getInstance()->setDirectHost("106.15.83.44");
// 存在部分设备在设置了dns后仍然无法通过SDK的dns获取可用的IP,
// 可调用此接口主动启用系统的getaddrinfo来解决这个问题.
//NlsClient::getInstance()->setUseSysGetAddrInfo(true);
// 启动工作线程, 在创建请求和启动前必须调用此函数, 可理解为对NlsClient的初始化
// 入参为负时, 启动当前系统中可用的核数。
// 200并发以下推荐入参为1, 更高并发入参推荐可看readme。
NlsClient::getInstance()->startWorkThread(1);
// 合成单个文本
speechSynthesizerFile(appkey.c_str());
// 合成单个文本
//speechSynthesizerMultFile(appkey.c_str());
// 所有工作完成,进程退出前,释放nlsClient。
// 请注意releaseInstance()非线程安全, 需要确认所有请求都停止工作才可释放。
NlsClient::releaseInstance();
return 0;
}