全部产品
阿里云办公

C++ SDK 1.0

更新时间:2018-12-10 10:59:12

本文档为智能语音交互1.0,新用户请使用智能语音交互2.0

一、SDK 使用说明

功能介绍

语音C++ SDK提供实时长语音识别服务,提供将实时长语音转成文字的功能。

SDK下载地址

实时语音识别C++ SDK


demo 编译,运行步骤

  1. Linuxdemo编译过程:
  2. 准备工作:
  3. 1: cd path/to/sdk/lib
  4. 2: tar -zxvpf linux.tar.gz
  5. cmake编译:
  6. 1: 请确认本地系统以安装Cmake,最低版本2.6
  7. 2: 执行[cd path/to/sdk/ && ./build.sh]编译demo
  8. 3: 编译完毕,进入path/to/sdk/demo目录,执行[./realtimeDemo config-realtime.txt your-id your-scret]
  9. 如果不支持cmake,可尝试手动编译:
  10. 1: g++ -o demo/realtimeDemo demo/realtime-demo.cpp -I./include -L./lib/linux -lrealTimeUnity -lssl -lcrypto -lopus -lpthread -D_GLIBCXX_USE_CXX11_ABI=0
  11. 2: export LD_LIBRARY_PATH=./lib/linux/
  12. 3: ./demo/realtimeDemo config-realtime.txt your-id your-scret
  13. Windowsdemo编译工程:
  14. Windows下需要用户自己搭建VS工程。
  15. 准备工作:
  16. 1: 进入 path/to/sdk/lib
  17. 2: 解压windows.zip

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. 针对Linux环境,SDK提供的库文件为librealTimeUnity.so 和librealTimeUnity-32.so,分别对应64位运行环境和32位运行环境。

  3. 针对Windows环境,SDK提供的库文件为Windows版本x86/64位realTimeSdk.dll(VS2013、VS2015)。

  4. SDK依赖openssl(l-1.0.2j),opus(1.2.1),pthread(2.9.1, Windows下使用;Linux下系统自带pthread)。依赖库放置在path/to/sdk/lib下。

    注意:path/to/sdk/lib/windwos/1x.0/pthread仅在Windows下使用。

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

  6. SDK自带对pcm格式语音进行opu压缩发送,只需将config文件中的Format改为opu即可,输入流仍然为pcm格式。(Format为opu时,sendAudio发送字节长度必须为640。)

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

  8. 语音数据发送控制:

    • 语音数据是实时的,不用sleep控制速率,直接发送即可。
    • 语音数据来自文件,发送时需要控制速率,使单位时间内发送的数据大小接近单位时间原始语音数据存储的大小。
    • 对于8k pcm 编码数据,建议每发送3200字节sleep 200ms。
    • 对于16k pcm 编码数据,建议每发送6400字节sleep 200ms。
    • 对于其它编码格式的数据,用户根据压缩比,自行估算,比如压缩比为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(LogError : 1, LogWarning : 2, LogInfo : 3, LogDebug : 4)
  5. * @param logFileSize 日志文件的大小,以MB为单位,默认为10MB;
  6. * 如果日志文件内容的大小超过这个值,SDK会自动备份当前的日志文件,最多可备份5个文件,超过后会循环覆盖已有文件。
  7. * @return 成功则返回0,失败返回-1
  8. */
  9. int setLogConfig(const char* logOutputFile, LogLevel logLevel, unsigned int logFileSize = 10);
  10. /**
  11. * @brief 创建实时语音识别Request对象
  12. * @param onResultReceivedEvent 事件回调接口
  13. * @param config 配置文件
  14. * @return 成功返回NlsRequest对象,否则返回NULL
  15. */
  16. NlsRequest* createRealTimeRequest(NlsSpeechCallback* onResultReceivedEvent, const char* config);
  17. /**
  18. * @brief 创建一句话识别Request对象
  19. * @param onResultReceivedEvent 事件回调接口
  20. * @param config 配置文件
  21. * @return 成功返回NlsRequest对象,否则返回NULL
  22. */
  23. NlsRequest* createAsrRequest(NlsSpeechCallback* onResultReceivedEvent, const char* config);
  24. /**
  25. * @brief 创建语音合成Request对象
  26. * @param onResultReceivedEvent 事件回调接口
  27. * @param config 配置文件
  28. * @return 成功返回NlsRequest对象,否则返回NULL
  29. */
  30. NlsRequest* createTtsRequest(NlsSpeechCallback* onResultReceivedEvent, const char* config);
  31. /**
  32. * @brief 创建NLu Request对象
  33. * @param onResultReceivedEvent 事件回调接口
  34. * @param config 配置文件
  35. * @return 成功返回NlsRequest对象,否则返回NULL
  36. */
  37. NlsRequest* createNluRequest(NlsSpeechCallback* onResultReceivedEvent, const char* config);
  38. /**
  39. * @brief 销毁NlsRequest
  40. * @param request createXXXXRequest所建立的NlsRequest对象
  41. * @return
  42. */
  43. void releaseNlsRequest(NlsRequest* request);
  44. /**
  45. * @brief NlsClient对象实例
  46. * @param sslInitial 是否初始化openssl 线程安全,默认为true
  47. * @return NlsClient对象
  48. */
  49. static NlsClient* getInstance(bool sslInitial = true);
  50. /**
  51. * @brief 销毁NlsClient对象实例
  52. * @note releaseInstance()非线程安全
  53. * @return
  54. */
  55. static void releaseInstance();

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:your-appkey
  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. /*自定义线程参数*/
  2. struct ParamStruct {
  3. string fileName;
  4. string config;
  5. string id;
  6. string scret;
  7. };
  8. /*自定义事件回调参数*/
  9. struct ParamCallBack {
  10. int iExg;
  11. string sExg;
  12. };
  13. /**
  14. * @brief 获取sendAudio发送延时时间
  15. * @param dataSize 待发送数据大小
  16. * @param sampleRate 采样率 16k/8K
  17. * @param compressRate 数据压缩率,例如压缩比为10:1的16k opus编码,此时为10;非压缩数据则为1
  18. * @return 返回sendAudio之后需要sleep的时间
  19. * @note 对于8k pcm 编码数据,16位采样,建议每发送3200字节sleep 200ms。
  20. 对于16k pcm 编码数据,16位采样,建议每发送6400字节sleep 200ms。
  21. 对于其它编码格式的数据,用户根据压缩比,自行估算,比如压缩比为10:1的 16k opus,需要每发送6400/10=640 sleep 200ms。
  22. */
  23. unsigned int getSendAudioSleepTime(const int dataSize,
  24. const int sampleRate,
  25. const int compressRate) {
  26. /*仅支持16位采样*/
  27. const int sampleBytes = 16;
  28. /*仅支持单通道*/
  29. const int soundChannel = 1;
  30. /*当前采样率,采样位数下每秒采样数据的大小*/
  31. int bytes = (sampleRate * sampleBytes * soundChannel) / 8;
  32. /*当前采样率,采样位数下每毫秒采样数据的大小*/
  33. int bytesMs = bytes / 1000;
  34. /*待发送数据大小除以每毫秒采样数据大小,以获取sleep时间*/
  35. int sleepMs = (dataSize * compressRate) / bytesMs;
  36. return sleepMs;
  37. }
  38. /*
  39. * 在回调函数内部,请不要进行耗时过久的操作。
  40. * 在接收到服务端识别结果响应时,上报OnResultDataRecved回调。此时可以在回调函数内部读取识别结果。
  41. * 注意:请不要在回调函数内部调用stop, releaseRequest操作。
  42. */
  43. void OnResultDataRecved(NlsEvent* cbEvent, void* cbParam) {
  44. ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
  45. cout << "CbParam: " << tmpParam->iExg << " " << tmpParam->sExg << endl; /*仅表示自定义参数示例*/
  46. cout << "OnResultDataRecved: " << cbEvent->getResponse() << endl; /*getResponse() 可以获取云端响应信息*/
  47. }
  48. /*
  49. * 在回调函数内部,请不要进行耗时过久的操作。
  50. * request内部流程出错,上报OnOperationFailed回调,此时可以停止工作线程send操作,调用stop。
  51. * 注意:请不要在回调函数内部调用stop,releaseRequest操作。
  52. */
  53. void OnOperationFailed(NlsEvent* cbEvent, void* cbParam) {
  54. ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
  55. cout << "CbParam: " << tmpParam->iExg << " " << tmpParam->sExg << endl; /*仅表示自定义参数示例*/
  56. cout << "OnOperationFailed: " << cbEvent->getErrorMessage() << endl; /*getErrorMessage() 可以获取异常失败信息*/
  57. }
  58. /*
  59. * 在回调函数内部,请不要进行耗时过久操作。
  60. * 在调用stop(),或者服务端主动关闭连接通道时,上报OnChannelCloseed回调,通知连接通道关闭。
  61. * 注意:请不要在回调函数内部调用stop,releaseRequest操作。
  62. */
  63. void OnChannelCloseed(NlsEvent* cbEvent, void* cbParam) {
  64. ParamCallBack* tmpParam = (ParamCallBack*)cbParam;
  65. cout << "CbParam: " << tmpParam->iExg << " " << tmpParam->sExg << endl; /*仅表示自定义参数示例*/
  66. cout << "OnChannelCloseed: " << cbEvent->getResponse() << endl; /*getResponse() 可以通道关闭信息*/
  67. }
  68. void* pthreadFunc(void* arg) {
  69. int sleepMs = 0;
  70. ParamCallBack cbParam;
  71. NlsSpeechCallback* callback = NULL;
  72. /*0: 从自定义线程参数中获取id、scret等配置文件等参数*/
  73. ParamStruct* tst = (ParamStruct*)arg;
  74. if (tst == NULL) {
  75. cout << "arg is not valid." << endl;
  76. return NULL;
  77. }
  78. /* 打开音频文件, 获取数据 */
  79. ifstream fs;
  80. fs.open(tst->fileName.c_str(), ios::binary | ios::in);
  81. if (!fs) {
  82. cout << tst->fileName << " isn't exist.." << endl;
  83. return NULL;
  84. }
  85. /*初始化自定义回调参数,仅作为示例表示参数传递,在demo中不起任何作用*/
  86. cbParam.iExg = 1;
  87. cbParam.sExg = "exg.";
  88. /*
  89. * 1: 创建并设置回调函数
  90. */
  91. callback = new NlsSpeechCallback();
  92. callback->setOnMessageReceiced(OnResultDataRecved, &cbParam);
  93. callback->setOnOperationFailed(OnOperationFailed, &cbParam);
  94. callback->setOnChannelClosed(OnChannelCloseed, &cbParam);
  95. /***************以读取config.txt方式创建request****************/
  96. /*
  97. * 创建一句话识别NlsRequest,第一个参数为callback对象,第二个参数为config.txt文件。
  98. * request对象在一个会话周期内可以重复使用。
  99. * 会话周期是一个逻辑概念,比如Demo中,指读取和发送完整个音频文件数据的时间。
  100. * 音频文件数据发送结束时,可以releaseNlsRequest。
  101. * request方法调用,比如create、start、sendAudio、stop、release必须在
  102. * 同一线程内完成,跨线程使用可能会引起异常错误。
  103. */
  104. /*
  105. * 2: 创建一句话识别createRealTimeRequest对象
  106. */
  107. NlsRequest* request = NlsClient::getInstance()->createRealTimeRequest(callback, tst->config.c_str());
  108. /***********************************************************/
  109. /*****************以参数设置方式创建request******************
  110. NlsRequest* request = gNlc->createRealTimeRequest(gCallback, NULL);
  111. request->SetParam("AppKey","your-key");
  112. request->SetParam("SampleRate","8000");
  113. request->SetParam("ResponseMode","streaming");
  114. request->SetParam("Format","pcm");
  115. request->SetParam("Url","wss://nls-trans.dataapi.aliyun.com:443/realtime");
  116. ************************************************************/
  117. if (request == NULL) {
  118. cout << "createRealTimeRequest fail" << endl;
  119. delete callback;
  120. callback = NULL;
  121. return NULL;
  122. }
  123. request->Authorize(tst->id.c_str(), tst->scret.c_str());
  124. /*
  125. * 3: start()为阻塞操作,发送start指令之后,会等待服务端响应,或超时之后才返回。
  126. */
  127. if (request->Start() < 0) {
  128. cout << "start() failed." << endl;
  129. NlsClient::getInstance()->releaseNlsRequest(request); /*start()失败,释放request对象*/
  130. delete callback;
  131. callback = NULL;
  132. return NULL;
  133. }
  134. while (!fs.eof()) {
  135. char data[FRAME_SIZE] = {0};
  136. fs.read(data, sizeof(char) * FRAME_SIZE);
  137. int nlen = fs.gcount();
  138. /*
  139. * 4: 发送音频数据 sendAudio返回-1表示发送失败,需要停止发送。对于第三个参数:
  140. * format为opu,SendAudio每次发送字节必须为640。
  141. */
  142. nlen = request->SendAudio(data, nlen);
  143. if (nlen < 0) {
  144. /*发送失败, 退出循环数据发送*/
  145. cout << "send data fail." << endl;
  146. break;
  147. } else {
  148. cout << "send len:" << nlen << " ." << endl;
  149. }
  150. /*
  151. *语音数据发送控制:
  152. *语音数据是实时的,不用sleep控制速率,直接发送即可。
  153. *语音数据来自文件,发送时需要控制速率,使单位时间内发送的数据大小接近单位时间原始语音数据存储的大小。
  154. */
  155. sleepMs = getSendAudioSleepTime(6400, 16000, 1); /*根据发送数据大小、采样率、数据压缩比来获取sleep时间*/
  156. /*
  157. * 5: 语音数据发送延时控制
  158. */
  159. #if defined(_WIN32)
  160. Sleep(sleepMs);
  161. #else
  162. usleep(sleepMs * 1000);
  163. #endif
  164. }
  165. /* 关闭音频文件 */
  166. fs.close();
  167. /*
  168. * 6: 数据发送结束,关闭识别连接通道。
  169. * stop()为阻塞操作,在接受到服务端响应,或者超时之后,才会返回。
  170. */
  171. request->Stop();
  172. /*7: 识别结束, 释放request对象*/
  173. NlsClient::getInstance()->releaseNlsRequest(request);
  174. return NULL;
  175. }
  176. /**
  177. * 线程循环识别
  178. * 需要调整count值和每次要识别的文件,Demo中默认每次识别一个文件。
  179. */
  180. void* multiRecognize(void* arg) {
  181. int count = 2;
  182. while (count > 0) {
  183. pthreadFunc(arg);
  184. count--;
  185. }
  186. return NULL;
  187. }
  188. /**
  189. * 识别单个音频数据
  190. */
  191. int speechRealTimeFile(const char* configFile, const char* id, const char* scret) {
  192. ParamStruct pa;
  193. pa.config = configFile;
  194. pa.id = id;
  195. pa.scret = scret;
  196. pa.fileName = "test0.wav";
  197. pthread_t pthreadId;
  198. /*启动一个工作线程, 用于单次识别*/
  199. pthread_create(&pthreadId, NULL, &pthreadFunc, (void *)&pa);
  200. /*启动一个工作线程, 用于循环识别*/
  201. // pthread_create(&pthreadId, NULL, &multiRecognize, (void *)&pa);
  202. pthread_join(pthreadId, NULL);
  203. return 0;
  204. }
  205. /**
  206. * 识别多个音频数据
  207. * SDK多线程指一个音频数据源对应一个线程,非一个音频数据对应多个线程。
  208. * 示例代码为同时开启4个线程识别4个文件。
  209. * 免费用户并发连接不能超过10个。
  210. */
  211. #define AUDIO_FILE_NUMS 4
  212. #define AUDIO_FILE_NAME_LENGTH 32
  213. int speechRealTimeMultFile(const char* configFile, const char* id, const char* scret) {
  214. char audioFileNames[AUDIO_FILE_NUMS][AUDIO_FILE_NAME_LENGTH] = {"test0.wav", "test1.wav", "test2.wav", "test3.wav"};
  215. ParamStruct pa[AUDIO_FILE_NUMS];
  216. for (int i = 0; i < AUDIO_FILE_NUMS; i ++) {
  217. pa[i].config = configFile;
  218. pa[i].id = id;
  219. pa[i].scret = scret;
  220. pa[i].fileName = audioFileNames[i];
  221. }
  222. vector<pthread_t> pthreadId(AUDIO_FILE_NUMS);
  223. /*启动四个工作线程, 同时识别四个音频文件*/
  224. for (int j = 0; j < AUDIO_FILE_NUMS; j++) {
  225. pthread_create(&pthreadId[j], NULL, &pthreadFunc, (void *)&(pa[j]));
  226. }
  227. for (int j = 0; j < AUDIO_FILE_NUMS; j++) {
  228. pthread_join(pthreadId[j], NULL);
  229. }
  230. return 0;
  231. }
  232. int main(int arc, char* argv[]) {
  233. if (arc < 4) {
  234. cout << "params is not valid. Usage: ./demo config.txt your-id your-scret" << endl;
  235. return -1;
  236. }
  237. int ret = NlsClient::getInstance()->setLogConfig("log-realtime.txt", LogInfo);
  238. if (-1 == ret) {
  239. cout << "set log failed." << endl;
  240. return -1;
  241. }
  242. /*识别单个音频数据*/
  243. speechRealTimeFile(argv[1], argv[2], argv[3]);
  244. /*识别多个音频数据*/
  245. //speechRealTimeMultFile(argv[1], argv[2], argv[3]);
  246. /*所有工作完成,进程退出前,释放nlsClient。请注意,releaseInstance()非线程安全。*/
  247. NlsClient::releaseInstance();
  248. return 0;
  249. }

常见问题

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

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

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

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

发送字节数不能太小,至少为100ms时长的语音数据,实时数据建议每次发送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需要注意跨模块内存释放的问题。