前些天项目需要集成一下语音识别,选了百度语音,进入文档中心,看了之后有点头大,从官网下载的Demo也是,很多项目集成在一起的,有点乱。

于是就想先在网上找找有没有已经集成好的拿来用,结果找个一个很有意思的Demo,下载下来半天不到就集成好了。这个Demo还是蛮有意思的,所以询问了一下作者进行转载一下。

作者:八怪不姓丑
链接: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目录中

然后将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"/><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"/><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 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

更多相关文章

  1. Android(安卓)6.0(权限申请)反射和注解实现权限封装
  2. Android(安卓)6.0运行时权限处理与封装(一)
  3. Android包管理机制
  4. Android(安卓)API Guides---System Permissions
  5. android App集成支付宝
  6. Android(安卓)集成 FFmpeg (四) 轻松实现一个音视频编辑 App
  7. java后台程序员转android 《三》之 集成腾讯云 云直播 直播推流
  8. Android(安卓)重学系列 资源管理系统 资源的初始化加载(上)
  9. Android中集成支付宝

随机推荐

  1. android 白天模式/夜间模式切换
  2. Android轮播图 banner,图片视频混播banner
  3. Cocos2d-x在win32,android和IOS下的文件读
  4. Android的FastBoot的安装与环境变量设置
  5. 子墨庖丁Android的ActionBar源码分析 (一
  6. Adobe官网曝光Android版Flash网站优化列
  7. Android JIT带来的虚拟机崩溃问题及解决
  8. Android中RecyclerView的长按
  9. android 将一些信息保存到本地,以后更新版
  10. Android多国语言values文件夹命名