讯飞语音云语音听写学习

        这几天两个舍友都买了iPhone 6S,玩起了“Hey, Siri”,我依旧对我的Nexus 5喊着“OK,Google”。但种种原因,国内的“OK,Google”并不能展示出他的全部威力,于是上网搜索国内Android平台的语音助手,个人觉得评价最好的是讯飞的——灵犀语音助手。其实讯飞语音云平台早就注册过了,并下载了相应的SDK,只是没仔细研究。今天突然想好好学习一下,以方便以后集成到自己开发的APP中,也可以方便大家参考。开发工具:Android Studio。

        好了,废话就说这些。先来看效果图:

下面是具体的步骤。

1,首先在讯飞开放平台注册开发者账号,注册流程很简单,就不详细介绍。网址:http://www.xfyun.cn/。然后就是像各大平台一样的步骤:新建Android应用获取APPID—〉下载语音听写SDK。此处需要注意的是一定要新建自己的应用,别人的工程虽然能用,但不方便后续开发。

2,解压下载的SDK目录,里面有详细的教程,可自行参考。然后新建工程,将MSC.jar(放入到libs文件夹下)和libmsc.so(放入到新建的jniLibs文件夹下)导入到自己的工程中(只有在线的所有功能,没有提供离线服务。)另外,讯飞提供了两种语音识别接口,一种是后台进行语音检测,没有界面UI提示;另一种是带UI的接口,在录音、播放音频的时候,会有dialog弹出,并伴有相应的动画,相对来说用户交互体验很不错。如果使用带UI接口时,请将assets下文件拷贝到项目中。这里注意的是每个SDK下载的assets可能不一样(没有亲自测试过,因为recognize.xml打开乱码),一定要将自己下载的SDK里的assets目录拷贝到XXX/src/main文件夹下。工程目录如下:

                    

3,在AndroidManifest.xml文件中添加权限:

<!-- 在工程 AndroidManifest.xml 文件中添加如下权限 -->
<!-- 连接网络权限,用于执行云端语音能力 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- 读取网络信息状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 获取当前wifi状态 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 允许程序改变网络连接状态 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!-- 读取手机信息权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 读取联系人权限,上传联系人需要用到此权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- 外存储写入权限, 构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

4,布局文件activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" > <EditText
android:id="@+id/content_rec"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="识别内容" /> <Button
android:id="@+id/bt_start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:onClick="startRec"
android:text="开始" /> <Button
android:id="@+id/btn_read"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/bt_start"
android:layout_alignLeft="@+id/bt_start"
android:layout_alignParentRight="true"
android:onClick="read"
android:text="朗读" /> </RelativeLayout>

5,Java代码:JsonParser.java 和 MainActivity.java

        (1),JsonParser.Java

package com.xiaobailong24.xunfeiyun;

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener; /**
* Json结果解析类
*/
public class JsonParser { public static String parseIatResult(String json) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener); JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
// 转写结果词,默认使用第一个结果
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
JSONObject obj = items.getJSONObject(0);
ret.append(obj.getString("w"));
// 如果需要多候选结果,解析数组其他字段
// for(int j = 0; j < items.length(); j++)
// {
// JSONObject obj = items.getJSONObject(j);
// ret.append(obj.getString("w"));
// }
}
} catch (Exception e) {
e.printStackTrace();
}
return ret.toString();
} public static String parseGrammarResult(String json) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener); JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
for(int j = 0; j < items.length(); j++)
{
JSONObject obj = items.getJSONObject(j);
if(obj.getString("w").contains("nomatch"))
{
ret.append("没有匹配结果.");
return ret.toString();
}
ret.append("【结果】" + obj.getString("w"));
ret.append("【置信度】" + obj.getInt("sc"));
ret.append("\n");
}
}
} catch (Exception e) {
e.printStackTrace();
ret.append("没有匹配结果.");
}
return ret.toString();
} public static String parseLocalGrammarResult(String json) {
StringBuffer ret = new StringBuffer();
try {
JSONTokener tokener = new JSONTokener(json);
JSONObject joResult = new JSONObject(tokener); JSONArray words = joResult.getJSONArray("ws");
for (int i = 0; i < words.length(); i++) {
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
for(int j = 0; j < items.length(); j++)
{
JSONObject obj = items.getJSONObject(j);
if(obj.getString("w").contains("nomatch"))
{
ret.append("没有匹配结果.");
return ret.toString();
}
ret.append("【结果】" + obj.getString("w"));
ret.append("\n");
}
}
ret.append("【置信度】" + joResult.optInt("sc")); } catch (Exception e) {
e.printStackTrace();
ret.append("没有匹配结果.");
}
return ret.toString();
}
}

        (2),MainActivity.java

