Android集成讯飞语音、百度语音、阿里语音识别

一、引言

demo下载地址:https://fir.im/jy28
demo源码查看:https://github.com/wapchief/android-CollectionDemo
效果图:

选这几个平台的主要也是从多方面考虑。
大概从这几个

  • 识别精准度
  • 免费限制
  • 稳定程度
  • 包体积
  • 拓展性

目前只有百度的语音服务支持长语音(60秒以上),和离线语音识别。
当然语音的库(.so)文件也是最大的。足足10多M。

二、申请应用

在集成之前,需要去相应的平台去申请应用。
拿到key等密钥。目前这几个平台都在测试免费层限制中。

百度是完全免费,讯飞有免费层日调用次数限制。

三、集成

首先去各大平台下载对于的语音文件库
一般都包含.so和libs两部分。这两部分都需要加入到项目中。

不过这里只需要注意一点是,每个平台的文档不一样,有些是使用libs集成第三方库,有些是使用jnilibs加载。

如果都按照第三方文档来集成,必定会出错。
这里统一使用jniLibs来集成(只适用于AndroidStudio)。如果是eclipse,则需要使用libs集成

如果在集成中遇到了问题,可以参考我以前写过的解决方案
Android关于libs,jniLibs库的基本使用说明及冲突解决

1、(必须)将下载后的所有so库文件(以.so结尾的文件)拷贝至项目下/app/src/main目录,如果没有则创建一个,里面的名字是固定的,注意不能修改,必须按照这样的架构目录集成。

2、(必须)将jar文件拷贝到libs目录中


image.png

然后将jar添加到项目。
可以使用右键对应的jar包,add-libs手动添加

3、(必须)在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"/>
<!--外存储读权限,构建语法需要用到此权限 -->
<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" />

如果SDK版本在6.0以上需要在项目中手动获取录音权限


    /*动态权限申请*/
    private void initPermission() {
        String permission[] = {Manifest.permission.RECORD_AUDIO,
                Manifest.permission.ACCESS_NETWORK_STATE,
                Manifest.permission.INTERNET,
                Manifest.permission.WRITE_EXTERNAL_STORAGE};
        ArrayList<String> applyList = new ArrayList<>();

        for (String per : permission) {
            if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, per)) {
                applyList.add(per);
            }
        }

        String tmpList[] = new String[applyList.size()];
        if (!applyList.isEmpty()) {
            ActivityCompat.requestPermissions(this, applyList.toArray(tmpList), 123);
        }
    }

四、初始化服务

各个平台的初始化方法都不一样。
但大多数都是在自己项目的Application中初始化。


        //初始化讯飞语音
        SpeechUtility.createUtility(mContext, SpeechConstant.APPID +"=59daecea," + SpeechConstant.FORCE_LOGIN +"=true");
        //讯飞调试日志开启
        Setting.setShowLog(true);
        //初始化阿里语音
        NlsClient.openLog(true);
        NlsClient.configure(mContext);

有些是在AndroidManifest.xml中初始化

       <!--******************************百度语音**********************************-->
        <meta-data android:name="com.baidu.speech.APP_ID"
            android:value="8172882" />
        <meta-data
            android:name="com.baidu.speech.API_KEY"
            android:value="R3crsZhvpqQSrLGUvG7kuG0pCnpTbXvb" />
        <meta-data
            android:name="com.baidu.speech.SECRET_KEY"
            android:value="6MafqZkSLoNYUML1YduHPDYBg1kkPLHj" />

        <service android:name="com.baidu.speech.VoiceRecognitionService" android:exported="false"/>

五、开启识别服务

以讯飞为例:
在开始识别前需要初始化识别对象,

 SpeechRecognizer  recognizer = SpeechRecognizer.createRecognizer(this, null);

然后配置听写参数

    /**
     * 参数设置
     */
    public void setParam() {
        //2.设置听写参数,详见《科大讯飞MSC API手册(Android)》SpeechConstant类
        recognizer.setParameter(SpeechConstant.DOMAIN, "iat");
        recognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        recognizer.setParameter(SpeechConstant.ACCENT, "mandarin ");
        //设置音频保存路径
        recognizer.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        recognizer.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/iat.wav");

    }

开始识别的开始和终止,及识别过程的内容回调

    //开启
    private void startXF() {
        setParam();
        recognizer.startListening(recognizerListener);
    }

    //停止
    private void stopXF() {

        recognizer.stopListening();
    }


    /*监听*/
    private RecognizerListener recognizerListener = new RecognizerListener() {
        @Override
        public void onVolumeChanged(int i, byte[] bytes) {
            //音量变化
        }

        @Override
        public void onBeginOfSpeech() {
            //开始说话
            Log.e(TAG, "XF开始说话");
        }

        @Override
        public void onEndOfSpeech() {
            //结束说话
            Log.e(TAG, "XF结束说话");

        }

        @Override
        public void onResult(RecognizerResult recognizerResult, boolean b) {
            //返回结果需要判断null
            text = JsonParser.parseIatResult(recognizerResult.getResultString());
            Log.e(TAG, "XFResult:" + text + "\n" + recognizerResult.getResultString());
            mVoiceTv.setText(recognizerResult.getResultString());
            printResult(recognizerResult);
        }

        @Override
        public void onError(SpeechError speechError) {
            //错误回调
            Log.e(TAG, "XFError:" + speechError.toString());

        }

        @Override
        public void onEvent(int i, int i1, int i2, Bundle bundle) {
            //事件拓展
        }
    };

解析语音识别的结果。

    //储存听写结果
    private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();

 /*解析器*/
    private void printResult(RecognizerResult results) {
        String text = JsonParser.parseIatResult(results.getResultString());

        String sn = null;
        // 读取json结果中的sn字段
        try {
            JSONObject resultJson = new JSONObject(results.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));
        }

        mVoiceEt.setText("讯飞识别结果:" + resultBuffer.toString());
        mVoiceEt.setSelection(mVoiceEt.length());
//        mVoiceTv.setText(resultBuffer.toString());
    }

六、异常及其他

SecurityException异常:
如果是在6.0以上版本的sdk可能会出现该问题,主要是临时权限调用,比如调用系统的录音文件播放,或者调用系统的图库。
可以参考调用图库的解决方案,原理一样
Android版本相机适配问题集合(不断整理更新中)

demo下载地址:
https://fir.im/jy28
demo源码:
https://github.com/wapchief/android-CollectionDemo

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容