快速开始

Release Notes

版本 日期 说明
0.1.0 2018.02.22 第一版!
0.1.2 2018.03.19 压缩性能优化
0.1.3 2018.03.29 新增切句配置,完善demo
0.1.4 2018.06.14 语音识别文本流携带毫秒级时间戳,完整句携带语速

接入准备

  • 参考“流程说明”—>“服务申请”完成权限申请;
  • 点击智能呼叫中心-智能电销C++ SDK完成C++ SDK下载;
  • 开发环境依赖:
    • Linux 64位
    • cmake :3.1,编译工具
    • gcc: 482 以上
    • curl : 7.33
    • ssl : 1.0.1i,如果开启https必须
    • jsoncpp : 可使用SDK提供的jsoncpp库
  • 开发机对SDK内config.json配置中“app.serverAddress”(服务访问)、“app.authAddress”(鉴权)地址开放公网访问权限;
  • 编译并运行SDK自带demo程序,熟悉SDK工作过程。

并发限制

受内存,核数限制,4核8G内存,并发数为20。

语音流改造

要求项 取值要求
音频格式 PCM
采样率 8KHz
采样精度 16bits
声道 单声道
实时语音流发送间隔 20ms~160ms内任意10的倍数,建议最佳发送间隔160ms
压缩选项 压缩为原始大小的1/8,节省带宽,但是音频质量会有损失
分轨 为保证识别效果,进行话者分离,拆分通话双侧音频流为两通路

输出

key 值说明
格式 EEventTypeWorkStatusResult,详见下文“识别结果”说明
语音识别 实时逐字识别文字,由静音检测识别出的完整句,文字对应开始&结束时间,完整句对应语速
语义识别 utf8编码,意图、槽位
输出方式 回调,实时返回

语速 = 完整句字数 / 秒。其中,单个单词整体算作1个字,不会按实际字母数统计。

SDK目录

${SDK_ROOT}
  |--- demo    // demo 源码和cmake文件
  |--- include // SDK 头文件
  |--- lib     // SDK 库文件
  |--- thirdparty  // 第三方库
       |--- include
       |--- lib
       |--- lib64

Demo 运行

1、请参考cmake官方文档配置gcc路径等参数。
2、修改demo/config.json文件
参考“流程说明”—>“免费账号和服务申请”流程,进入应用“概览”页面,点击左侧导航“应用列表”,查询“API Key”和“Secret Key”。

"app.appKey": "API Key",  
"app.appSecret": "Secret Key", 
"app.scope": "brain_ai_talker",

3、编译及运行

cd ${SDK_ROOT}/demo
cmake .
make
//{并发数} {循环数} {坐席语音文件} {客户语音文件}
./bd_itma_demo 1 1 salesman.wav customer.wav

4、自带音频文件
为方便开发者进行测试,自带示例音频文件。

- 坐席侧salesman.wav;
- 用户侧customer.wav。

调用接口及参数说明

全局接口

在使用SDK之前,必须进行初始化操作。

1、配置全局回调。

auto *user_callback_param = new int(12345);
// set callback before init
cntl->set_callback(itma_callback, user_callback_param);

传入typedef void (*ItmaCntlCallback)(Event& e, void* data)类型的函数指针。user_callback_param与constroller绑定(全局唯一),会回调给用户。

SDK将通过此回调通知用户SDK内部的工作状态,包括所有生成的Session的工作状态。

event_type 说明 附带参数列表
EEventTypeWorkStatusPktPosted 【DEBUG】SDK发出一个数据包的回调
EEventTypeWorkStatusSpeechStarted 服务端成功受理了用户开启session的请求 K_CALL_ID
EEventTypeWorkStatusResult 识别结果/意图结果回调 K_CALL_ID, K_EVENT_RESULT
EEventTypeError 错误回调 K_EVENT_ERR_CODE, K_EVENT_ERR_SUB_CODE. K_ERROR_MSG
EEventTypeFatal 错误回调,表明SDK无法继续运行 K_EVENT_ERR_CODE, K_EVENT_ERR_SUB_CODE. K_ERROR_MSG

2、参数设置

配置参数列表 类型 必选 说明 默认值
app.appKey string Y app key -
app.appSecret string Y app secret -
app.compress 0/1 Y 是否开启压缩。开启压缩后,网络传输字节减少至约1/7,
对识别效果几乎没有影响。但需消耗一定的CPU资源。
-
app.machineName string N 机器唯一标识。
建议填写mac地址(移除冒号,如14-10-9f-df-45-4f)或有唯一性含义的hostname
${hostname}
app.scope string Y 使用的服务。
brain_ai_talker: 智能电销。
app.serverAddress string Y 服务器地址(若使用https必须libcurl支持) -
app.authAddress string Y 验证服务地址(若使用https必须libcurl支持) -
app.upload.threads number N 上传线程数(根据并发数和实际网络状况与我们沟通后修改) 1
app.upload.duration number N 上传线程超时时间(秒,根据实际网络状况与我们沟通后修改) 900
log.toStandardOutput 0/1 Y 日志是否输出至标准输出 1
log.toFile 0/1 Y 日志是否输出至文件 0
log.filename string Y 日志文件名
log.maxLogFileSize number N 日志文件最大限制 10 1024 1024
log.enableDebug 0/1 Y 开启Debug日志 -
log.enableInfo 0/1 Y 开启Info日志(建议在生产环境中开启) -
log.enableWarning 0/1 Y 开启Warning日志 -
log.immediateFlush 0/1 Y 日志是否实时flush -

