全部产品
弹性计算 会员服务 网络 安全 移动云 数加·大数据分析及展现 数加·大数据应用 管理与监控 云通信 阿里云办公 培训与认证 智能硬件
存储与CDN 数据库 域名与网站(万网) 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网 更多

C++ SDK

更新时间:2018-06-14 15:26:35

一、SDK 使用说明

功能介绍

语音C++ SDK提供一句话识别服务,提供将短语音转成文字的功能。

SDK下载地址

一句话识别C++ SDK

demo 编译,运行步骤

  1. Linux环境下,请确认本地系统以安装Cmake,最低版本2.4
  2. 解压SDK压缩包,执行[./build.sh]编译demo
  3. 编译完毕,进入demo目录,执行demo
  • 由于链接顺序对编译会造成影响,如果提示编译错误,可以调整CMakeLists.txt调整-lrealTimeUnity -lopus前后顺序
  • 由于此sdk没有采用c11,如果报C++11编译错误,可以在CMakeLists.txt中添加-D_GLIBCXX_USE_CXX11_ABI=0

SDK调用顺序

  1. 创建一个的NlsSpeechCallback实例callbck,并分别设置结果返回、操作错误和通道关闭的回调函数.

  2. 创建一个NlsClient的对象nlc,该对象只需创建一次并且可以重复使用。

  3. 准备好config.txt配置文件,其内包含app-key、url等参数,详细见本文末尾的示例。

  4. 通过调用2步中的nlc对象的createAsrRequest方法获得一个NlsRequest 对象的指针(用完记得释放),该NlsRequest对象不能重复使用,但是可以重复创建。

  5. 调用4中返回的NlsRequest对象的Authorize方法进行设置用户id和scret。

  6. 调用4中 NlsRequest对象的start方法.

  7. 调用4中的NlsRequest对象的sendAudio方法发送语音流,如有结果,则会触发1中设置的相关回调函数。

  8. 语音发送完后,调用 调用4中 NlsRequest对象的stop方法

  • 注意:Request的create()——>start()——>send()——>stop()——>delete操作,请在一个线程内部完成。不要夸线程。否则会有异常。Demo.cpp内部实现亦是在一个线程内部完成。

