Android

语音听写和语音合成

2017-06-26  本文已影响101人  loser先生

简述

今天主要学习了语音听写和语音合成功能的实现,其中语音听写是将语音转化为文字,而语音合成则是将文字转化为语音。基于科大讯飞开放平台,在参考了其示例代码的基础上,写了一个小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) {}
};
上一篇 下一篇

猜你喜欢

热点阅读