设置方法

ItmaController* cntl = global_controller();
std::string err_msg;
// 使用配置文件初始化
cntl->init("./config.json", err_msg);

// 也可以使用Json::Value类初始化
Json::Value cfg;
cfg["app.appKey"] = "app key";
cfg["app.appSecret"] = "app secret";
cntl->init(cfg, err_msg);

单通电话调用

每通电话分为三种状态:电话开始、电话过程中、电话结束。
基本流程:

session = global_controller.new_session()
session.speech_start()
while(the call is still active) {
  session.speech_doing()
}
session.speech_end()

global_control.release_session(session)

ItmaSession 类的所有方法都是线程不安全的

1、电话开始
创建新的session。
global_controller 必须已初始化。若指定call_id,请确保call_id 的全局唯一性,且满足以下正则(推荐使用UUID生成)。

^[0-9a-zA-Z_\.-]{16,128}$

若不指定,系统会随机生成一个call_id。

// 获得一个新的session

ItmaSession* session;
// 指定call_id
global_controller()->new_session("yourcallid.12345", session, err_msg);

// 指定其他参数
Json::Value param;
param[K_AGENT_DN] = 1234;
param[K_ROLEID] = 2; // 同时有坐席和用户
global_controller()->new_session(param, session, err_msg)

new_session param参数列表

KEY 说明 类型 是否必须 可选值
K_AGENT_DN 坐席号 number N
K_RATE 采样率 number N(默认8000) 目前只支持8000
K_ROLEID 语音的分轨说明 number N(默认2) 0:只有坐席
1: 只有用户
2:同时有坐席和用户
K_PARAM 其他定制化参数,请参考下文 string N

关于 K_PARAM 参数
K_PARAM参数用于传入定制化参数,KEY为K_PARAM, VALUE必须为string,string内容为可解析的json,如

param[K_PARAM] = R"({
    "sentenceHandler": {
        "client": "STANDARD_COMPLETED",
        "agent": "STANDARD_COMPLETED"
    }
})";

请务必检查设置的字符串格式是否正确。目前K_PARAM支持的参数包括

结果返回模式

"sentenceHandler": {
    "client": "STANDARD_COMPLETED",
    "agent": "STANDARD_COMPLETED"
}

client 和 agent表示对应用户与坐席的返回类型设置,支持的结果返回模式包括

含义 备注
STANDARD_COMPLETED 完整句切句 屏蔽掉所有过程句子,只下发完整句。
NONE 实时翻译结果 默认值,逐字识别结果及完整句

配置Session回调

auto *user_callback_param = new int(23456);
session->set_callback(itma_session_callback, user_callback_param);

传入typedef void (*ItmaSessionCallback)(ItmaSession* session, const Event& e, void* user_callback_param);类型的函数指针。user_callback_param与session绑定,会回调给用户。
回调的参数与内容与全局回调一致,但是只会回调与该Session相关的内容。

2、电话过程中
语音流发送,发送间隔20ms(160字节)~160ms(2560字节)内任意10的倍数。
推荐发送间隔为160ms,语音流长度2560字节。

// 开始识别
session->speech_start(...);
// 放入数据, 
while({having binary data}) {
    // not thread safe
    session->speech_doing(binary, ...);  
}

请务必检查所有的speech_doing的返回值是否为0。

若开启了压缩,SDK会在执行session->speech_doing(binary, ...)的线程中进行一定的计算操作,会有一定的CPU时间消耗。
4核机器上,若开启压缩,并发数请勿超过20

3、电话结束

// 结束识别
session->speech_end(...);

一通电话结束后,请务必调用speech_end 来结束通话。否则在超时之前,这通未结束的电话会持续占用您的并发配额。

识别结果

识别结果通过回调,以EEventTypeWorkStatusResult的类型返回,返回的字段说明如下:

key 说明 必选 内容
appId 标识所属app
callId 知识所属call
roleCategory 知识所属于角色 AGENT,座席;CLIENT,客户
category 知识类型 TXT,文本;
INTENT,意图;
KNOWLEDGE,知识;
SPEECH,合成语音(url地址);
EVENT,事件
content 知识内容 返回的知识的内容
triggerTxt 触发知识的文本 string
triggerTime 触发知识的时间 timestamp
extJson 扩展字段 扩展Json对象
logId 本次返回标识 String

extJson字段说明

