Windows SDK
1、概述
SDK作为思必驰离线语音技术,集成了一整套成熟的单点语音技术,旨在使第三方应用可以快捷便利地集成和使用思必驰的离线语音技术。在使用单项基础技术接口之前,先授权(离线功能概述)
2、语法编译
语法编译(gram),基于ebnf的语法格式(详见附录1-1),对输入的文本内容进行解析,生成可用于语音识别的语法网络资源。
2.1 duilite_gram_new
struct duilite_gram *duilite_gram_new(char *cfg);
接口能力
初始化gram引擎。
输入参数
{ } |
返回值
失败 – NULL;
2.2 duilite_gram_start
int duilite_gram_start(struct duilite_gram *gram, char *param);
接口能力
启动gram引擎,开始语法编译。
输入参数
param – 启动参数,JSON字符串,格式如下:
{ "outputPath": "res_file_path", "ebnf": "ebnf_content" } 或 { "outputPath": "res_file_path", "ebnfFile": "ebnf_content.xbnf" } |
其中outputPath为生成的语法网络资源文件存放路径,必选;ebnf为基于ebnf的语法格式的文本内容;ebnfFile为基于ebnf的语法格式的文件。ebnf与ebnfFile二选一即可。
返回值
失败 – 非0;
2.3 duilite_gram_delete
int duilite_gram_delete(struct duilite_gram *gram);
接口能力
销毁gram引擎。
输入参数
gram – 引擎指针;
返回值
成功 – 0;
失败 – 非0;
3、离线语音识别
语音识别(asr),利用声学模型,语言模型和其他相关的资源,将输入的语音转为文字。
3.1 duilite_asr_new
struct duilite_asr *duilite_asr_new(char *cfg, duilite_callback callback, void *userdata);
接口能力
输入参数
{ "resBinPath": "res_file_path", } |
其中,resBinPath为识别资源文件,包括grammar和ngram两种,区别见附录1-2,必选;netBinPath为语法网络资源文件,即gram引擎生成的资源文件,当resBinPath使用ngram资源时,可选;当resBinPath使用grammar增量网络资源时,请勿配置。
callback – 通用回调函数,内部串行调用,与外部调用线程属于同一线程。识别结果通过该函数返回,识别结果示例见附录1-2;
userdata – 用户指针,透传,不需要可设为NULL;
返回值
成功 – 引擎指针;
失败 – NULL;
3.2 duilite_asr_start
int duilite_asr_start(struct duilite_asr *asr, char *param);
接口能力
启动asr引擎。
输入参数
asr – 引擎指针;
param – 启动参数,JSON字符串,格式如下:
{ "env": "...;...;" } |
其中env可选,具体配置示例见附录1-2。
返回值
成功 – 0;
失败 – 非0;
3.3 duilite_asr_feed
int duilite_asr_feed(struct duilite_asr *asr, char *data, int len);
接口能力
输入音频数据,每次识别操作(每启动引擎视为一次)输入音频数据时长最长为60s,超过限制的数据不会处理,并返回错误。
输入参数
asr – 引擎指针;
data – 音频数据,格式为单通道,16k采样率,有符号16bit编码;
len – 音频数据长度;
返回值
成功 – 0;
失败 – 非0;
3.4 duilite_asr_stop
int duilite_asr_stop(struct duilite_asr *asr);
接口能力
停止asr引擎,并通过串行调用通用回调函数输出识别结果,一般在语音结束时调用。
输入参数
asr – 引擎指针;
返回值
成功 – 0;
失败 – 非0;
3.5 duilite_asr_cancel
int duilite_asr_cancel(struct duilite_asr *asr);
接口能力
取消当前识别操作,并重置asr引擎,不会有识别结果输出。
输入参数
asr – 引擎指针;
返回值
成功 – 0;
失败 – 非0;
3.6 duilite_asr_delete
int duilite_asr_delete(struct duilite_asr *asr);
接口能力
销毁asr引擎。
输入参数
asr – 引擎指针;
返回值
成功 – 0;
4、语音端点检测
语音端点检测(Voice Activity Detection,VAD),检测语音的开始和结束的时间点,过滤静音,提取有效人声,配合语音识别使用。
4.1 duilite_vad_new
struct duilite_vad *duilite_vad_new(char *cfg, duilite_callback callback, void *userdata);
接口能力
初始化vad引擎。
输入参数
cfg – 初始化配置,JSON字符串,格式如下:
{ "resBinPath": "res_file_path", "pauseTime": 300, "fullMode": 0 } |
其中,resBinPath为资源文件,必选;pauseTime为语音结束延长时间,单位为毫秒(ms),可选,默认为0;fullMode为全双工模式开关,1为开,0为关,可选,默认为关,当开启时可以连续输出语音状态检测跳变状态。
callback – 通用回调函数,内部串行调用,与外部调用线程属于同一线程;
DUILITE_MSG_TYPE_BINARY返回切割后音频;DUILITE_MSG_TYPE_JSON返回检测结果,格式如下:
{"status":1} {"status":2} |
其中1表示音频开始,2表示音频结束。
userdata – 用户指针,透传,不需要可设为NULL;
返回值
成功 – 引擎指针;
失败 – NULL;
4.2 duilite_vad_start
int duilite_vad_start(struct duilite_vad *vad, char *param);
接口能力
启动vad引擎。
输入参数
vad – 引擎指针;
param – 启动参数,JSON字符串,可选,不需要可设为NULL,格式如下:
{ "pauseTime": 300 } |
通过pauseTime更新语音结束延长时间。
返回值
成功 – 0;
失败 – 非0;
4.3 duilite_vad_feed
int duilite_vad_feed(struct duilite_vad *vad, char *data, int len);
接口能力
输入音频数据,同时串行调用通用回调函数返回音频数据与检测状态变化。
输入参数
vad – 引擎指针;
data – 音频数据,格式为16k采样率,有符号16bit编码;
len – 音频数据长度;
返回值
成功 – 0;
失败 – 非0;
4.4 duilite_vad_stop
int duilite_vad_stop(struct duilite_vad *vad);
接口能力
停止vad引擎,并将缓冲区的音频数据处理完毕;一般在收到语音结束状态时调用;注意,不能在通用回调函数中调用该接口。
输入参数
vad – 引擎指针;
返回值
成功 – 0;
失败 – 非0;
4.5 duilite_vad_cancel
int duilite_vad_cancel(struct duilite_vad *vad);
接口能力
取消vad检测。
输入参数
vad – 引擎指针;
返回值
成功 – 0;
失败 – 非0;
4.6 duilite_vad_delete
int duilite_vad_delete(struct duilite_vad *vad);
接口能力
销毁vad引擎。
输入参数
vad – 引擎指针;
返回值
成功 – 0;
失败 – 非0;
附录
1. 动态语法编译 XBNF
- 语法规则
XBNF文件采用ebnf语法作为基础语法,EBNF (extended Backus-Naur Form,扩展巴科斯-瑙尔范式)是表达作为描述计算机编程语言和形式语言的正规方式的上下文无关文法的元语法 (metalanguage)符号表示法。
- 常用符号说明
用途 |
符号表示 |
描述 |
注释 |
# |
该符号之后的文本为注释文本 |
定义 |
= |
为变量定义内容 |
终止 |
; |
表达式的结束 |
分割 |
| |
列举,从中选择一个 |
可选 |
[....] |
用户描述当前语句重复0或1次 |
分组 |
(....) |
描述当前内容在一个组合内,多与”|”搭配使用 |
0 到多的重复 |
{....} |
被包含语句重复 0 到多次 |
1 到多的重复 |
<....> |
被包含语句重复 1 到多次 |
指定范围的重复 |
/min=a,max=b / |
描述钱一个语句重复[a,b]次 |
- 基本语法说明
ebnf语法有两部分组成:定义变量及主执行语句,例如:
$hello=你好;# 定义变量 变量名由字母或者中文组成 (\<s\> $hello \<\s\>) # 主执行语句 |
一般在前后加上“<s>”、“</s>”,用于表明句子的开始及结束。变量在使用的时候,使用“$变量名“引用,以空格结束。
- 语义设定
a) K,V项的设置
在扩展属性语法“/.../”中设置“K”、“V”,用于识别反馈语义,如:
$digit=(1|2|3|4|5|6|7|8|9|0); $phone_num=($digit/min=1,max=11,k=”number”/); $expr1=(打电话)/k=”action” , v=”call”/ $phone_num; (\<s\> ($expr1) \<\/s\> ) |
如果扩展属性语法“/.../”中存在“K”值,即当前结果是要做语义输出的,如果没有指定V”,则采用对应的识别结果作为对应的键值;如果指定V”,则使用V”做为输出。
b) 层级嵌套的设定
语法属性支持层级的设计,输出结果为JSON,如:
$digit=(1|2|3|4|5|6|7|8|9|0); $phone_num=($digit/min=1,max=11,k=”number”/); $expr1=((打电话)/k=”action” , v=”call”/ $phone_num) /k=”test”/; (\<s\> ($expr1) \<\/s\> ) |
如果识别结果为“打电话给123456”,对应的语义输出为: {“test”:{“action”:”call”,”number”:”123456”}}。
c) 扩展的属性
同时支持自定义扩展属性,用于JSON输出,如:
$NUM=( $DIGIT /min=1,max=11,k=”number”,check=”hook” /) |
其对应的输出为{”number”:”123456”,”check ”:”hook”},check=“hook”即为自定义属性。
- 语法文件样例
$phone_num=(1386000000|15152439000|119|110); $person=(小明|金钟|刘德华|张学友)/k="person"/; $phone_action=(打[电话]给 | 电话给 | 呼叫 | 联系 | 致电 | 拨通 | 拨打 )/action="call"/; $cmd=($phone_action ($person | $phone_num)) /domain="phone"/; $appF=(QQ|微信|相机|手电筒|图库|地图)/k="Fun"/; $app_action=(打开| 开启| 启动)/action="OPEN"/; $OPEN=($app_action $appF) /domain="open"/; (\<s\> (( $cmd ) | ( $OPEN ) ) \<\/s\> ) |
2. 语音识别引擎启动参数及结果示例
识别资源分为两种,grammar与ngram,区别如下:
l grammar就是基于EBNF (extended Backus-Naur Form)的语法格式生成的语言模型,限定了说法的内容;
l ngram是基于这样一种假设,第n个词的出现只与前面n-1个词相关,而与其它任何词都不相关,是用语料训练出来的,支持的说法不固定。
grammar识别默认结果示例如下:
ngram识别默认结果如下:
{ "version": "1.9.20.2018.12.21.11:12:39", "res": "res_file_path", "eof": 1, "rec": "你好 小 乐 打开 空调", "conf": 0.674354, "wavetime": 4823, "vadtime": 4823, "prutime": 0, "systime": 147, "rectime": 0, "sestime": 148, "posttime": 2, "delaytime": 2, "delayframe": 0, "net_type": 1, "post": {} } |
融合(grammar+ngram)识别默认结果如下:
{ "grammar": { "version": "1.9.20.2018.12.21.11:12:39", "res": "res_file_path", "eof": 1, "rec": "你 好 小 乐 打 开 空 调", "conf": 0.674354, "wavetime": 4823, "vadtime": 4823, "prutime": 0, "systime": 152, "rectime": 0, "sestime": 156, "posttime": 3, "delaytime": 3, "delayframe": 0, "net_type": 0, "post": { "sem": { "operation": "open", "object": "空调", "domain": "device_control" } } }, "ngram": { "version": "1.9.20.2018.12.21.11:12:39", "res": "res_file_path", "eof": 1, "rec": "你好 小 乐 打开 空调", "conf": 0, "wavetime": 4823, "vadtime": 4823, "prutime": 0, "systime": 152, "rectime": 0, "sestime": 156, "posttime": 3, "delaytime": 3, "delayframe": 0, "net_type": 1, "post": { "sem": { "operation": "open", "object": "空调", "domain": "device_control" } } } } |
各字段释义如下表:
字段 |
释义 |
|
version |
解码器版本 |
|
res |
解码资源版本 |
|
eof |
识别状态标志:音频结束为1,未结束为0 |
|
rec |
识别结果 |
|
conf |
置信度 |
|
wavetime |
实际处理的音频时间(vad切出的音频时间) |
|
vadtime |
同wavetime |
|
prutime |
解码过程中的剪枝耗时 |
|
systime |
实际解码时间(CPU时间) |
|
rectime |
多线程下的解码时间,当前为0 |
|
sestime |
实际解码时间 |
|
delaytime |
音频送完到输出结果的延时 |
|
delayframe |
音频送完到输出结果这段时间里处理的音频帧数 |
|
net_type |
net类型,0为grammar,1为ngram |
|
post |
|
后处理输出 |
|
sem |
语义信息 |
- 实时反馈
使用实时反馈功能,增加 env配置如下:
"use_frame_split=1;" |
其中,1表示打开实时反馈;0或者未设置该参数,表示关闭实时反馈。
实时反馈结果示例如下:
{"grammar":{"rec":"切 歌","var":0},"ngram":{"rec":"你","var":0}} {"grammar":{"rec":"你 好 小 乐 切 歌","var":0},"ngram":{"rec":"你好 小 乐","var":0}} {"grammar":{"rec":"你 好 小 乐 打 开 空 调","var":0},"ngram":{"rec":"你好 小 乐 打开 空调","var":0}} |
其中"var":0表示实时反馈结果,根据所使用的资源,输出grammar,ngram结果。
- 语义信息
输出语义信息,增加env配置如下:
"use_xbnf_rec=1;" |
其中1表示输出语义信息,未设置该参数时默认输出语义信息;0表示不输出语义信息。
语义信息只在识别最终结果中,示例如下:
{ ...... "eof": 1, ...... "post": { "sem": { "operation": "open", "object": "空调", "domain": "device_control" } } } |
其中sem表示语义信息,其内容由根据xbnf文件生成的语法网络资源文件或ngram资源文件所决定。
- 结果拼音输出
输出拼音结果,增加env配置如下:
"use_pinyin=1;" |
其中,1表示打开拼音输出;0或者未设置该参数,表示关闭拼音输出。
{ ...... "pinyin": "ni hao xiao le da kai kong diao", ...... } |
- 结果分割符
识别结果分割符,默认为空格,若需要修改,增加env配置如下,以","为示例:
"rec_wrd_sep=\",\";" |
识别结果如下:
{ ...... "rec": "你,好,小,乐,打,开,空,调", ...... } |
- 多候选结果
多候选结果仅在单独ngram识别时可用,增加env配置如下:
"nbest=n;" |
其中n表示候选结果数量。n为3时,识别结果示例如下:
{ ...... "nbest": ["你好 小 乐 打开 空调", "你好 小 勒 打开 空调", "你好 晓 乐 打开 空调"], ...... } |
- 融合识别ngram置信度
融合识别时,若需要输出ngram识别结果的置信度,增加env配置如下:
"hold_conf=1;" |
其中1表示输出ngram识别结果的confidence;0或未设置该选项表示不输出ngram识别结果的confidence。
识别结果示例如下:
{ "grammar": { ...... }, "ngram": { ...... "conf": 0.674354, ...... } } |
- oneshot
用于提高ngram的oneshot识别准确率,增加env配置如下:
"one_shot_json=\"wakeup_word.json\";" |
其中wakeup_word.json文件格式及示例如下:
{ "one_shot_words": [ "你好小勒", "你好小德" ] } |
识别结果示例如下:
{ ...... "rec": "你好小勒 打开 空调", ...... } |
- 动态加载
在某些场景下,存在语法网络资源占用内存较大的情况,比如电话黄页等。可以通过将语法网络资源分开编译,动态加载的方法优化内存占用,下面举例说明:
duilite_asr_new传入的netBinPath语法网络资源所对应的xbnf文件将复杂说法内容抽离,使用@符号引用在外部定义的复杂说法,格式及示例如下:
$DEVICE_CMD_OPEN = ((打开)/operation="open"/@DEVICE); $DEVICE_CMD_CLOSE = ((关闭)/operation="close"/@DEVICE); $DEVICE_CMD_ALL = ($DEVICE_CMD_OPEN|$DEVICE_CMD_CLOSE) /domain= "device_control"/; $SEMANTIC_OUTPUT = @WAKEUP_WORD ($DEVICE_CMD_ALL); ( \<s\> ($SEMANTIC_OUTPUT) \<\/s\> ) |
增加env配置如下:
"expand_fn=\"slot.json\";" |
其中slot.json文件格式及示例如下:
{ "slot": [{ "name": "DEVICE", "path": "device.slot.bin" }, { "name": "WAKEUP_WORD", "path": "wakeup_word.slot.bin" }] } |
需要注意的是,slot.json中的name字段的值需要和xbnf文件中定义与引用的变量名保持一致。
device.slot.bin所对应的xbnf文件中对DEVICE中定义:
$DEVICE = (电视|空调|电灯|净化器)/k="object"/; ( \<s\> ($DEVICE) \<\/s\> ) |
wakeup_word.slot.bin所对应的xbnf文件中对WAKEUP_WORD中定义:
$WAKEUP_WORD = [你好小乐]; ( \<s\> ($WAKEUP_WORD) \<\/s\> ) |
- 热词更新
单独使用grammar的增量网络资源,可实现热词更新,增加env配置如下:
"dynamic_list=\"word1,word2,word3\";blacklist=\"word1,word2,word3\";" |
dynamic_list为热词白名单;blacklist为热词黑名单;若命中黑名单,则识别结果为空。
- filler
filler用于减少误识别,增加env配置如下:
"use_filler=1;filler_penalty_score=2.0;" |
use_filler为该功能开关,1为开,0为关,默认关闭;filler_penalty_score为惩罚分数,可选,默认为2.0。
3. 常见错误码
错误码 |
数值 |
释义 |
SpeechNoError |
0 |
成功,无错误 |
SpeechAuthError |
-9999 |
授权错误 |
SpeechReadFileError |
-9998 |
读文件失败 |
SpeechWriteFileError |
-9997 |
写文件失败 |
SpeechRemoveFileError |
-9996 |
删除文件失败 |
SpeechStatFileError |
-9995 |
获取文件信息失败 |
SpeechNotDir |
-9994 |
目录不存在 |
SpeechOpenDirError |
-9993 |
打开目录失败 |
SpeechMakeDirError |
-9992 |
创建目录失败 |
SpeechDirPathInvaild |
-9991 |
目录路径非法 |
SpeechWsaInitError |
-9990 |
Wsa初始化失败 |
SpeechInputNull |
-9899 |
输入为空 |
SpeechNotJson |
-9898 |
非Json格式 |
SpeechNoField |
-9897 |
配置字段缺失 |
SpeechNoFile |
-9896 |
文件缺失 |
SpeechNoMem |
-9895 |
内存申请失败 |
SpeechNoInstance |
-9894 |
引擎指针为空 |
SpeechCoreError |
-9893 |
内核错误 |
SpeechCoreNotSupport |
-9892 |
内核不支持该功能 |
SpeechExceedLimit |
-9891 |
超过相应限制 |
SpeechSpeexChannelError |
-9799 |
Speex通道错误 |
SpeechSpeexRateError |
-9798 |
Speex比特率错误 |
SpeechSpeexOggInitError |
-9797 |
Ogg初始化错误 |
SpeechSpeexStateError |
-9796 |
Speex引擎错误 |
SpeechNWakeupIndexError |
-9699 |
多路唤醒通道索引错误 |
SpeechUploadInitError |
-9599 |
数据上传模块初始化失败 |