现在国内语音就讯飞和百度,百度免费的,果断采用。
一、首先去官网注册,申请KEY(http://ai.baidu.com/tech/speech/asr)。
二、下载SDK(DEMO里有SDK和jniLibs),开始集成
库文件路径:
jar :core/libs 目录下
so:core/src/main/jniLibs 目录
以下代码可以在demo中查找
/**
* android 6.0 以上需要动态申请权限
*/
private void initPermission() {
String permissions[] = {Manifest.permission.RECORD_AUDIO,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.INTERNET,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
ArrayList toApplyList = new ArrayList();
for (String perm :permissions){
if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, perm)) {
toApplyList.add(perm);
//进入到这里代表没有权限.
}
}
String tmpList[] = new String[toApplyList.size()];
if (!toApplyList.isEmpty()){
ActivityCompat.requestPermissions(this, toApplyList.toArray(tmpList), 123);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
// 此处为android 6.0以上动态授权的回调,用户自行实现。
将app/libs/bdasr_V3_xxxxx_xxxxx.jar 复制到您的项目的同名目录中。
-keep class com.baidu.speech.**{*;}
http://ai.baidu.com/docs#/ASR-Android-SDK/3844a54f
DEMO
package com.baidu.speech.recognizerdemo;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import org.json.JSONObject;
import android.Manifest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.speech.RecognitionListener;
import android.speech.SpeechRecognizer;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.baidu.speech.EventListener;
import com.baidu.speech.EventManager;
import com.baidu.speech.EventManagerFactory;
import com.baidu.speech.VoiceRecognitionService;
import com.baidu.speech.asr.SpeechConstant;
public class MainActivity extends Activity implements EventListener {
/*private SpeechRecognizer speechRecognizer;
private Button btn;
private TextView iat_text;
public static final int STATUS_None = 0;
public static final int STATUS_WaitingReady = 2;
public static final int STATUS_Ready = 3;
public static final int STATUS_Speaking = 4;
public static final int STATUS_Recognition = 5;
private static final int EVENT_ERROR = 11;
private int status = STATUS_None;
*/
protected TextView txtLog;
protected TextView txtResult;
protected Button btn;
protected Button stopBtn;
private EventManager asr;
private boolean logTime = true;
private boolean enableOffline = true; // 测试离线命令词,需要改成true
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
// initPermission();
asr = EventManagerFactory.create(this, "asr");
asr.registerListener(this); // EventListener 中 onEvent方法
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
start();
}
});
stopBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stop();
}
});
if (enableOffline) {
loadOfflineEngine(); //测试离线命令词请开启, 测试 ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH 参数时开启
}
}
@Override
protected void onDestroy() {
super.onDestroy();
asr.send(SpeechConstant.ASR_CANCEL, "{}", null, 0, 0);
if (enableOffline) {
unloadOfflineEngine(); //测试离线命令词请开启, 测试 ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH 参数时开启
}
}
/**
* 测试参数填在这里
*/
private void start() {
txtLog.setText("");
Map params = new LinkedHashMap();
String event = null;
event = SpeechConstant.ASR_START; // 替换成测试的event
if (enableOffline){
params.put(SpeechConstant.DECODER, 2);
}
params.put(SpeechConstant.VAD_ENDPOINT_TIMEOUT,2000);
params.put(SpeechConstant.ACCEPT_AUDIO_VOLUME, false);
params.put(SpeechConstant.OUT_FILE, "/storage/emulated/0/baiduASR/outfile.pcm");
params.put(SpeechConstant.ACCEPT_AUDIO_DATA, true);
params.put(SpeechConstant.DISABLE_PUNCTUATION,false);
// params.put(SpeechConstant.NLU, "enable");
// params.put(SpeechConstant.VAD_ENDPOINT_TIMEOUT, 800);
// params.put(SpeechConstant.VAD, SpeechConstant.VAD_DNN);
// params.put(SpeechConstant.PROP ,20000);
String json = null; //可以替换成自己的json
json = new JSONObject(params).toString(); // 这里可以替换成你需要测试的json
printLog("输入参数:" + json);
asr.send(event, json, null, 0, 0);
}
private void stop() {
asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0); //
}
private void loadOfflineEngine() {
Map params = new LinkedHashMap();
params.put(SpeechConstant.DECODER, 2);
params.put(SpeechConstant.ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH, "assets://baidu_speech_grammar.bsg");
asr.send(SpeechConstant.ASR_KWS_LOAD_ENGINE, new JSONObject(params).toString(), null, 0, 0);
}
private void unloadOfflineEngine() {
asr.send(SpeechConstant.ASR_KWS_UNLOAD_ENGINE, null, null, 0, 0); //
}
/*
* EventListener 回调方法
* name:回调事件
* params: JSON数据,其格式如下:
*
* */
@Override
public void onEvent(String name, String params, byte[] data, int offset, int length) {
String result = "name" + name;
if (length > 0 && data.length > 0) {
result += ", 语义解析结果:" + new String(data, offset, length);
}
if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_READY)) {
// 引擎准备就绪,可以开始说话
result += "引擎准备就绪,可以开始说话";
} else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_BEGIN)) {
// 检测到用户的已经开始说话
result += "检测到用户的已经开始说话";
} else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_END)) {
// 检测到用户的已经停止说话
result += "检测到用户的已经停止说话";
if (params != null && !params.isEmpty()) {
result += "params :" + params + "\n";
}
} else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {
// 临时识别结果, 长语音模式需要从此消息中取出结果
result += "识别临时识别结果";
if (params != null && !params.isEmpty()) {
result += "params :" + params + "\n";
}
Log.d(TAG, "Temp Params:"+result);
} else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_FINISH)) {
// 识别结束, 最终识别结果或可能的错误
result += "识别结束";
asr.send(SpeechConstant.ASR_STOP, null, null, 0, 0);
if (params != null && !params.isEmpty()) {
result += "params :" + params + "\n";
}
Log.d(TAG, "Result Params:"+result);
}
}
private void printLog(String text) {
if (logTime) {
text += " ;time=" + System.currentTimeMillis();
}
text += "\n";
Log.i(getClass().getName(), text);
txtLog.append(text + "\n");
}
private void initView() {
txtResult = (TextView) findViewById(R.id.txtResult);
txtLog = (TextView) findViewById(R.id.txtLog);
btn = (Button) findViewById(R.id.btn);
stopBtn = (Button) findViewById(R.id.btn_stop);
txtLog.setText(DESC_TEXT + "\n");
}
/**
* android 6.0 以上需要动态申请权限
private void initPermission() {
String permissions[] = {Manifest.permission.RECORD_AUDIO,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.INTERNET,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
ArrayList toApplyList = new ArrayList();
for (String perm :permissions){
if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, perm)) {
toApplyList.add(perm);
//进入到这里代表没有权限.
}
}
String tmpList[] = new String[toApplyList.size()];
if (!toApplyList.isEmpty()){
ActivityCompat.requestPermissions(this, toApplyList.toArray(tmpList), 123);
}
}*/
/*@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
// 此处为android 6.0以上动态授权的回调,用户自行实现。
}*/
}
附:讯飞语音识别
同百度语音一样,都是先官网申请key,然后将生成下载的Android_iat1136_*****.zip报解压,放入对应位置
在onCreate方法中初始化
//配置语音
SpeechUtility.createUtility(this, SpeechConstant.APPID + "=123456");
其中123456换成自己申请的key
封装的方法
public void startVoice(){
RecognizerDialog recognizerDialog = new RecognizerDialog(searchActivity.this, this);
recognizerDialog.setParameter(SpeechConstant.LANGUAGE, "zh_cn");//语种,这里可以有zh_cn和en_us
recognizerDialog.setParameter(SpeechConstant.ACCENT, "mandarin");//设置口音,这里设置的是汉语普通话
recognizerDialog.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8");//设置编码类型
recognizerDialog.setListener(new RecognizerDialogListener() {
@Override
public void onResult(RecognizerResult recognizerResult, boolean b) {
record = "";
if (!b) {
Log.i("test_xunfei", recognizerResult.getResultString());
Gson gson = new Gson();
speech s = gson.fromJson(recognizerResult.getResultString(),speech.class);
List ws = s.getWs();
for (int i = 0;i < ws.size();i++){
List cw = ws.get(i).getCw();
for (int j = 0;j < cw.size();j++){
record = record + cw.get(j).getW();
}
}
Log.i("xunfei",record);
Message msg = new Message();
msg.what = 1;
msg.obj = record;
mHandler.sendMessage(msg);
}
}
@Override
public void onError(SpeechError speechError) {//返回错误
Log.e("xunfei", speechError.getErrorCode() + "");
}
});
recognizerDialog.show();
}
@Override
public void onInit(int code) {
if (code != ErrorCode.SUCCESS) {
Toast.makeText(searchActivity.this,"初始化失败,错误码:" + code,Toast.LENGTH_LONG).show();
}
}
bean
package bean;
import java.util.List;
/**
* Created by Administrator on 2019/5/15
*
* desc:
*/
public class speech {
/**
* sn : 1
* ls : false
* bg : 0
* ed : 0
* ws : [{"bg":0,"cw":[{"sc":0,"w":"321"}]}]
*/
private int sn;
private boolean ls;
private int bg;
private int ed;
private List ws;
public int getSn() {
return sn;
}
public void setSn(int sn) {
this.sn = sn;
}
public boolean isLs() {
return ls;
}
public void setLs(boolean ls) {
this.ls = ls;
}
public int getBg() {
return bg;
}
public void setBg(int bg) {
this.bg = bg;
}
public int getEd() {
return ed;
}
public void setEd(int ed) {
this.ed = ed;
}
public List getWs() {
return ws;
}
public void setWs(List ws) {
this.ws = ws;
}
public static class WsBean {
/**
* bg : 0
* cw : [{"sc":0,"w":"321"}]
*/
private int bg;
private List cw;
public int getBg() {
return bg;
}
public void setBg(int bg) {
this.bg = bg;
}
public List getCw() {
return cw;
}
public void setCw(List cw) {
this.cw = cw;
}
public static class CwBean {
/**
* sc : 0.0
* w : 321
*/
private double sc;
private String w;
public double getSc() {
return sc;
}
public void setSc(double sc) {
this.sc = sc;
}
public String getW() {
return w;
}
public void setW(String w) {
this.w = w;
}
}
}
}