安卓平台使用pocketSphinx离线语音识别
版权声明:本文为elecdog原创文章,可以转载,但必须在明确位置注明出处!谢谢合作。
关于语音识别,国内已经有比较好的公司推出相关的服务了,比如百度免费的离在线融合语音识别以及讯飞收费的在线和离线语音识别服务。这里不作过多介绍,需要的同学可以直接去官网阅读接入文档。这里要介绍的是一个离线语音识别的开源项目——CMU PocketSpinnx,在安卓开发中的使用。在智能家居 APP 开发中常需要在没法联网的设备识别一些比较简单的命令词,百度的离在线融合语音识别识别率还不错,不过在设备连接局域网的情况下仍然优先使用在线识别,导致识别时间太长或者转换不过来,讯飞离线语音识别没有使用过,因为是收费的,而且对于个人开发者价格也不便宜,相比较之下,PocketSpinnx则是完全离线的语音识别,只要按照要求部署项目,识别率也差强人意。
首先我们可以通过 PocketSpinnx 官网的介绍来了解该离线语音识别项目的工作原理,能够加深对项目使用的理解。下面我们一步一步来把PocketSpinnx的离线语音识别功能引入到我们自己的项目中来。
获取语言模型
首先我们需要把想要识别的命令词编写成命令集,打开 Sublime Text 新建 txt 文件,编码采用 utf-8,每一行写一个命令词,如图所示:
然后访问网址 http://www.speech.cs.cmu.edu/tools/lmtool-new.html 生成语言模型(国内访问不稳定,需自备梯子),点击选择文件,选择刚才编写的命令集文件 command.txt,然后点击COMPILE KNOWLEDGE BASE按钮就可以生成语言模型,如图:
这里生成了好几个文件,我们可以把整个 .tgz 文件下载下来解压缩,其中得到的 .lm 文件就是我们需要的语言模型。
获取字典模型
字典模型的作用,就是告诉语音识别器中文的发音,这样他才能认得中文,字典模型很简单,首先到 PocketSpinnx 的资源网盘,进入 Mandarin 文件夹,下载一个后缀为 .dic 的文件,里面涵盖了很多普通话的发音,查找到我们的命令词,找不到完整命令词的也可以找单个字的发音,然后参考这个 .dic 文件的格式,在上一步获取到的 .lm 语言模型文件中还有一个 .dic 文件,补充完整这个 .dic 文件的发音,如图所示:
这样字典模型就算是完成了。
获取声学模型
同样是在资源网盘的 Mandarin 文件夹下,下载 .tar.bz2 的压缩文件解压后,得到如下声学模型文件:
在项目中导入接口
在以上必要文件都准备好之后,我们可以在 PocketSpinnx 开源的安卓 demo中直观地了解具体的用法,项目结构如图所示:
我们可以把 demo 中的 aars 和 models 导入到我们自己的项目中,快速集成相关接口。demo 中 en-us-ptm 中的是英文的声学模型,为了能够识别中文,我们可以依样画葫芦新建一个 ptm-zh 文件夹,放入我们前面获取的普通话声学模型。同时,还需要把我们的语言模型和字典模型放进来,准备工作算是完成了。
获取识别器
现在我们已经可以在项目中调用相关的 API 了,首先需要获取最重要的语音识别器类SpeechRecognizer
,如demo中的代码:
private void runRecognizerSetup() {
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in async task
new AsyncTask<Void, Void, Exception>() {
@Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(PocketSphinxActivity.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
@Override
protected void onPostExecute(Exception result) {
if (result != null) {
((TextView) findViewById(R.id.caption_text))
.setText("Failed to init recognizer " + result);
} else {
switchSearch(KWS_SEARCH);
}
}
}.execute();
}
private void setupRecognizer(File assetsDir) throws IOException {
// The recognizer can be configured to perform multiple searches
// of different kind and switch between them
recognizer = SpeechRecognizerSetup.defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))//设置声学模型的文件夹
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))//设置字典模型
.setRawLogDir(assetsDir) // To disable logging of raw audio comment out this call (takes a lot of space on the device)
.getRecognizer();
recognizer.addListener(this);
/** In your application you might not need to add all those searches.
* They are added here for demonstration. You can leave just one.
*/
// 创建短语监听
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
//创建命令文件监听
File menuGrammar = new File(assetsDir, "menu.gram");
recognizer.addGrammarSearch(MENU_SEARCH, menuGrammar);
// Create grammar-based search for digit recognition
File digitsGrammar = new File(assetsDir, "digits.gram");
recognizer.addGrammarSearch(DIGITS_SEARCH, digitsGrammar);
// Create language model search
File languageModel = new File(assetsDir, "weather.dmp");
recognizer.addNgramSearch(FORECAST_SEARCH, languageModel);
// Phonetic search
File phoneticModel = new File(assetsDir, "en-phone.dmp");
recognizer.addAllphoneSearch(PHONE_SEARCH, phoneticModel);
}
private void switchSearch(String searchName) {
recognizer.stop();
// If we are not spotting, start listening with timeout (10000 ms or 10 seconds).
if (searchName.equals(KWS_SEARCH))
recognizer.startListening(searchName);
else
recognizer.startListening(searchName, 10000);
}
这里需要注意设置声学模型文件夹的时候不需要写成 sync/ptm-zh,sync不需要写,否则会报错找不到文件。到这里按照 demo 的示例代码基本可以学会重要的方法调用了,如开始监听和结束监听等。
这里再提一下我们创建命令文件监听的时候需要使用的 .gram 文件,其实看一下 demo 中的 .gram 文件我们也知道该如何编写自己的命令文件了
#JSGF V1.0;
grammar menu;
public <item> = 命令词1 | 命令词2 | 命令词3;
一旦开始命令文件监听,则监听器就会监听命令文件中的命令词,当监听到语音的时候就会取出发音最相似的那个命令词返回到监听结果。请注意,这里意思是取出发音最相近的,这导致的时候也许你并没有说这些命令词的任何一个,只是监听器同样会取出他认为最相近的一个返回给结果,也就是表现的识别过于敏感,我在使用过程中还是属于可接受范围内。可以根据自己需求选择短语监听或者命令文件监听。
结束
到这里基本就可以使用 PocketSpinnx 离线语音识别了,一些细节的处理还需要自己阅读 demo 中的代码,代码不多而且容易理解,可以加深对使用的理解,另外,推荐阅读官方文档,能够详细知道项目的运行原理,以及文中没有提到的一些内容,虽然是英文的,但通过单词翻译也不难理解。
安卓平台使用pocketSphinx离线语音识别的更多相关文章
- Android离线语音识别(PocketSphinx)
近期做项目.用到离线语音识别.整了好久,查了好多方法.最终完毕.网上资料有点乱,并且大部分就是那几个人写的.一群人转!以下我总结一下.也为后来人行个方便. 关于环境配置我就不多说了.我就是依照这个教程 ...
- 安卓平台 全面支持软解和硬解的SDK-Demo源代码开放
专业做视频编解码的SDK开发工作. 2015年12月1日10:46:55: 更新到1.5.0版本 功能列表: 基本播放: 1,正常播放, 支持MP4,FLV,AVI,TS,3GP,RMVB,WM,WM ...
- 在Unity3D中实现安卓平台的本地通知推送
[前言] 对于手游来说,什么时候需要推送呢?玩过一些带体力限制的游戏就会发现,我的体力在恢复满后,手机会收到一个通知告诉我体力已完全恢复了.这类通知通常是由本地的客户端发起的,没有经过服务端. 在安卓 ...
- ionic3 打包安卓平台环境搭建报错解决方案总结
1.jvm虚拟机提供的运行空间小于项目所需的空间是报错.如图: 解决方法:在环境变量中配置jvm的运行内存大小,大于所需的内存即可. 其中:-Xmx512M可根据实际提示情况,进行更改,如1024M, ...
- Unity切换到安卓平台Shader丢失(opengl)
Unity安卓平台shader平台丢失 Unity的工程切换到Android平台后,运行游戏出现shader丢失 解决办法:在Unity桌面图标的快捷方式后添加 -force-gles20 示例:&q ...
- cocos2d-x 3.0 WIN7+VS2012 安卓平台搭建
***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...
- cocos2d-x hello world及安卓平台迁移
本节和大家一起新建一个项目工程,并通过cygwin迁移至android平台. 以下是本节主要内容: 利用cocos2d-x自带脚本,生成测试工程,并测试运行: 将该测试项目通过cyg ...
- 安卓平台ARM Mali OpenCL例子-灰度转换(转)
手头一块RK3288的板子,在板子上测试了一张1080p的彩色图灰度转换的OpenCL例子.OpenCL没有任何优化.例子请移步这里. 该例子是编译成安卓平台下的可执行程序. 进入jni文件夹,进行如 ...
- phongap开发中安卓平台上如何调用第三方播放器来播放HLS视频
前文曾经讲了关于在安卓平台上利用phonegap开发播放HLS的解决方案,其实最好的方案就是自己针对HLS视频开发自己的播放器,但是开发播放器是一个浩大的工程,必须对原生安卓开发非常熟悉,并且对视频播 ...
随机推荐
- 实验:Oracle数据泵导出导入之序列问题
今天同事提出了一个问题: 使用数据泵expdp导出1个schema,有个表主键是触发器自增的id,导入测试库测试时,发现表里的数据比自增序列的值要大.导致插入数据报错. 最终结论是: 由于数据库先进行 ...
- Mac OS X 安装后的简单设置
让Mac拥有类似apt-get的功能--安装Homebrew Homebrew是一个包管理器,用于在Mac上安装一些OS X没有的UNIX工具(比如著名的wget). 国内下载地址:http://ww ...
- 并发编程(三):从AQS到CountDownLatch与ReentrantLock
一.目录 1.AQS简要分析 2.谈CountDownLatch 3.谈ReentrantLock 4.谈消费者与生产者模式(notfiyAll/wait.si ...
- 遇到android.os等系统sdk包没有自动导入的情况
采取手动导入,build path,然后add external jar,找到sdk的安装目录,导入android 的jar包即可
- Android 任何位置的可移动悬浮窗
刚好要做这块的东西,所以网上翻了下资料,百度出来的基本上都是:默认起始位置左上角,还不能改动,一改动起始位置,第二次拖动就不正常了~~ 下面直接附上任意位置可拖动的源码(由于是demo写的比较乱): ...
- redis内存消耗详解
Redis所有的数据都存在内存中,相对于廉价的硬盘,内存资源还是比较昂贵的,因此如何高效利用redis内存变得非常重要. 内存消耗分析 管理内存的原理和方法 内存优化技巧 一.内存消耗 理解redis ...
- 网络配置之nmcli
使用nmcli命令配置网络 NetworkManager是管理和监控网络设置的守护进程,设备既就是网络接口,连接是对网络接口的配置,一个网络接口可以有多个连接配置,但同时只有一个连接配置生效. 1 配 ...
- 浅入深出之Java集合框架(下)
Java中的集合框架(下) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,哈哈这篇其实也还是基础,惊不惊喜意不意外 ̄▽ ̄ 写文真的好累,懒得写了.. ...
- hdu2413(二分+二分匹配)
题意:人和外星人星球大战,人总共有H个星球,外星人有A个星球,现在人要用飞船去打外星人的飞船,要求每个人类星球只能对战一个外星球,且每个星球都开始有己知的飞船数,不论是人或外星人的星球,并每个星球都有 ...
- 将ArrayList<HashMap<String, String>>转为ArrayList<Bundle>类型的解决方案
Bundle是一种利用键值对存储的数据格式,而我们在程序中通常利用HashMap存储数据.在开发中,通过Http请求得到JSONArray类型的返回值,我选择利用ArrayList<HashMa ...