语音听写和语音合成
简述
今天主要学习了语音听写和语音合成功能的实现,其中语音听写是将语音转化为文字,而语音合成则是将文字转化为语音。基于科大讯飞开放平台,在参考了其示例代码的基础上,写了一个小demo,基本实现了语音听写和语音合成功能。
集成科大讯飞
使用科大讯飞的产品服务一般有以下几个步骤:
1、在讯飞开放平台注册开发者账号;
2、申请应用-appkey
登陆成功后,用户-->创建新应用-->应用创建成功后即可生成该应用的id
申请的相关应用 Appid: xnxnnxx
3、下载SDK
在我的应用中,选择需要的服务,然后点击服务如语音听写-->单个服务SDK下载,即可下载SDK.
4、参照文档或者案例集成
如语音听写SDK下载好之后,解压,里面的doc是参考文档,assets是一些图片等资源文件,libs是一些库,sample是一些示例,其中sample中有三个示例,FaceDemo是人脸识别,IsvDempo是声纹识别,SpeechDemo是语音读写,我们只需要将SpeechDemo导入到我们的EnjoyPlayer工程文件中即可,参照这个示例进行编写语音听写的代码。
科大讯飞语音输入和语音合成
参照科大讯飞提供的语音输入和语音合成的示例SpeechDemo,在工程文件下新建一个Module即SpeechSysDemo,在该案例中实现基本的语音输入和语音合成功能。
1、导入SDK
SDK下载完成后解压,打开里面的libs文件夹,将其中的Msc.jar和Sunflower.jar复制到SpeechSysDemo工程里的libs目录下,并右键Add As Library将这两个Jar包作为库添加到该工程中,同时右键src/main-->new Directory-->jniLibs,打开sdk加压包文件夹libs,将其中的jar包之外的其余文件夹复制到SpeechSysDemo的jniLibs中。
2、添加用户权限
<!--连接网络权限,用于执行云端语音能力 -->
<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"/>
<!--外存储读权限,构建语法需要用到此权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--配置权限,用来记录应用配置信息 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<!--手机定位信息,用来为语义等功能提供定位,提供更精准的服务-->
<!--定位信息是敏感信息,可通过 Setting.setLocationEnable(false)关闭定位请求 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--如需使用人脸识别,还要添加:摄相头权限,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />
3、初始化
初始化即创建语音配置对象,只有初始化后才可以使用 MSC 的各项服务。建议将初始
化放在程序入口处(如 Application、Activity 的 onCreate 方法),我们将其放在SpeechSysDemo的MainActivity的onCreate方法中,初始化代码如下:
// 将“12345678”替换成您申请的 APPID,申请地址:http://www.xfyun.cn
// 请勿在“=”与 appid 之间添加任何空字符或者转义符
SpeechUtility.createUtility(this, SpeechConstant.APPID +"=5943551f");//初始化 其中APPID已经替换成了我们自己申请的
4、为了便于快速开发,SDK 提供了识别时用户交互(User Interface)的对话框控件类
RecognizerDialog,又被称为语音输入UI。使用时,需先将SDK资源包assets路径下的资
源文件拷贝至SpeechSysDemo工程asstes目录下(如果asstes没有则新创建asstes目录)。
5、SpeechSysDemo的布局文件很简单,线性布局,包含一个文本输入框和两个按钮,这三个控件垂直排列,文本输入框用于显示语音输入的内容(语音-->文字)同时也可以在输入框中编写内容用于语音合成(文字-->语音),两个按钮分别用于语音输入和语音合成:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/et_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入内容" />
<Button
android:id="@+id/btn_start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="语音输入"/>
<Button
android:id="@+id/btn_speechtext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="语音合成"/>
</LinearLayout>
6、在MainActivity中初始化布局文件的各控件,并且为两个按钮添加点击事件。
private EditText et_input;
private Button btn_start;//语音输入
private Button btn_speechtext;//语音合成
----------------------------------------
//在onCreate方法中对各控件进行实例化,并为两按钮添加点击事件:
et_input = (EditText)findViewById(R.id.et_input);
btn_start = (Button)findViewById(R.id.btn_start);
btn_speechtext = (Button)findViewById(R.id.btn_speechtext);
//设置点击事件
btn_start.setOnClickListener(this);
btn_speechtext.setOnClickListener(this);
----------------------------------------------
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_start://语音输入 语音-->文字
showDialog();
break;
case R.id.btn_speechtext://语音合成 文字-->语音
speechText();
break;
}
}
7、在两按钮的点击事件中分别实现语音输入和语音合成的功能。
private void showDialog() {
//1.创建 RecognizerDialog 对象
RecognizerDialog mDialog = new RecognizerDialog(this, new MyInitListener());
//2.设置accent、language等参数
mDialog.setParameter(SpeechConstant.LANGUAGE,"zh_cn");
mDialog.setParameter(SpeechConstant.ACCENT,"mandarin");
//若要将 RecognizerDialog 用于语义理解,必须添加以下参数设置,设置之后 onResult回调返回将是语义理解的结果
// mDialog.setParameter("asr_sch", "1");
// mDialog.setParameter("nlp_version", "3.0");
//3.设置回调接口
mDialog.setListener(new MyRecognizerDialogListener());
//4.显示 dialog,接收语音输入
mDialog.show();
}
class MyInitListener implements InitListener {
@Override
public void onInit(int i) {
if (i != ErrorCode.SUCCESS){
Toast.makeText(MainActivity.this,"初始化失败",Toast.LENGTH_SHORT).show();
}
}
}
class MyRecognizerDialogListener implements RecognizerDialogListener{
/**
*返回结果
* @param recognizerResult
* @param b 是否说话结束
*/
@Override
public void onResult(RecognizerResult recognizerResult, boolean b) {
String result = recognizerResult.getResultString();
Log.e("MainActivity","result == "+ result);
String text = JsonParser.parseIatResult(result);//对返回的json数据进行解析
//解析好的
Log.e("MainActivity", "text ==" + text);
String sn = null;
// 读取json结果中的sn字段
try {
JSONObject resultJson = new JSONObject(recognizerResult.getResultString());
sn = resultJson.optString("sn");
} catch (JSONException e) {
e.printStackTrace();
}
mIatResults.put(sn, text);
StringBuffer resultBuffer = new StringBuffer();//拼成一句
for (String key : mIatResults.keySet()) {
resultBuffer.append(mIatResults.get(key));
}
et_input.setText(resultBuffer.toString());
et_input.setSelection(et_input.length());
}
/**
* 出错了
* @param speechError
*/
@Override
public void onError(SpeechError speechError) {
Log.e("MainActivity","onError == "+ speechError.getMessage());
}
}
注:parseIatResult方法来源于JsonParser类,该类是从SpeechDemo中复制到SpeechSysDemo中的,主要用于解析在回调方法onResult中得到的Json类型的数据(结果)。
----------------------------------------------------------------------
private void speechText() {
//1.创建 SpeechSynthesizer 对象, 第二个参数: 本地合成时传 InitListener
SpeechSynthesizer mTts= SpeechSynthesizer.createSynthesizer(this, null);
//2.合成参数设置,详见《 MSC Reference Manual》 SpeechSynthesizer 类
//设置发音人(更多在线发音人,用户可参见 附录13.2
mTts.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan"); //设置发音人 小燕 青年女声 普通话
mTts.setParameter(SpeechConstant.SPEED, "50");//设置语速
mTts.setParameter(SpeechConstant.VOLUME, "80");//设置音量,范围 0~100
mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); //设置云端
//设置合成音频保存位置(可自定义保存位置),保存在“./sdcard/iflytek.pcm”
//保存在 SD 卡需要在 AndroidManifest.xml 添加写 SD 卡权限
//仅支持保存为 pcm 和 wav 格式, 如果不需要保存合成音频,注释该行代码
mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, "./sdcard/iflytek.pcm");
//3.开始合成
mTts.startSpeaking(et_input.getText().toString(), mSynListener);
}
//合成监听器
private SynthesizerListener mSynListener = new SynthesizerListener(){
//会话结束回调接口,没有错误时, error为null
public void onCompleted(SpeechError error) {}
//缓冲进度回调
//percent为缓冲进度0~100, beginPos为缓冲音频在文本中开始位置, endPos表示缓冲音频在
//文本中结束位置, info为附加信息。
public void onBufferProgress(int percent, int beginPos, int endPos, String info) {}
//开始播放
public void onSpeakBegin() {}
//暂停播放
public void onSpeakPaused() {}
//播放进度回调
//percent为播放进度0~100,beginPos为播放音频在文本中开始位置, endPos表示播放音频在文
//本中结束位置.
public void onSpeakProgress(int percent, int beginPos, int endPos) {}
//恢复播放回调接口
public void onSpeakResumed() {}
//会话事件回调接口
public void onEvent(int arg0, int arg1, int arg2, Bundle arg3) {}
};