key 说明 必选 内容
completed 识别文本状态 取值1和3。1,过程中逐字识别结果;3,vad切分产生的完整句
snStartTime 文本开始时间 毫秒级,样例:00:00.100
snStopTime 文本结束时间 毫秒级,样例:00:01.100
speed 完整句语速 完整句字数 / 秒。其中,单个单词整体算作1个字,不会按实际字母数统计。

示例

{
    "callId" : "xxxxx.21532-32024.1519268928131-5812",
    "category" : "TXT",
    "content" : "医学考试时间",
    "logId" : "f579116d-7741-4bf4-b94b-caf2cdd650cf_-1",
    "roleCategory" : "AGENT",
    "triggerTime" : 1519268932820,
    "extJson":{
        "snStopTime":"00:00.900",
        "speed":"1.25",
        "snStartTime":"00:00.100",
        "completed":3
    }
}

统一错误处理

SDK大部分方法遵循类C风格的统一错误处理方案:返回值非0为错误,若错误,具体的错误信息将传入参数err_msg。如:

auto cntl = global_controller();
std::string err_msg;
if (cntl->init(..., err_msg) != 0) {
    std::cout << "failed to xxxxx: " << err_msg << std::endl;
    // 错误处理
};

错误码均定义在enum ERROR_CODE中(itma_define.h). 在运行中遇到的错误请查看err_msg参数以及日志说明。

资源回收

一次识别结束后,使用

global_controller()->release_session(session)

来释放此次识别Session的资源。不调用此方法会造成内存泄漏。

当不再需要使用所有功能后,使用如下方法回收SDK的资源:

while (true) {
  if (global_controller()->try_stop(err_msg) != 0) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
  } else {
    break;
  }
}

Demo 示例

以下为Demo运行的示例日志(已关闭debug日志)

2018-03-27 21:18:15,504 INFO [ITMA] [itma_controller.cpp:59] 139640604037376 My SDKID is CPP_0.1.3-BIBIBI-30216_29255
2018-03-27 21:18:15,585 INFO [ITMA] [token_holder.cpp:61] 139640604037376 Token refreshed: 24.8dd9b6580e51dc52e9e4a693342279a2.2592000.1524748695.282335-10811527:1524748695585
2018-03-27 21:18:15,585 INFO [ITMA] [download_runner.cpp:63] 139640563357440 [Download] start nth: 0
2018-03-27 21:18:15,607 INFO [ITMA] [itma_controller.cpp:460] 139640325535488 New session created 0x7f00840094f0 BIBIBI-30216_59273.1522156695607101933-962863
[Demo] Now recognize file salesman.wav customer.wav with id: BIBIBI-30216_59273.1522156695607101933-962863
2018-03-27 21:18:16,586 INFO [ITMA] [upload_runner.cpp:44] 139640552867584 [Upload] Started, nth: 0
2018-03-27 21:18:16,645 INFO [ITMA] [itma_controller.cpp:145] 139640563357440 Speech started: "BIBIBI-30216_59273.1522156695607101933-962863"
[Demo] [Session:0x7f00840094f0] call BIBIBI-30216_59273.1522156695607101933-962863 started at server, user_param: 0
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, TXT: 您好,
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, CLIENT, TXT: 诶您好,
2018-03-27 21:18:26,611 INFO [ITMA] [upload_runner.cpp:44] 139640552867584 [Upload] Started, nth: 1
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, TXT: 哎您好先生不好意思这么晚也打扰到您了这边是信用卡中心的,今天上午有跟您来过电的您还记的吗?
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, TXT: 诶您,
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, CLIENT, TXT: 几点我知道,
2018-03-27 21:18:36,699 INFO [ITMA] [upload_runner.cpp:44] 139640552867584 [Upload] Started, nth: 2
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, TXT: 呃就是说当时您说呃不太听的见不方便是吧,
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, TXT: 哦就是说您这个呃像像您不是说您还有其他银行的信用卡对吧,
2018-03-27 21:18:46,786 INFO [ITMA] [upload_runner.cpp:44] 139640552867584 [Upload] Started, nth: 3
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, CLIENT, TXT: 银行的卡我肯定有啊,
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, TXT: 呃您其他银行的信用卡先生,
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, INTENT: 信息确认
2018-03-27 21:18:56,874 INFO [ITMA] [upload_runner.cpp:44] 139640552867584 [Upload] Started, nth: 4
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, TXT: 呃没有是吧,
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, CLIENT, TXT: 没有,
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, TXT: 那天您名下有房贷吗?
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, INTENT: 信息确认
[Demo] call BIBIBI-30216_59273.1522156695607101933-962863, AGENT, TXT: 嗯对,

分布式使用

识别服务支持分布式。
启用压缩:由于压缩算法具有一定的效果优化策略,需确保一通电话单侧(坐席|客户)语音流由同一个SDK实例上传。
非压缩:可由同一SDK实例上传,也可采用一通电话的音频数据从不同的SDK实例(不同进程、不同机器)上传。
若有疑问,可通过工单或商务合作联系我们。