语音化实践
2018-06-18 本文已影响36人
默默磊OK
一、语音识别篇
1、语音识别方案选择
目前市场上提供语音识别技术公司相对较多,相关技术较为成熟,一些比较知名的语音服务提供商:
公司 | 相关产品 | 特点 |
---|---|---|
科大讯飞 | 讯飞输入法、京东、携程、新浪微博、猎豹浏览器、有道翻译官等 | 国内语音产业的先行者,中文语音识别市场占有率第一,市面上大部分应用的语音功能都是使用讯飞的接口 |
百度 | 百度输入法,魅族输入法等 | 免费! 技术实力也较为强大 |
思必驰 | 思必驰 | 更多偏向于智能硬件,智能家具、车载方面 |
方案选择时的注意点:
技术方面:
- 识别准确率 :目前市场上提供语音识别技术的主流公司的识别准确率都在95%以上,差异不大。 对于偏僻字、方言的识别讯飞更好一些
- 垂直领域的定制化:在垂直领域使用通用数据进行识别,效果肯定不太好,如果缺少支持该领域的相关功能,那么识别功能的效果就会大打折扣。比如生活服务中,“陈鱼落宴”是一家主营烤鱼的餐厅,用户语音搜索中,如果按照通用识别,将会识别为“沉鱼落雁”,那么这次搜索对于用户来说就是无效的。除此之外,如需要中英混合识别也需要注意能否支持。
服务方面:
- 文档是否全面,出现问题是否能及时找到支持人员等
实践: 我们在项目中所选用的是科大讯飞的语音识别,总体很不错,文档和技术支持(大公司)都不错,但定制化方面略有局限。
2、讯飞语音识别的使用
(1)识别的过程

当用户开启麦克风并说话后:“今天天气怎么样”,讯飞会将听到内容截断,“今天”,“天气”,然后将识别后的内容返回,依次进行,直到识别到最后一个字后,返回结束符号,完成此次识别。
举例:识别的返回内容
{
"sn": 1,
"ls": false,
"bg": 0,
"ed": 0,
"ws": [ {
"bg": 0,
"cw": [
{
"w": "今天",
"sc": 0
} ]
},
{
"bg": 0,
"cw": [
{
"w": "天气",
"sc": 0
}
]
}
]
}
(2)讯飞的SDK使用
- 使用讯飞服务前需要初始化SDK
SpeechUtility.createUtility(android.content.Context, APPID) //需要在讯飞平台上注册一个App,初始化时需要这个Appid
- 设置识别的类型参数
通过setParameter(String key, java.lang.String value) 配置的识别参数,可设置的参数有:
SpeechConstant.NET_TIMEOUT: 网络连接超时时间
SpeechConstant.KEY_SPEECH_TIMEOUT:语音输入超时时间
SpeechConstant.LANGUAGE:语言 //中文、外文等
SpeechConstant.ACCENT:语言区域 //普通话、粤语、等地方方言都支持
SpeechConstant.AUDIO_SOURCE:音频源
SpeechConstant.BLUETOOTH: 蓝牙录音
SpeechConstant.VAD_BOS:前端点超时,//开始录入音频后,音频前面部分最长静音时长
SpeechConstant.VAD_EOS:后端点超时//开始录入音频后,音频后面部分最长静音时长
SpeechConstant.ASR_PTT:设置是否有标点符号
SpeechConstant.RESULT_TYPE:识别结果类型
SpeechConstant.ASR_AUDIO_PATH:识别录音保存路径
如需对识别内容进行翻译,增加以下参数:
SpeechConstant.ASR_SCH:语义或翻译
SpeechConstant.ORI_LANG: 原始语种
SpeechConstant.TRANS_LANG: 目标语种
SpeechConstant.ADD_CAP:语义或翻译处理通道
SpeechConstant.TRS_SRC:翻译结果格式
- 内容识别后的回调方法
//音量变化 当开始识别,到停止录音(停止写入音频流)或SDK返回最后一个结果自动结束识别为止,
//SDK检测到音频数据(正在录音或写入音频流)的音量变化时,会多次通过此函数回调,告知应用层当前的音量值。
void onVolumeChanged(int var1, byte[] var2);
//开始说话。调用开始录音方法后,会自动开启系统录音机,录音机开启后会回调该函数
void onBeginOfSpeech();
//结束说话。SDK检测到音频的静音断点时,会回调此函数
void onEndOfSpeech();
//返回结果 返回的结果可能为null,请增加判断处理。
void onResult(RecognizerResult result, boolean islastWord);
///错误回调 当此函数回调时,说明当次会话出现错误,会话自动结束,录音也会停止
void onError(SpeechError var1);
//事件拓展接口,由具体业务约定
void onEvent(int var1, int var2, int var3, Bundle var4);
二、语音合成篇
1、语音合成方案选择
公司 | 相关产品 | 特点 |
---|---|---|
科大讯飞 | 滴滴出行、高德地图、携程、叮咚音响 | - |
百度 | iReader、逍遥西游 | 免费! 技术实力也较为强大 |
语音合成方面,推荐上面两家,也是市场上使用率较高的两家。我们使用的是百度的,百度的开发文档,社区内容,确实没有讯飞的全面,不过按百度当前的速度,两者的差距会很快被磨平,更重要的是百度免费!
2、百度语音合成调研
-
接口模式:
- REST API 方式。 基于HTTP方式调用接口,每次下载全部的语音合成内容。
- SDK方式。和REST API的区别在于支持边下边播。
-
SDK识别模式的选择。提供了两种模式:
- 纯在线合成。 任何网络条件下都会连接百度服务器,如果连接失败,则合成失败
- 离在线混合合成。区分用户的网络环境选择在线或离线。网络连接失败自动切换为离线。离在线模式下还按网络分为不同模式
-
SDK引入的Size大小
- 纯在线模式。jar包380K + so库1.6M
- 离在线混合模式:在纯在线模式基础上,额外增加:声音数据包260K/种 + 文本模型包4.5M
3、百度语音合成使用
我们选择的是纯在线模式。在使用前需要完成注册,设置合成参数
private void initSpeechSynthesizer(Context context) {
SpeechSynthesizer mSpeechSynthesizer = SpeechSynthesizer.getInstance();
SynthesizerListener mSynthesizerListener = new SynthesizerListener();
//完成SDK的注册
mSpeechSynthesizer.setAppId(BAIDU_APPID);
mSpeechSynthesizer.setApiKey(BAIDU_APIKEY, BAIDU_SECRETKEY);
mSpeechSynthesizer.setContext(context);
mSpeechSynthesizer.setSpeechSynthesizerListener(mSynthesizerListener);
mSpeechSynthesizer.auth(TtsMode.ONLINE); //纯在线识别
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");// 设置发声的人声音,在线生效
mSpeechSynthesizer.initTts(TtsMode.ONLINE); // 初始化在线模式
}
具体使用:
// 进行播报
mSpeechSynthesizer.speak(String content)
// 停止播报
mSpeechSynthesizer.stop()
4、其他注意
额外说下SpeechSynthesizer.auth(TtsMode.ONLINE)方法,按照文档描述,auth()接口用于测试开发者是否成功申请了在线或者离线授权。 不过在项目上线后发现该方法引发了较多ANR问题。经过分析发现,第一次打开App时auth方法耗时在1.5s左右,鉴权耗时较长,我们在开发中,要根据业务场景延后加载或进行异步处理;除此之外,和百度同学沟通后,确定对于纯在线模式,auth方法也可以不调用(好坑,demo和文档中并没有此描述)