package com.xiaobailong24.xunfeiyun;

import android.app.Activity;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
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 com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener; public class MainActivity extends Activity { private static String TAG = "MainActivity";
// 函数调用返回值
int ret = 0;
// 语音听写对象
private SpeechRecognizer mIat;
// 语音听写UI
private RecognizerDialog iatDialog;
// 听写结果内容
private EditText mResultText;
// 语音合成对象
private SpeechSynthesizer mTts; // 默认发音人
private String voicer = "xiaoyan"; // 缓冲进度
private int mPercentForBuffering = 0;
// 播放进度
private int mPercentForPlaying = 0; private Toast mToast; @Override
public void onCreate(Bundle savedInstanceState) {
Log.e(TAG, "onCreate");
super.onCreate(savedInstanceState);
// this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
// 用于验证应用的key,将XXXXXXXX改为你申请的APPID
SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID + "=XXXXXXXX");
// 创建语音听写对象
mIat = SpeechRecognizer.createRecognizer(this, mInitListener);
// 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer
// 创建语音听写UI
iatDialog = new RecognizerDialog(MainActivity.this, mInitListener);
// 创建语音合成对象
mTts = SpeechSynthesizer.createSynthesizer(this, mInitListener);
mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
content_rec));
} public void startRec(View view) {
mResultText.setText(null);
setParam();
boolean isShowDialog = true;
if (isShowDialog) {
// 显示听写对话框
iatDialog.setListener(recognizerDialogListener);
iatDialog.show();
// showTip("begin");
} else {
// 不显示听写对话框
ret = mIat.startListening(recognizerListener);
if (ret != ErrorCode.SUCCESS) {
// showTip("听写失败,错误码:" + ret);
} else {
// showTip("begin");
}
}
} public void read(View view) {
String text = mResultText.getText().toString();
// 设置参数
setParam2();
//朗读
int code = mTts.startSpeaking(text, mTtsListener);
if (code != ErrorCode.SUCCESS) {
if (code == ErrorCode.ERROR_COMPONENT_NOT_INSTALLED) {
// 未安装则跳转到提示安装页面
} else {
showTip("语音合成失败,错误码: " + code);
}
}
} /**
* 参数设置
*
* @param
* @return
*/
private void setParam2() {
Log.e(TAG, "setParam2");
// 设置合成
mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
// 设置发音人
mTts.setParameter(SpeechConstant.VOICE_NAME, voicer); // 设置语速
mTts.setParameter(SpeechConstant.SPEED, "50"); // 设置音调
mTts.setParameter(SpeechConstant.PITCH, "50"); // 设置音量
mTts.setParameter(SpeechConstant.VOLUME, "50"); // 设置播放器音频流类型
mTts.setParameter(SpeechConstant.STREAM_TYPE, "3");
} public void setParam() {
Log.e(TAG, "setParam");
// 清空参数
mIat.setParameter(SpeechConstant.PARAMS, null);
// 设置听写引擎
mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); // 设置语言
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
// 设置语言区域
mIat.setParameter(SpeechConstant.ACCENT, "mandarin"); // 设置语音前端点
mIat.setParameter(SpeechConstant.VAD_BOS, "4000");
// 设置语音后端点
mIat.setParameter(SpeechConstant.VAD_EOS, "1000");
// 设置标点符号 1为有标点 0为没标点
mIat.setParameter(SpeechConstant.ASR_PTT, "0");
// 设置音频保存路径
mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH,
Environment.getExternalStorageDirectory()
+ "/xiaobailong24/xunfeiyun");
} /**
* 合成回调监听。
*/
private SynthesizerListener mTtsListener = new SynthesizerListener() {
@Override
public void onSpeakBegin() {
Log.e(TAG, "mTtsListener-->onSpeakBegin");
showTip("开始播放");
} @Override
public void onSpeakPaused() {
Log.e(TAG, "mTtsListener-->onSpeakPaused");
showTip("暂停播放");
} @Override
public void onSpeakResumed() {
Log.e(TAG, "mTtsListener-->onSpeakResumed");
showTip("继续播放");
} @Override
public void onBufferProgress(int percent, int beginPos, int endPos,
String info) {
Log.e(TAG, "mTtsListener-->onBufferProgress");
mPercentForBuffering = percent;
showTip(String.format(getString(R.string.tts_toast_format),
mPercentForBuffering, mPercentForPlaying));
} @Override
public void onSpeakProgress(int percent, int beginPos, int endPos) {
Log.e(TAG, "mTtsListener-->onSpeakProgress");
mPercentForPlaying = percent;
showTip(String.format(getString(R.string.tts_toast_format),
mPercentForBuffering, mPercentForPlaying));
} @Override
public void onCompleted(SpeechError error) {
Log.e(TAG, "mTtsListener-->onCompleted");
if (error == null) {
showTip("播放完成");
} else if (error != null) {
showTip(error.getPlainDescription(true));
}
} @Override
public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
Log.e(TAG, "mTtsListener-->onEvent");
}
};
/**
* 听写监听器。
*/
private RecognizerListener recognizerListener = new RecognizerListener() { @Override
public void onVolumeChanged(int i, byte[] bytes) {
Log.e(TAG, "recognizerListener-->onVolumeChanged");
showTip("当前正在说话,音量大小:" + i);
} @Override
public void onBeginOfSpeech() {
Log.e(TAG, "recognizerListener-->onBeginOfSpeech");
showTip("开始说话");
} @Override
public void onEndOfSpeech() {
Log.e(TAG, "recognizerListener-->onEndOfSpeech");
showTip("结束说话");
} @Override
public void onResult(RecognizerResult results, boolean isLast) {
Log.e(TAG, "recognizerListener-->onResult");
String text = JsonParser.parseIatResult(results.getResultString());
mResultText.append(text);
mResultText.setSelection(mResultText.length());
if (isLast) {
// TODO 最后的结果
}
} @Override
public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
Log.e(TAG, "recognizerListener-->onEvent");
} @Override
public void onError(SpeechError arg0) {
Log.e(TAG, "recognizerListener-->onError");
// TODO Auto-generated method stub
}
};
/**
* 听写UI监听器
*/
private RecognizerDialogListener recognizerDialogListener = new RecognizerDialogListener() { public void onResult(RecognizerResult results, boolean isLast) {
Log.e(TAG, "recognizerDialogListener-->onResult");
String text = JsonParser.parseIatResult(results.getResultString());
mResultText.append(text);
mResultText.setSelection(mResultText.length());
} /**
* 识别回调错误.
*/
public void onError(SpeechError error) {
Log.e(TAG, "recognizerDialogListener-->onError");
showTip(error.getPlainDescription(true));
}
};
private InitListener mInitListener = new InitListener() {
@Override
public void onInit(int code) {
Log.e(TAG, "mInitListener-->onInit");
Log.d(TAG, "SpeechRecognizer init() code = " + code);
if (code != ErrorCode.SUCCESS) {
showTip("初始化失败,错误码:" + code);
}
}
}; private void showTip(final String str) {
Log.e(TAG, "showTip-->" + str);
mToast.setText(str);
mToast.show();
} @Override
protected void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
// 退出时释放连接
mIat.cancel();
mIat.destroy();
} @Override
protected void onResume() {
Log.e(TAG, "onResume");
super.onResume();
} @Override
protected void onPause() {
Log.e(TAG, "onPause");
super.onPause();
} }

