Android开发集成科大讯飞语音识别+语音合成功能

(本Demo的开发环境为Android Studio)。

转载自:http://blog.csdn.net/highboys/article/details/52145038

一、语音识别

1.下载SDK(地址: http://www.xfyun.cn/sdk/dispatcher ),选择语音听写SDK(如下图) ,下载前会让你先创建应用,创建应用后会得到一个appid。然后点“立即开通”去开通“语音识别”功能,之后就会跳出“SDK下载”的页面,然后就可以下载了(未注册账号的要先注册一个账号)。
Android开发集成科大讯飞语音识别+语音合成功能_第1张图片
Android开发集成科大讯飞语音识别+语音合成功能_第2张图片
2.将下载好的SDK中 libs 目录下的 Msc.jar包引入到工程中(参见 http://blog.csdn.net/highboys/article/details/51549679 ,此外,因为本Demo中会用到json的东西,所以还得自己去网上下一个Gson的jar包,一并引进去)。之后在main目录下新建一个jniLibs目录,将 SDK中libs 目录下的armeabi 拷进去,如下图所示(第④个先不用管): 
Android开发集成科大讯飞语音识别+语音合成功能_第3张图片
3.科大讯飞为我们提供了一套语音听写时的UI,即听写的时候会有一个动画效果(如下图),这个时候我们需要 先将 SDK 资源包 assets 路径下的资源文件拷贝至 Android 工程asstes 目录下(没有的话自己新建),参照第2步图的④。
4.接下来就是代码的实现了。首先在Manifest中添加一下权限

    
    
    
    
    
    
    
    
    
    
    

    
    
    
    
其次是java代码(逻辑上是点击了某个Button之后,才执行下面的代码)。
//有动画效果
    private RecognizerDialog iatDialog;
// ①语音配置对象初始化
                SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID + "=578f1af7");//将这里的578f1af7替换成自己申请得到的8位appid
                // ②初始化有交互动画的语音识别器
                iatDialog = new RecognizerDialog(MainActivity.this, mInitListener);
  //③设置监听,实现听写结果的回调
                iatDialog.setListener(new RecognizerDialogListener() {
                    String resultJson = "[";//放置在外边做类的变量则报错,会造成json格式不对(?)

                    @Override
                    public void onResult(RecognizerResult recognizerResult, boolean isLast) {
                        System.out.println("----------------- onResult -----------------");
                        if (!isLast) {
                            resultJson += recognizerResult.getResultString() + ",";
                        } else {
                            resultJson += recognizerResult.getResultString() + "]";
                        }

                        if (isLast) {
                            //解析语音识别后返回的json格式的结果
                            Gson gson = new Gson();
                            List resultList = gson.fromJson(resultJson,
                                    new TypeToken>() {
                                    }.getType());
                            String result = "";
                            for (int i = 0; i < resultList.size() - 1; i++) {
                                result += resultList.get(i).toString();
                            }
                            etText.setText(result);
                            //获取焦点
                            etText.requestFocus();
                            //将光标定位到文字最后,以便修改
                            etText.setSelection(result.length());
                        }
                    }

                    @Override
                    public void onError(SpeechError speechError) {
                        //自动生成的方法存根
                        speechError.getPlainDescription(true);
                    }
                });
                //开始听写,需将sdk中的assets文件下的文件夹拷入项目的assets文件夹下(没有的话自己新建)
                iatDialog.show();
其中的mInitListener定义如下:(此处写在方法外即可)
public static final String TAG = "MainActivity";
    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();
            }
        }
    };

上面的代码用到了一个DictationResult类(一个用来接收转换 语音听写结果的类),需要自己新建,定义如下
/**
 * 解析 语音听写返回结果Json格式字符串 的模板类(多重嵌套Json)
 *
 * 语音识别结果Json数据格式(单条数据):
 * {"sn":1,"ls":true,"bg":0,"ed":0,"ws":[
 * {"bg":0,"cw":[{"w":"今天","sc":0}]},
 * {"bg":0,"cw":[{"w":"的","sc":0}]},
 * {"bg":0,"cw":[{"w":"天气","sc":0}]},
 * {"bg":0,"cw":[{"w":"怎么样","sc":0}]},
 * {"bg":0,"cw":[{"w":"。","sc":0}]}
 * ]}
 *
 * sn number :第几句
 * ls boolean: 是否最后一句
 * bg number :开始
 * ed number :结束
 * ws array :词
 * cw array :中文分词
 * w string :单字
 * sc number :分数
 */
public class DictationResult {
    private String sn;
    private String ls;
    private String bg;
    private String ed;

    private List ws;

    public static class Words {
        private String bg;
        private List cw;

        public static class Cw {
            private String w;
            private String sc;

            public String getW() {
                return w;
            }

            public void setW(String w) {
                this.w = w;
            }

            public String getSc() {
                return sc;
            }

            public void setSc(String sc) {
                this.sc = sc;
            }