SDK调用注意事项

  1. sdk采用ISO 标准c++编写,运行环境最低要求:glibc:2.5 gcc 版本:4.1.2.

  2. sdk内部采用pthread多线程机制,因此在linux环境下可以直接使用,如果需要在windows环境下使用,需要额外安装能够在windows环境下运行的pthread的支持库(ftp://sourceware.org/pub/pthreads-win32/).

  3. 针对linux环境,sdk提供的库文件为librealTimeUnity.so 和librealTimeUnity-32.so,分别对应64位运行环境和32位运行环境.

  4. sdk依赖于第三方库,主要是(libssl.a libcrypto.a libopus.so.0),其中前两个来自于openssl,版本为1.0.2j,最后一个是用于opus编解码,版本不限.

  5. sdk提供的第三方库均为64位,如需32位,请根据如上版本自行下载源码进行编译.

  6. sdk自带对pcm格式语音进行opu压缩发送,只需将config文件中的Format改为opu即可,输入流仍然为pcm格式。

  7. 并发或多线程支持,如果需要在您的应用支持多个并发请求,请不要重复创建NlsClient对象。只需要在不同的线程中创建NlsRequest对象,同时创建不同的NlsListener,并传入NlsRequest对象。这样就可以并发不同请求并且拿到正确的相应的结果。

  8. 语音数据发送控制:

    • 语音数据是实时的,不用sleep控制速率,直接发送即可。
    • 语音数据来自文件,发送时需要控制速率,使单位时间内发送的数据大小接近单位时间原始语音数据存储的大小。
    • 对于8k pcm 编码数据,建议每发送3200字节 sleep 200 ms。
    • 对于16k pcm 编码数据,建议每发送6400字节 sleep 200 ms。
    • 对于其它编码格式的数据,用户根据压缩比,自行估算,比如压缩比为10:1的 16k opus,需要每发送6400/10=640 sleep 200ms。

重要接口说明

NlsClient:语音SDK的Client,相当于所有语音相关处理类的factory,全局创建一个实例即可。线程安全。可通过NlsClient创建语音识别request对象。


  1. /**
  2. * @brief 设置日志文件与存储路径
  3. * @param logOutputFile 日志文件
  4. * @param logLevel 日志级别,默认1(Error : 1、Warn : 2、Debug : 3)
  5. * @return 成功则返回0,失败返回-1
  6. */
  7. int setLogConfig(const char* logOutputFile, int loglevel);
  8. /**
  9. * @brief 创建实时语音识别Request对象
  10. * @param onResultReceivedEvent 事件回调接口
  11. * @param config 配置文件
  12. * @return 成功返回NlsRequest对象,否则返回NULL
  13. */
  14. NlsRequest* createRealTimeRequest(NlsSpeechCallback* onResultReceivedEvent, const char* config);
  15. /**
  16. * @brief 创建一句话识别Request对象
  17. * @param onResultReceivedEvent 事件回调接口
  18. * @param config 配置文件
  19. * @return 成功返回NlsRequest对象,否则返回NULL
  20. */
  21. NlsRequest* createAsrRequest(NlsSpeechCallback* onResultReceivedEvent, const char* config);
  22. /**
  23. * @brief 创建语音合成Request对象
  24. * @param onResultReceivedEvent 事件回调接口
  25. * @param config 配置文件
  26. * @return 成功返回NlsRequest对象,否则返回NULL
  27. */
  28. NlsRequest* createTtsRequest(NlsSpeechCallback* onResultReceivedEvent, const char* config);
  29. /**
  30. * @brief 创建NLu Request对象
  31. * @param onResultReceivedEvent 事件回调接口
  32. * @param config 配置文件
  33. * @return 成功返回NlsRequest对象,否则返回NULL
  34. */
  35. NlsRequest* createNluRequest(NlsSpeechCallback* onResultReceivedEvent, const char* config);
  36. /**
  37. * @brief NlsClient对象实例
  38. * @param sslInitial 是否初始化openssl 线程安全,默认为true
  39. * @return NlsClient对象
  40. */
  41. static NlsClient* getInstance(bool sslInitial = true);

NlsRequest:语音识别请求对象,通过调用该类的start()、stop()、sendAudio()等方法来打开、关闭或发送语音数据。。


  1. /**
  2. * @brief 参数设置
  3. * @param value appKey字符串
  4. * @return 成功则返回0,否则返回-1
  5. */
  6. int SetParam(const char* str_key, const char* str_value); // add format
  7. /**
  8. * @brief 启动Request
  9. * @note 阻塞操作,等待服务端响应、或10秒超时才会返回
  10. * @return 成功则返回0,否则返回-1
  11. */
  12. int Start();
  13. /**
  14. * @brief 会与服务端确认关闭,正常停止SpeechRecognizerRequest链接操作
  15. * @note 阻塞操作,等待服务端响应才会返回
  16. * @return 成功则返回0,否则返回-1
  17. */
  18. int Stop();
  19. /**
  20. * @brief 不会与服务端确认关闭,直接关闭SpeechRecognizerRequest链接
  21. * @note 正常情况下,建议使用stop结束操作
  22. * @return 成功则返回0,否则返回-1
  23. */
  24. int Cancel();
  25. /**
  26. * @brief 授权校验
  27. * @param id
  28. * @param scret
  29. * @return 成功则返回实际发送长度,失败返回-1
  30. */
  31. int Authorize(const char* id, const char* scret);
  32. /**
  33. * @brief 发送语音数据
  34. * @param data 语音数据
  35. * @param dataSize 语音数据长度
  36. * @return 成功则返回实际发送长度,失败返回-1
  37. */
  38. int SendAudio(char* data, size_t num_byte);

NlsSpeechCallback:回调函数集合的对象,语音结果、异常等回调的统一入口。


  1. /**
  2. * @brief 设置结果消息接受回调函数
  3. * @param _event 回调方法
  4. * @param para 用户传入参数, 默认为NULL
  5. * @return void
  6. */
  7. void setOnMessageReceiced(NlsCallbackMethod onMessageReceived,void*para=NULL);
  8. /**
  9. * @brief 设置错误回调函数
  10. * @note 在请求过程中出现错误时,触发该回调。用户可以在事件的消息头中检查状态码和状态消息,以确认失败的具体原因。
  11. * @param _event 回调方法
  12. * @param para 用户传入参数, 默认为NULL
  13. * @return void
  14. */
  15. void setOnOperationFailed(NlsCallbackMethod _event, void*para=NULL);
  16. /**
  17. * @brief 设置通道关闭回调函数
  18. * @note 在请求过程中通道关闭时,触发该回调.
  19. * @param _event 回调方法
  20. * @param para 用户传入参数, 默认为NULL
  21. * @return void
  22. */
  23. void setOnChannelClosed(NlsCallbackMethod _event, void*para=NULL);
  24. /**
  25. * @brief 二进制音频数据接收回调函数
  26. * @note 仅在tts语音合成中触发该回调
  27. * @param _event 回调方法
  28. * @param para 用户传入参数, 默认为NULL
  29. * @return void
  30. */
  31. void setOnBinaryDataReceived(NlsCallbackMethod _event, void*para=NULL);

NlsEvent:回调事件对象,用户可以从中获取Request状态码、云端返回结果、失败信息等。


  1. /**
  2. * @brief 获取状态码
  3. * @note 正常情况为0或者200,失败时对应失败的错误码。错误码参考SDK文档说明。
  4. * @return string
  5. */
  6. std::string getStausCode();
  7. /**
  8. * @brief 获取云端返回的结果
  9. * @note json格式
  10. * @return string
  11. */
  12. std::string getResponse();
  13. /**
  14. * @brief 获取NlsRequest操作过程中出现失败时的错误信息
  15. * @note 在Failed回调函数中使用
  16. * @return string
  17. */
  18. std::string getErrorMessage();
  19. /**
  20. * @brief 获取云端返回的二进制数据
  21. * @note 仅用于tts语音合成功能
  22. * @return vector<unsigned char>
  23. */
  24. std::vector<unsigned char> getBinaryData();
  25. /**
  26. * @brief 获取当前所发生Event的类型
  27. * @note Event值参照NlsClient.h说明
  28. * @return EventType
  29. */
  30. EventType getMsgType();
  31. /**
  32. * @brief 获取当前request对象id
  33. * @return string
  34. */
  35. std::string getId();
  36. /**
  37. * @brief 设置当前request对象id
  38. * @return
  39. */
  40. void setId(std::string id);

更多详细介绍参见SDK压缩包内部include/NlsClient.h。


错误码

服务端错误码:

状态 status_code CloseFrame状态码 HTTP语义
成功 200 1000 成功处理
请求格式有误 400 4400 错误请求
需要鉴权信息 401 4401 请求要求身份验证
鉴权失败 403 4403 服务器拒绝请求
超出最大并发量 429 4429 太多请求
请求超时 408 4408 处理请求超时
处理出错 500 4500 服务器内部错误
服务不可用 503 4503 服务不可用
服务不可用 503 4503 服务不可用

SDK错误码

状态 status_code
“status_code not found” 999
“GetInetAddressByHostname fail” 1028
“asr frame type must be text” 1030
“Json reader fail” 1031
“Authorization mustn’t be null” 10002
“get time fail” 10003
“PING no implementaion” 10004
“ConnectToHttp fail” 10005
“Json convert fail” 10006
“SSLv23_client_method fail” 10015
“SSL_CTX_new fail” 10016
“SSL_new fail” 10017
“not support mode” 10020
“ssl connect fail” 参考SSL官方错误码
“convert to utf8 error” 参考系统错误码

结果回调说明

返回的识别结果result是一个response的对象:

  1. {
  2. "status" : "1",// 服务器状态,0为失败,非零为成功
  3. "id" : "",// 透传系统始终的uuid,服务端配置是否返回
  4. "finish" : "1",// 0为未结束,非零为结束,识别是否已经结束
  5. "results" : {
  6. "asr_out" : {
  7. "result" : "",// 语音识别结果
  8. "status" : 1,// 服务器状态,0为失败,非零为成功
  9. "finish" : 1,// 0为未结束,非零为结束,识别是否已经结束
  10. "version" : "4.0"
  11. },
  12. "out" : {}//保留字段
  13. },
  14. "bstream_attached" : false,// 应答包的后面是不是还接着二进制语音流。
  15. "version" : "4.0"// 协议版本号
  16. }

SDK参数配置

config.txt 内容如下:

  1. #注意:
  2. #1. 以#开头的行为注释,处理时会直接跳过该行。
  3. #2. 配置中每行只能出现一条配置且以key:value的形式出现,切忌中间、行头、行尾不要出现空格,除非key, value字段中本身含有空格
  4. Url:wss://nls.dataapi.aliyun.com:443
  5. #AppKey 不同领域对应不同的AppKey,详细可见官网简介
  6. AppKey:nls-service
  7. #Language:EN/CHN
  8. #VocabId 表示所要使用的热词对应的id,详细可见官网热词说明文档
  9. #VocabId:
  10. #KeyWordListId 表示所要检测的关键词对应的id,详细可见官网关键词说明文档
  11. #KeyWordListId:
  12. #ResponseMode 支持streaming, normal
  13. ResponseMode:streaming
  14. #Format 支持pcm 、opu
  15. Format:pcm
  16. AsrInEnable:true

完整示例

  1. #include <string>
  2. #include <iostream>
  3. #include <vector>
  4. #include <fstream>
  5. #include <sstream>
  6. #include "pthread.h"
  7. #include "NlsClient.h"
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #ifdef _WINDOWS_COMPILE_
  11. #include <windows.h>
  12. #else
  13. #include <unistd.h>
  14. #endif
  15. using namespace std;
  16. #define FRAME_SIZE 6400
  17. NlsSpeechCallback* gCallback = NULL;
  18. NlsClient* gNlc = NULL;
  19. struct ParamStruct {
  20. std::string filename;
  21. std::string config;
  22. int threadcount;
  23. int count;
  24. std::string id;
  25. std::string key;
  26. bool isSendData;
  27. };
  28. void* func(void* arg)
  29. {
  30. int loop = 0;
  31. while (loop ++ < 1) {
  32. try {
  33. ParamStruct* tst = (ParamStruct*)arg;
  34. if (tst == NULL) {
  35. std::cout << "filename is not valid" << endl;
  36. return 0;
  37. }
  38. ifstream fs;
  39. fs.open(tst->filename.c_str(), ios::binary | ios::in);
  40. if (!fs) {
  41. throw ("file isn't exist");
  42. }
  43. /*******************第一种调用方*****************************/
  44. /*
  45. * 创建一句话识别 NlsRequest,第一个参数为callback对象,第二个参数为config.txt文件.
  46. * request对象在一个会话周期内可以重复使用.
  47. * 会话周期是一个逻辑概念. 比如Demo中,指读取, 发送完整个音频文件数据的时间.
  48. * 音频文件数据发送结束时, 可以delete request.
  49. * request方法调用,比如create, start, sendAudio, stop, delete必须在.
  50. * 同一线程内完成,跨线程使用可能会引起异常错误.
  51. */
  52. //下面是以读取config.txt方式创建request
  53. NlsRequest* request = gNlc->createAsrRequest(gCallback, tst->config.c_str());
  54. /***********************************************************/
  55. /*******************第二种调用方式*************************
  56. //以参数设置方式创建request
  57. NlsRequest* request = gNlc->createAsrRequest(gCallback, NULL);
  58. request->SetParam("AppKey","nls-service");
  59. request->SetParam("AsrInEnable","true");
  60. request->SetParam("ResponseMode","normal");
  61. request->SetParam("Format","pcm");
  62. request->SetParam("Url","wss://nls.dataapi.aliyun.com:443");
  63. *********************************************************/
  64. if (request == NULL) {
  65. std::cout << "createAsrRequest fail" << endl;
  66. return 0;
  67. }
  68. request->Authorize(tst->id.c_str(), tst->key.c_str());
  69. //start()为非异步操作,发送start指令之后,会等待服务端响应、或超时之后才返回
  70. if (request->Start() < 0) {
  71. std::cout << "start fail" << endl;
  72. delete request;
  73. request = NULL;
  74. return 0;
  75. }
  76. if (tst->isSendData) {
  77. while (!fs.eof()) {
  78. vector<char> data(FRAME_SIZE, 0);
  79. fs.read(&data[0], sizeof(char) * FRAME_SIZE);
  80. int nlen = fs.gcount();
  81. nlen = request->SendAudio((char*)&data[0], nlen);
  82. if (nlen <= 0) {
  83. std::cout << "send data fail" << endl;
  84. break;
  85. }
  86. /*
  87. *语音数据发送控制:
  88. *- 语音数据是实时的, 不用sleep控制速率, 直接发送即可.
  89. *- 语音数据来自文件, 发送时需要控制速率, 使单位时间内发送的数据大小接近单位时间原始语音数据存储的大小.
  90. *对于8k pcm 编码数据, 建议每发送3200字节 sleep 200 ms.
  91. *对于16k pcm 编码数据, 建议每发送6400字节 sleep 200 ms.
  92. *对于其它编码格式的数据, 用户根据压缩比, 自行估算, 比如压缩比为10:1的 16k opus,
  93. *需要每发送6400/10=640 sleep 200ms.
  94. */
  95. #ifdef _WINDOWS_COMPILE_
  96. Sleep(200);
  97. #else
  98. usleep(200 * 1000);
  99. #endif
  100. }
  101. }
  102. fs.close();
  103. /*
  104. *音频文件数据发送结束(一个会话周期结束), 此时调用stop().
  105. *stop()非异步,在接受到服务端响应,或者超时之后,才会返回.
  106. *返回之后,可以调用delete request
  107. */
  108. request->Stop();
  109. delete request;
  110. request = NULL;
  111. } catch (const char* e) {
  112. std::cout << e << endl;
  113. }
  114. }
  115. return 0;
  116. }
  117. void OnResultDataRecved(NlsEvent* str,void* para=NULL) {
  118. std::cout << "Id:" << (*(int*)para) << " " << str->getResponse() << endl;
  119. }
  120. void OnOperationFailed(NlsEvent* str, void* para=NULL) {
  121. std::cout << "Id:" << (*(int*)para) << " " << str->getErrorMessage() << endl;
  122. }
  123. void OnChannelCloseed(NlsEvent* str, void* para=NULL) {
  124. std::cout << "Id:" << (*(int*)para) << " " << str->getResponse() << endl;
  125. }
  126. int main(int arc, char* argv[]) {
  127. try {
  128. if (arc <= 7) {
  129. cout << "param is not valid. Usage: demo test.wav config.txt 1 1 [your-id] [your-scret] 1" << endl;
  130. return -1;
  131. }
  132. int id = 123434;
  133. gCallback = new NlsSpeechCallback();
  134. gCallback->setOnMessageReceiced(OnResultDataRecved,&id);
  135. gCallback->setOnOperationFailed(OnOperationFailed,&id);
  136. gCallback->setOnChannelClosed(OnChannelCloseed,&id);
  137. gNlc = NlsClient::getInstance();
  138. int ret = gNlc->setLogConfig("log-asr.txt",3);
  139. ParamStruct pa;
  140. pa.filename = argv[1];
  141. pa.config = argv[2];
  142. pa.threadcount = atoi(argv[3]);
  143. pa.count = atoi(argv[4]);
  144. pa.id = argv[5];
  145. pa.key = argv[6];
  146. pa.isSendData = strcmp(argv[7], "0") == 0 ? false : true;
  147. const int ThreadCount = pa.threadcount;
  148. vector<pthread_t> tarr(ThreadCount);
  149. for (int i = 0; i < pa.count; i++) {
  150. for (int j = 0; j < ThreadCount; j++)
  151. pthread_create(&tarr[j], NULL, &func, (void*)&pa);
  152. for (int j = 0; j < ThreadCount; j++)
  153. pthread_join(tarr[j], NULL);
  154. }
  155. if(gNlc != NULL) {
  156. delete gNlc;
  157. gNlc = NULL;
  158. }
  159. delete gCallback;
  160. gCallback = NULL;
  161. } catch (exception& e) {
  162. cout << e.what() << endl;
  163. }
  164. return 0;
  165. }

常见问题

1. 回调函数的参数的作用是什么?

回调函数为void (*NlsCallbackMethod)(NlsEvent*, void*)

  • NlsEvent 指针所指向的对象包含了由服务器返回的识别信息。
  • void* 参数是由用户在设置回调函数时传入的参数,SDK不做处理。

2. 每次sendAudio()发送字节数是否有限制?

通常可以随意设置,实时数据建议每次发送6400字节。压缩数据可以根据压缩比换算。

3. 如何处理 onOperationFailed 回调函数的返回结果?

接收到onOperationFailed回调函数的返回结果,说明在请求过程中出现了异常,此时需要停止发送,关闭连接。如还需发送数据,可以重新建立连接。 onChannelClosed 回调函数在onOperationFailed异常时,停止工作线程,重新启动新的请求线程,但可能不会上报。

4. 如何处理 onChannelClosed 回调函数的返回结果?

onChannelClosed,说明连接通道已经关闭。此时需要停止发送,调用request关闭,销毁流程。如还需发送数据,可以重新建立连接。 调用stop方法,会触发此回调。服务端检测到语音识别结束,也会主动关闭连接,触发此回调。

5. 音频数据在发送过程中断网后SDK会如何处理?

SDK会调用onOperationFailed回调函数,返回错误码是-1。

6. demo中的多线程是什么?

同时读多个文件,分别识别。

7. windows平台下编译c++ sdk出错,如何处理?

C++ SDK提供的windows平台的lib支持vs2013和vs2015,请选用与您编译器相同的版本来编译您的工程。此外C++ SDK依赖于libpthread、libopus、openssl,请确保已正确链接相关依赖库。

8. MT和MD运行时库的区别是什么?

  • MD: 表示运行时库由操作系统提供一个DLL,程序里不集成。
  • MT:表示运行时库由程序集成。
  • MT需要注意跨模块内存释放的问题。
本文导读目录