smart_speech_sdk
智言语音评测Flutter sdk ,支持安卓(Android)、苹果(iOS)和鸿蒙(ohos) 三个平台。
合作联系人:18519378559
合作 邮箱: xuhaitao@samrt-speech.com
官方 网站:https://smart-speech.com/
一、集成步骤
支持平台:
- Android API Level >=19 (Android 4.4及以上)
- iOS 12 及以上版本
- Ohos 12及以上版本,flutterHarmonyOS 化是基于flutter3.7.12版本开发
授权账号:
- appId
- appSecret
1. 在项目中引入SDK
- 方式一,远程依赖集成(推荐) :
# pubspec.yaml
# 远程依赖集成
dependencies:
smart_speech_sdk: ^1.6.1
- 方式二,本地集成
# pubspec.yaml
# 本地集成
dependencies:
smart_speech_sdk:
path: *** #此处填写Flutter sdk在磁盘上的存放路径
2. 调用步骤/示例代码
graph LR
A[创建评测类对象] --> B[设置公共参数]
B --> C[初始化创建引擎create]
C --> D[设置题型相关参数]
D --> E[调用SDK录音]
D --> F[传音频文件]
E --> E1[startRecorder]
E1 --> E2[stop]
E2 --> E4[onResult获取结果]
E1 --> E3[cancel]
E3 --> G[取消评测 无结果]
F --> F1[startFile wavPath]
F1 --> E3
F1 --> F4[发送完成后自动结束]
F4 --> Z[onResult获取结果]
G --> H[destroy]
E4 --> H
Z --> H
① 获取录音权限
使用前,flutter 代码需要获取录音权限,否则录音会失败。
如果有统一获取录音权限的方式(安卓、鸿蒙、iOS),请在调用前自行获取获取。或者通过Platform根据平台来分别获取不同系统的录音权限。
② 初始化引擎实例
import 'package:smart_speech_sdk/smart_speech_sdk.dart';
import 'package:logger/logger.dart';
/// demo中写的一个全局单例,可以根据自己的业务进行处理
class GlobalEngine{
static SmartSpeechSdk? _speechEvalSdkPlugin;
static final logger = Logger();
static void loggerd(String msg){
logger.d(TAG,msg);
}
static void loggere(String msg){
logger.e(TAG,msg);
}
static void loggeri(String msg){
logger.i(TAG,msg);
}
static void loggerw(String msg){
logger.w(TAG,msg);
}
static void loggerv(String msg){
logger.v(TAG,msg);
}
}
/// 创建引擎实例,并初使化
Future<void> createEngine() async {
Map cfg = {
"appId": "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxx", // appId
"appSecret": "xxxxxxxxxxxx", //app Secret
"sampleRate":"16000", //固定值
//
// None, 不支持
// OralOnLine, 配置在线
//
"en": InitSettingOnline.OralOnLine.name, //英文语种初使化配置,如果没有可以设置为None
"zh": InitSettingOnline.OralOnLine.name, //中文语种初使化配置,如果没有可以设置为None
"ja": InitSettingOnline.OralOnLine.name, //日文语种初使化配置,如果没有可以设置为None
"userId":"111", //用户的userId, 建议设置, 以方便区分不同的用户
"serverUrl":"", //服务器域名,通常不用设置
"i18n":I18n.ZH.name, // 国际化提示,默认提示中文
};
GlobalEngine._speechEvalSdkPlugin = SmartSpeechSdk();
GlobalEngine._speechEvalSdkPlugin?.create(jsonEncode(cfg),RecordScoreCallBack(engineInitState: (String code,String msg){
if(code == "00000"){
GlobalEngine.loggere("engineInitState=========成功:::code:$code===msg:$msg");
//创建引擎成功
} else {
GlobalEngine.loggere("engineInitState======失败===:::code:$code===msg:$msg");
// 创建引擎失败
}
},onWsStart: (String taskId){
//在线评测ws建立成功时回调
GlobalEngine?.loggeri("onWsStart=====taskId:$taskId");
},onStartRecording: (){
//录音开始回调,不会等ws连接成功
GlobalEngine?.loggeri("onStartRecording=================");
},onStopSending: (){
//录音停止时回调
GlobalEngine?.loggeri("onStopSending=====");
},onGetVolume: (double volume){
//实时返回音量信息回调
GlobalEngine?.loggeri("onGetVolume=====volume:$volume");
},onSaveAudioFile: (String localPath){
// 设置 setSaveAudio(true) 时,此方法会回调
GlobalEngine?.loggeri("onSaveAudioFile=====localPath:$localPath");
},onWarning: (String taskId,String code,String msg){
//提醒、警告信息,根据自己业务端需求进行处理
GlobalEngine?.loggerw("onWarning=====taskId:$taskId==code:$code==msg:$msg");
},onError: (String taskId,String code,String msg){
////评测错误回调
GlobalEngine?.loggere("onError=====taskId:$taskId==code:$code==msg:$msg");
},onRealtimeResult: (String result){
//realtime设置为true时,中/英文 sentence、chapter、freedom 题型,以及中文 poem、recite 题型 ,
//会实时返回评测数据
log("onRealtimeResult=====result:$result");
},onResult: (String result,bool online){
//评测返回结果回调,online=true为在线返回的结果
log("onResult===result:$result");
}));
}
初始化状态回调方法 engineInitState 对应状态码:
在线
"00000","success"
"13010", "缺少网络权限"
"13011", "无网络连接"
"10002", "参数错误"
"11011", "signature错误"
"11012", "appid不可用"
"11013", "appid不存在"
"11014", "生成token错误"
"11015", "非法的当前时间"
③ 设置参数
评测参数
- 使用
eval.setKEY(VALUE);的方法设置评测参数 - 必填参数如缺失或赋值超出范围,将在
onError中返回错误码、错误信息 - 选填参数如缺失,将取默认值;如赋值超出范围,将取默认值,并在
onWarning中返回错误码、错误信息
示例代码
void engineStart(){
if(speechText.isNotEmpty){
/// 公共 必传参数
GlobalEngine._speechEvalSdkPlugin?.setLangType(LangType.enUS); // 设置评测的语种 zhHans,enUS,jaJP
GlobalEngine._speechEvalSdkPlugin?.setSampleRate(16000); //采样率,只能是16000
///公共非必传参数,可不设置(有默认值),或者根据需求进行设置
GlobalEngine._speechEvalSdkPlugin?.setAudioUrl(false); //是否返回音频文件,默认为false,即服务端不保存音频
GlobalEngine._speechEvalSdkPlugin?.setSaveAudio(true); //设置保存音频(本地磁盘)
GlobalEngine._speechEvalSdkPlugin?.setLooseness(4); //宽松度,取值范围[0,9],默认为4
GlobalEngine._speechEvalSdkPlugin?.setRatio(1.0); //拉伸系数,取值范围[0.8,1.5],默认为1
GlobalEngine._speechEvalSdkPlugin?.setScale(100); //分制,取值范围[1,100],默认为100
GlobalEngine._speechEvalSdkPlugin?.setConnectTimeout(50); //连接超时时间,单位秒,默认为15秒
GlobalEngine._speechEvalSdkPlugin?.setResponseTimeout(50); //评测超时时间,单位秒,默认为15秒
GlobalEngine._speechEvalSdkPlugin?.setRealtime(false); //是否实时返回结果,默认为false
GlobalEngine._speechEvalSdkPlugin?.setMaxPrefixSilenceMs(0); //最大前置静音时长,单位毫秒,默认0,不开启
GlobalEngine._speechEvalSdkPlugin?.setMaxSuffixSilenceMs(0); //最大后置静音时长,单位毫秒,默认0,不开启
GlobalEngine._speechEvalSdkPlugin?.setUserId(""); //用户id,默认为空,建议设置, 以方便区分不同的用户
GlobalEngine._speechEvalSdkPlugin?.setMini(0); //是否返回全量数据,默认0,0返回全量数据,1为返回精简数据
GlobalEngine._speechEvalSdkPlugin?.setPrecision("0.1"); //评测精度,取值范围{"0","0.1","0.25","0.5","1"}
GlobalEngine._speechEvalSdkPlugin?.setPauseInterval(400); //停顿间隔时间设置,单位毫秒,默认为400
GlobalEngine._speechEvalSdkPlugin?.setClientData(""); //客户端自定义参数,默认"", 建议不要传过大的数据
/// 设置题型参数,各个题型的参数设置方式请参考对应题型的接口参数文档
Map paramsJson ={
"mode": "word",
"refText":"good morning."
};
GlobalEngine.loggerd("paramsjson:$paramsJson");
GlobalEngine._speechEvalSdkPlugin?.setParamsJson(jsonEncode(paramsJson));
GlobalEngine._speechEvalSdkPlugin?.startRecorder();
}
④ 开始/停止/取消评测
- 录音方式
GlobalEngine._speechEvalSdkPlugin?.startRecorder();
//此时开始使用麦克风接收音频
// ...
//接收完成后手动停止录音完成评测,或者开启后置静音检测,检测到后置静音会自动停止,如果没有调用,超过最大录音时长时会自动停止。
GlobalEngine._speechEvalSdkPlugin?.stop();
//如果不想要此次评测的结果,可以调用cancel方法
GlobalEngine._speechEvalSdkPlugin?.cancel();
- 发送本地录音文件方式
//开始
String wavePath = "/sdcard/xxx/abc.wav"
GlobalEngine._speechEvalSdkPlugin?.startFile(wavePath);
//传入wav或pcm格式音频数据,要求为16000Hz、16Bit、单声道音频文件
GlobalEngine._speechEvalSdkPlugin?.setFileFormat("wav");
//自动读取音频文件并发送,完成后自动停止评测,不需要调整stop();
//如果不想要此次评测的结果,可以调用cancel方法取消,即不返回当前评测结果
GlobalEngine._speechEvalSdkPlugin?.cancel();
⑤ 处理评测结果
参考 ② , 在 listener 中处理评测结果
⑥ 释放评测资源
//一般可以放在Activity.onDestroy中调用
GlobalEngine._speechEvalSdkPlugin?.destroy();
3. 混淆机制
//安卓项目中,如果要做混淆,排除SDK做混淆即可
-keep class com.zhiyan.**{*;}
二、常见问题
1.Flutter SDK 支持的最小系统版本号是多少?
答:Android版本SDK目前支持4.4及以上版本(即19),iOS 支持 12及以上的版本,鸿蒙sdk支持12(5.0.0)及以上的版本
2.libc++_shared.so 冲突解决办法
在工程的build文件中加入如下代码
android {
packagingOptions {
pickFirst 'lib/*/libc++_shared.so'
}
}
3.如果使用代码混淆功能时,不能正常评测
在proguard-rules.pro文件中检查是否添加了如下规则:
-keep class com.zhiyan.**{*;}
6.语音评测支持哪些应用平台?
目前语音评测支持:Android、iOS、HarmonyOS、Web、小程序、Linux、Windows、词典笔、RTOS等应用平台
7.语音评测支持的音频格式有哪些?
音频格式介绍,请查看 支持音频格式 文档
8.错误码及相关的解决方案
错误码介绍,请查看 状态码 文档
9.语音评测支持的题型、文本、音频时长限制、结果及各字段的含义
10.为什么返回结果中没有音频 audioUrl地址,或者audioUrl地址为空?
需要在评测前传递audioUrl=true ,结果中才会返回audioUrl音频地址
11.评测音频地址存储多久?
默认保留20天,如果需要更长时间存储,建议下载至自己的服务器,保存音频 需要给评分引擎设置audioUrl=true。
12.如果某次打分有问题,需要智言协助分析,需要提供哪些信息?
提供智言返回的 audioUrl 即可,或者提供taskId
13.使用麦克风录制的音频,没有朗读任何内容,此时评测为何会有分数?
录音音频的环境中有噪声,噪声中的部分声音与评测文本中的发音相同,所以出现有分数的情况,但分数是偏低的。
14.评测参数中,设置userId的作用是什么?是否需要设置?
userId用来标识不同的用户,建议使用评测的时候,将产品中的userId设置成和产品登录账号相关联的内容。若有用户反馈评分方面的问题,智言可以快速定位到评分数据进行分析。
15.单词为什么没有流利度得分?
流利度这项维度只有句子、段落等 这种长文本的题型才有,单词发音只要朗读清晰、饱满、正确,即可正常打分。
16.语音评测Licence 是如何计数的?
请求token或者获取激活码后,即用掉一个Licence,同一个设备多次向服务器发起注册请求,只计一次。
17.语音评测并发是如何计算的?
并发就是某一时刻同时在进行录音评测的请求个数。
18.语音评测调用次数是否包含失败的情况?
语音评测调用次数,只包含服务端成功响应的次数,失败的次数不会计算在内。
19.句子评测和段落评测中,为何只读了部分内容,但流利度很很高?
流利度是对已朗读的部分进行评价,这种未朗读完的情况,完整度的得分是偏低的。所以总分在这种情况下不会出现高分。