            @Override
            public String toString() {
                return w;
            }
        }

        public String getBg() {
            return bg;
        }

        public void setBg(String bg) {
            this.bg = bg;
        }

        public List getCw() {
            return cw;
        }

        public void setCw(List cw) {
            this.cw = cw;
        }

        @Override
        public String toString() {
            String result = "";
            for (Cw cwTmp : cw) {
                result += cwTmp.toString();
            }
            return result;
        }
    }

    public String getSn() {
        return sn;
    }

    public void setSn(String sn) {
        this.sn = sn;
    }

    public String getLs() {
        return ls;
    }

    public void setLs(String ls) {
        this.ls = ls;
    }

    public String getBg() {
        return bg;
    }

    public void setBg(String bg) {
        this.bg = bg;
    }

    public String getEd() {
        return ed;
    }

    public void setEd(String ed) {
        this.ed = ed;
    }

    public List getWs() {
        return ws;
    }

    public void setWs(List ws) {
        this.ws = ws;
    }

    @Override
    public String toString() {
        String result = "";
        for (Words wsTmp : ws) {
            result += wsTmp.toString();
        }
        return result;
    }
}

如此,便可实现语音听写了。这个过程可能会遇到各种各样的问题,具体错误码参见  http://www.xfyun.cn/doccenter/faq
5.说完了有动画效果的,下面就来说说没有动画效果的(也比较简单)。
//1.创建SpeechRecognizer对象,第二个参数:本地识别时传InitListener
    SpeechRecognizer mIat = SpeechRecognizer.createRecognizer(context, null);
    //2.设置听写参数,详见SDK中《MSC Reference Manual》文件夹下的SpeechConstant类
    mIat.setParameter(SpeechConstant.DOMAIN,"iat");
    mIat.setParameter(SpeechConstant.LANGUAGE,"zh_cn");
    mIat.setParameter(SpeechConstant.ACCENT,"mandarin ");

      //保存音频文件到本地(有需要的话) 仅支持pcm和wav,且需要自行添加读写SD卡权限
    mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/mIat.wav");
    // 3.开始听写
    mIat.startListening(mRecoListener);
    //听写监听器
    private RecognizerListener mRecoListener = new RecognizerListener() {
        //听写结果回调接口(返回Json格式结果,用户可参见附录13.1);
        // 一般情况下会通过onResults接口多次返回结果,完整的识别内容是多次结果的累加;
        // 关于解析Json的代码可参见Demo中JsonParser类;
        // isLast等于true时会话结束。
        public void onResult(RecognizerResult results, boolean isLast) {
            Log.d(TAG, "result:" + results.getResultString());
        }

        //会话发生错误回调接口
        public void onError(SpeechError error) {
            //打印错误码描述
            Log.d(TAG, "error:" + error.getPlainDescription(true))
        }

        //开始录音
        public void onBeginOfSpeech() {
        }

        // volume音量值0~30,data音频数据
        public void onVolumeChanged(int volume, byte[] data) {
        }

        //结束录音
        public void onEndOfSpeech() {
        }

        //扩展用接口
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
        }
    };

可以看到上面的onResult回调方法跟有动画效果时的onResult回调方法是一样的,所以主要的处理还是在这个方法中,将有动画的那个onResult回调中的代码拷过来就行了。如此,简单的语音听写功能就实现了。

效果图:

Android开发集成科大讯飞语音识别+语音合成功能_第4张图片

二、语音合成

1.语音合成也需要创建语音配置对象:
SpeechUtility.createUtility(MainActivity.this, SpeechConstant.APPID + "=578f1af7");
2.创建用于语音合成的对象并设置参数,进行语音合成
//1.创建SpeechSynthesizer对象, 第二个参数:本地合成时传InitListener
        SpeechSynthesizer mTts = SpeechSynthesizer.createSynthesizer(MainActivity.this, null);

        /**
         2.合成参数设置,详见《科大讯飞MSC API手册(Android)》SpeechSynthesizer 类
         */
        // 清空参数
        mTts.setParameter(SpeechConstant.PARAMS, null);

        mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD); //设置云端
        mTts.setParameter(SpeechConstant.VOICE_NAME, "xiaoyan");//设置发音人
        mTts.setParameter(SpeechConstant.SPEED, "50");//设置语速
        //设置合成音调
        mTts.setParameter(SpeechConstant.PITCH, "50");
        mTts.setParameter(SpeechConstant.VOLUME, "80");//设置音量,范围0~100
        mTts.setParameter(SpeechConstant.STREAM_TYPE, "3");
        // 设置播放合成音频打断音乐播放,默认为true
        mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");

        // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        // 注:AUDIO_FORMAT参数语记需要更新版本才能生效
// mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
// boolean isSuccess = mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/tts2.wav");
// Toast.makeText(MainActivity.this, "语音合成 保存音频到本地:\n" + isSuccess, Toast.LENGTH_LONG).show();
        //3.开始合成
        int code = mTts.startSpeaking("在这里放置需要进行合成的文本", mSynListener);

        if (code != ErrorCode.SUCCESS) {
            if (code == ErrorCode.ERROR_COMPONENT_NOT_INSTALLED) {
                //上面的语音配置对象为初始化时:
                Toast.makeText(MainActivity.this, "语音组件未安装", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(MainActivity.this, "语音合成失败,错误码: " + code, Toast.LENGTH_LONG).show();
            }
        }

合成时需要一个SynthesizerListener类型的合成监听器作参数,定义如下
//合成监听器
    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) {
        }
    };
本文参照SDK中doc文件夹下的  MSC Develop Manual for Android.pdf 文件完成,里边写得很详细。也可参见   http://www.xfyun.cn/doccenter/awd   。
常见问题   http://www.xfyun.cn/doccenter/faq
效果:
Android开发集成科大讯飞语音识别+语音合成功能_第5张图片
错误码
10000~19999的错误码参见 MSC错误码
其它错误码参见下表:
错误码 数值 含义
ERROR_NO_NETWORK 20001 无有效的网络连接
ERROR_NETWORK_TIMEOUT 20002 网络连接超时
ERROR_NET_EXPECTION 20003 网络连接发生异常
ERROR_INVALID_RESULT 20004 无有效的结果
ERROR_NO_MATCH 20005 无匹配结果
ERROR_AUDIO_RECORD 20006 录音失败
ERROR_NO_SPPECH 20007 未检测到语音
ERROR_SPEECH_TIMEOUT 20008 音频输入超时
ERROR_EMPTY_UTTERANCE 20009 无效的文本输入
ERROR_FILE_ACCESS 20010 文件读写失败
ERROR_PLAY_MEDIA 20011 音频播放失败
ERROR_INVALID_PARAM 20012 无效的参数
ERROR_TEXT_OVERFLOW 20013 文本溢出
ERROR_INVALID_DATA 20014 无效数据
ERROR_LOGIN 20015 用户未登陆
ERROR_PERMISSION_DENIED 20016 无效授权
ERROR_INTERRUPT 20017 被异常打断
ERROR_VERSION_LOWER 20018 版本过低
ERROR_COMPONENT_NOT_INSTALLED 21001 没有安装语音组件
ERROR_ENGINE_NOT_SUPPORTED 21002 引擎不支持
ERROR_ENGINE_INIT_FAIL 21003 初始化失败
ERROR_ENGINE_CALL_FAIL 21004 调用失败
ERROR_ENGINE_BUSY 21005 引擎繁忙
ERROR_LOCAL_NO_INIT 22001 本地引擎未初始化
ERROR_LOCAL_RESOURCE 22002 本地引擎无资源
ERROR_LOCAL_ENGINE 22003 本地引擎内部错误
ERROR_IVW_INTERRUPT 22004 本地唤醒引擎被异常打断
ERROR_UNKNOWN 20999 未知错误
合成发音人列表
  1. 语言为中英文的发音人可以支持中英文的混合朗读。
  2. 英文发音人只能朗读英文,中文无法朗读。
  3. 汉语发音人只能朗读中文,遇到英文会以单个字母的方式进行朗读。
  4. 使用新引擎参数会获得更好的合成效果。
名称 属性 语言 参数名称 新引擎参数 备注
小燕 青年女声 中英文
(普通话)
xiaoyan   默认
小宇 青年男声 中英文
(普通话)
xiaoyu    
凯瑟琳 青年女声 英文 catherine    
亨利 青年男声 英文 henry    
玛丽 青年女声 英文 vimary    
小研 青年女声 中英文
(普通话)
vixy    
小琪 青年女声 中英文
(普通话)
vixq xiaoqi  
小峰 青年男声 中英文
(普通话)
vixf    
小梅 青年女声 中英文
(粤语)
vixm xiaomei  
小莉 青年女声 中英文
(台湾普通话)
vixl    
晓琳 青年女声 中英文
(台湾普通话)
  xiaolin  
小蓉 青年女声 汉语
(四川话)
vixr xiaorong  
小芸 青年女声 汉语
(东北话)
vixyun    
小倩 青年女声 汉语
(东北话)
  xiaoqian  
小坤 青年男声 汉语
(河南话)
vixk xiaokun  
小强 青年男声 汉语
(湖南话)
vixqa xiaoqiang  
小莹 青年女声 汉语
(陕西话)
vixying    
小新 童年男声 汉语
(普通话)
vixx xiaoxin  
楠楠 童年女声 汉语
(普通话)
vinn nannan  
老孙 老年男声 汉语
(普通话)
vils    
Mariane   法语 Mariane    
Allabent   俄语 Allabent    
Gabriela   西班牙语 Gabriela    
Abha   印地语 Abha    
XiaoYun   越南语 XiaoYun    

你可能感兴趣的:(Android)