自然语言处理现在是比较火的一个领域,也有了很多成熟的应用,像科大讯飞或是百度语音等等这些商业产品的一个优势之一就是比较稳定,适合用来做开发。下面就展示一个根据讯飞SDK文档做出的具有语音识别和语音合成功能的小Demo。
首先,第一步当然是去讯飞官网注册账号,创建应用并获得一个AppID,然后下载相应的SDK,我这里只下了两个,分别是语音听写和语音合成的。
然后将SDK里libs目录下的文件全部拷贝到自己项目的libs目录下,android studio还需要注意在gradle文件里android加入如下代码
否则的话按照官方文档直接编译运行,会产生对象空指针的异常(这个问题搞了我好半天)。
接下来就按照官方文档的例子,一步步编写代码了。我这个demo的实现思路就是:用户点击按钮开始录音,然后根据识别出的结果利用语音合成生成不同的句子进行反馈,这样就有一种和机器人对话的感觉了。
具体代码
package com.evoice;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.SynthesizerListener;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
// 语音识别对象
private SpeechRecognizer recognizer;
//语音合成对象
private SpeechSynthesizer speaker;
//识别出来的句子
StringBuilder sentence = null ;
//麦克风按钮
private ImageView startRecord ;
//听写监听器
private RecognizerListener recognizerListener = new RecognizerListener(){
@Override
public void onVolumeChanged(int i, byte[] bytes) {
}
/**
* 开始录音
*/
@Override
public void onBeginOfSpeech() {
Toast.makeText(MainActivity.this,"开始录音",Toast.LENGTH_SHORT).show();
}
/**
* 结束录音
*/
@Override
public void onEndOfSpeech() {
//结束录音后,根据识别出来的句子,通过语音合成进行反馈
Toast.makeText(MainActivity.this,"结束录音",Toast.LENGTH_SHORT).show();
if( sentence.indexOf("晚上好") != -1){
speaker.startSpeaking("晚上好",synthesizerListener);
}
else if( sentence.indexOf("你好") != -1 ){
speaker.startSpeaking("你好",synthesizerListener);
}
else if( sentence.indexOf("现在几点") != -1){
//获取本地时间
Date date=new Date();
DateFormat format=new SimpleDateFormat("HH:mm:ss");
String time= format.format(date);
//提取时,分,秒
String[] timeArray = time.split(":");
String hour = timeArray[0];
String minute = timeArray[1];
String seconds = timeArray[2];
speaker.startSpeaking("现在是北京时间"+hour+"时"+minute+"分"+seconds+"秒",synthesizerListener);
}else if( sentence.indexOf("你是男的还是女的") != -1 ){
speaker.startSpeaking("难道你听不出来吗",synthesizerListener);
}else {
speaker.startSpeaking("我听不懂你在说什么",synthesizerListener);
}
}
/**
* 听写结果回调接口 , 返回Json格式结果
* @param recognizerResult json结果对象
* @param b 等于true时会话结束
*/
@Override
public void onResult(RecognizerResult recognizerResult, boolean b) {
String result = recognizerResult.getResultString();
try {
//处理json结果
JSONObject jsonObject = new JSONObject(result);
JSONArray words = jsonObject.getJSONArray("ws");
//拼成句子
sentence = new StringBuilder("");
for( int i = 0 ; i < words.length() ; i ++ ){
JSONObject word = words.getJSONObject(i);
JSONArray subArray = word.getJSONArray("cw");
JSONObject subWord = subArray.getJSONObject(0);
String character = subWord.getString("w");
sentence.append(character);
}
//打印
Log.e("TAG", sentence.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 会话发生错误回调接口
* @param speechError
*/
@Override
public void onError(SpeechError speechError) {
}
/**
* 扩展用接口
*/
@Override
public void onEvent(int i, int i1, int i2, Bundle bundle) {
}
};
//语音合成监听器
private SynthesizerListener synthesizerListener = new SynthesizerListener() {
/**
* 开始播放
*/
@Override
public void onSpeakBegin() {
}
/**
* 缓冲进度回调
*/
@Override
public void onBufferProgress(int i, int i1, int i2, String s) {
}
/**
* 暂停播放
*/
@Override
public void onSpeakPaused() {
}
/**
* 恢复播放回调接口
*/
@Override
public void onSpeakResumed() {
}
/**
* 播放进度回调
*/
@Override
public void onSpeakProgress(int i, int i1, int i2) {
}
/**
* 会话结束回调接口,没有错误时,error为null
*/
@Override
public void onCompleted(SpeechError speechError) {
}
/**
* 会话事件回调接口
*/
@Override
public void onEvent(int i, int i1, int i2, Bundle bundle) {
}
};
//初始化监听器。
private InitListener mInitListener = new InitListener() {
@Override
public void onInit(int code) {
Log.d("TAG", "SpeechRecognizer init() code = " + code);
if (code != ErrorCode.SUCCESS) {
Toast.makeText(MainActivity.this,"初始化失败,错误码:" + code, Toast.LENGTH_SHORT).show();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
//根据APPID创建语音配置对象
SpeechUtility.createUtility(this, SpeechConstant.APPID +"=59b94905");
super.onCreate(savedInstanceState);
//设置主视图
setContentView(R.layout.activity_main);
//获取录音按钮视图
startRecord = (ImageView) findViewById(R.id.record);
//初始化语音对象
recognizer = SpeechRecognizer.createRecognizer(this,mInitListener);
speaker = SpeechSynthesizer.createSynthesizer(this,mInitListener);
//设置听写参数
recognizer.setParameter(SpeechConstant.DOMAIN, "iat");
//设置为中文
recognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
//设置为普通话
recognizer.setParameter(SpeechConstant.ACCENT, "mandarin ");
//设置发音人
speaker.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");
//设置语速
speaker.setParameter(SpeechConstant.SPEED, "30");
//设置音量,范围0~100
speaker.setParameter(SpeechConstant.VOLUME, "200");
//设置云端
speaker.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
//点击开始录音
startRecord.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
recognizer.startListening(recognizerListener);
startRecord.setImageResource(R.drawable.voice_full);
}
});
}
}