Android讯飞语音云语音听写学习的更多相关文章

  1. Android 讯飞语音听写SDK快速接入(附空指针解决和修改对话框文字方法)

    1.账号准备工作 首先要有一个讯飞的账号啦,为后面申请APPID.APPKey等东西做准备.顺带一提:讯飞对不同认证类型用户开 放的SDK的使用次数是有不同的,详情如下图. 账号申请完成后,需要去你自 ...

  2. android讯飞语音开发常遇到的问题

    场景:android项目中共使用了3个语音组件:在线语音听写.离线语音合成.离线语音识别 11208:遇到这个错误,授权应用失败,先检查装机量(3台测试权限),以及appid的申请时间(35天期限), ...

  3. android 讯飞语音识别(离线)注意事项

    讯飞语音识别:使用注意事项:mainfest.xml中一定要记得权限写进去21001:我的情况是没有写SpeechApp类,并且需要在application中注册:20005:无匹配结果23300:本 ...

  4. Android 讯飞语音之语音合成(在线有声朗读)

    原文:http://www.cnblogs.com/scetopcsa/p/3845427.html 在线语音合成的使用方法: 首先下载相关的sdk,这个网址里有多种版本,我选择的Android. h ...

  5. 微信小程序语音与讯飞语音识别接口(Java)

    项目需求,需要使用讯飞的语音识别接口,将微信小程序上传的录音文件识别成文字返回 而微信小程序上传的文件格式是silk的,而讯飞接口能识别wav 格式的文件,所以需要将小程序上传的silk文件转成wav ...

  6. 微信小程序语音与讯飞语音识别接口(Java),Kronopath/SILKCodec,ffmpeg处理silk,pcm,wav转换

    项目需求,需要使用讯飞的语音识别接口,将微信小程序上传的录音文件识别成文字返回 首先去讯飞开放平台中申请开通语音识别功能 在这里面下载sdk,然后解压,注意appid与sdk是关联的,appid在初始 ...

  7. 初探机器学习之使用讯飞TTS服务实现在线语音合成

    最近在调研使用各个云平台提供的AI服务,有个语音合成的需求因此就使用了一下科大讯飞的TTS服务,也用.NET Core写了一个小示例,下面就是这个小示例及其相关背景知识的介绍. 一.什么是语音合成(T ...

  8. 关于讯飞语音SDK开发学习

    前奏,浑浑噩噩已经工作一年多,这一年多收获还是挺多的.逛园子应该有两年多了,工作后基本上是天天都会来园子逛逛,园子 里还是有很多牛人写了一些不错的博客,帮我解决很多问题.但是一直没写过博客,归根到底一 ...

  9. 一百元的智能家居——Asp.Net Mvc Api+讯飞语音+Android+Arduino

    大半夜的,先说些废话提提神 如今智能家居已经不再停留在概念阶段,高大上的科技公司都已经推出了自己的部分或全套的智能家居解决方案,不过就目前的现状而言,大多还停留在展厅阶段,还没有广泛的推广起来,有人说 ...

随机推荐

  1. javascript使用栈结构将中缀表达式转换为后缀表达式并计算值

    1.概念 你可能听说过表达式,a+b,a+b*c这些,但是前缀表达式,前缀记法,中缀表达式,波兰式,后缀表达式,后缀记法,逆波兰式这些都是也是表达式. a+b,a+b*c这些看上去比较正常的是中缀表达 ...

  2. Linux下用信号量实现对共享内存的访问保护

    转自:http://www.cppblog.com/zjl-1026-2001/archive/2010/03/03/108768.html 最近一直在研究多进程间通过共享内存来实现通信的事情,以便高 ...

  3. C语言 位运算

    1G=1024M; 1M=102KB; 1KB=1024B(字节); 1B=8bits(位); #include<stdio.h> #include<stdlib.h> //C ...

  4. U3D 动态创建Prefab的多个实例

    情景:我们有一个mytest脚本,一个my_prefab预置体 想在在这个脚本的start()方法中复制多个my_prefab的实例.有3种方法: 1,将预置体my_prefab放于Resouce文件 ...

  5. QuickFIX/J常见问题汇总

    最近在搞QuickFIX/J,网上的资料不算很多,遇到一些简单的问题都需要google一阵才能找到解决方法,因此做点记录: 错误:Rejecting invalid message: quickfix ...

  6. JS replace()方法-字符串首字母大写

    replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. replace()方法有两个参数,第一个参数是正则表达式,正则表达式如果带全局标志/g,则是代表替换 ...

  7. ListView中多个EditText设置焦点 多次点击异常报错

    08-17 18:23:09.825: ERROR/AndroidRuntime(1608): FATAL EXCEPTION: main 08-17 18:23:09.825: ERROR/Andr ...

  8. Python解析器源码加密系列之(二):一次使用标准c的FILE*访问内存块的尝试

    摘要:由于近期打算修改Python解释器以实现pyc文件的加密/解密,出于保密的要求,解密之后的数据只能放在内存中,不能写入到文件中.但是后续的解析pyc文件的代码又只能接受FILE*作为入参,所以就 ...

  9. TCP的三次握手和四次挥手

    置顶文章:<纯CSS打造银色MacBook Air(完整版)> 上一篇:<两个简单的Loading> 作者主页:myvin 博主QQ:851399101(点击QQ和博主发起临时 ...

  10. Lua语言的特别之处

    所谓特别,是相对的,是相对别的主流语言而言,有些也可能只是我个人看法. 1. 函数定义与调用,与代码位置的先后顺序有关,例如 calculate() function calculate() .... ...