您的位置:首页 > 移动开发 > Android开发

用Kotlin开发android平台语音识别语义理解应用

2017-08-09 15:57 435 查看
Kotlin开发android平台语音识别,语义理解应用(olamisdk转载请注明CSDN博文地址:http://blog.csdn.net/ls0609/article/details/75084994本文使用Kotlin开发Android平台的一个语音识别方面的应用,用的是欧拉密开放平台olamisdk。

1.Kotlin简介

Kotlin是由JetBrains创建的基于JVM的编程语言,IntelliJ正是JetBrains的杰作,而android Studio是
基于IntelliJ修改而来的。Kotlin是一门包含很多函数式编程思想的面向对象编程语言。
  后来了解到Kotlin原来是以一个岛的名字命名的(Котлин),它是一门静态类型编程语言,支持JVM平台,android平台,浏览器js运行环境,本地机器码等。支持与Java,Android
100% 完全互操作。Kotlin生来就是为了弥补Java缺失的现代语言的特性,并极大的简化了代码,使得开发者可以编写尽量少的样板代码。

2.Kotlin,java,Swift简单比较

1.输出Hello,World!

JAVA: System.out.println("Hello,World!");
Kotlin: println("Hello,World!")
Swift: print("Hello,World!")2.变量和常量

Java: int mVariable
=10;
mVariable =20; static final int mConstant
= 10;
Kotlin:var mVariable
= 10
mVariable = 20 val
mConstant = 10
Swift:var mVariable
= 10
mVariable = 20 let mConstant
= 10 感觉Swift和Kotlin比Java简洁,Kotlin和swift很像。 3.强制类型转换

Swift: let label = "Hello world
" let width = 80 let widthLabel = label +
String(width)
Kotlin: val label = "Hello world
" val width = 80 val widthLabel =label +
width 4数组

Swift : var tempList =
["one", "two","three"]
tempList[1] = "zero"
Kotlin : val tempList =
arrayOf("one", "two","three")
tempList[1] = "zero" 5.函数

Swift :func greet(_
name: String,_day: String) -> String { return"Hello\(name),today is
\(day)." }
greet("Bob", "Tuesday")
Kotlin : fun
greet(name: String, day: String): String { return"Hello$name, today is
$day."}
greet("Bob", "Tuesday") 6.类声明及用法

Swift: 声明:classShape { var
numberOfSides = 0
func simpleDescription() -> String
{ return"A shapewith
\(numberOfSides) sides."
}
} 用法:varshape =
Shape()
shape.numberOfSides = 7 var
shapeDescription =shape.simpleDescription() Kotlin : 声明:classShape { var
numberOfSides = 0 fun
simpleDescription() = "A shapewith
$numberOfSides sides."
} 用法:var shape =
Shape()
shape.numberOfSides = 7 var
shapeDescription= shape.simpleDescription() 可见,Kotlin和Swift好像,现代语言的特征,比java这样的高级语言更加简化,更贴近自然语言

3.开发环境

本文使用的是android
studio2.0版本,启动androd
studio。
如下图在configure下拉菜单中选择plugins,在搜索框中搜索Kotlin,找到结果列表中的”Kotlin”插件。


如下图,找了一张还没有安装kotlin插件的图

点击右侧intall,安装后重启studio.

4.新建android项目

你可以像以前使用android
stuio一样新建一个andoid项目,建立一个activity。本文用已经完成的一个demo来做示范。如下图是一个stuio的demo工程


选择MainActivity和MessageConst两个java文件,然后选择导航栏上的code,在下拉菜单中选择convert Java file
to kotlin file

系统会自动进行转化,转化完后会生成对应的MainActivity.kt
MessageConst.kt文件,打开MainActivity.kt,编译器上方会提示”Kotlin
not configured”,点击一下Configure按钮,IDE就会自动帮我们配置好了!将两个kt文件复制到src/kotlin目录下,如下图

转化后的文件,也许有些语法错误,需要按照kotlin的语法修改。环境配置好后,来看下gradle更新有哪些区别project的gradle代码如下: buildscript
{ ext.kotlin_version
= '1.1.3-2' repositories
{
jcenter() } dependencies
{
classpath 'com.android.tools.build:gradle:2.0.0' //此处多了kotlin插件依赖
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" }} allprojects
{ repositories
{
jcenter() }} 再来看看某个module的gradle代码: apply
plugin: 'com.android.application'apply
plugin: 'kotlin-android'//此处多了这条插件声明 android {
compileSdkVersion 14
buildToolsVersion "24.0.0" defaultConfig
{
applicationId "com.olami"
minSdkVersion 8
targetSdkVersion 14 } buildTypes
{ release
{
minifyEnabled false
proguardFilesgetDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } sourceSets
{
main.java.srcDirs += 'src/main/kotlin'//生成的***.kt文件需要copy到对应的目录 }} dependencies
{
compile 'com.android.support:support-v4:18.0.0' compile
files('libs/voicesdk_android.jar')
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"//此处多了kotlin包的依赖}repositories
{
mavenCentral()} 如上所示,如果不是通过转化的方式新建kotlin工程,则需要自己按照上面的gradle中增加的部分配置好。

5.olami语音识别应用

先贴一张识别后的效果图:

在MainActivity.kt中 override
funonCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initHandler()//初始化handler用于处理消息
initView()//初始化view控件,比如点击开始录音的button
initViaVoiceRecognizerListener()//初始化语音识别回调,用于返回录音状态和识别结果
init()//初始化语音识别对象} fun init(){
initHandler() //定义olami语音识别对象
mOlamiVoiceRecognizer =OlamiVoiceRecognizer(this@MainActivity) val telephonyManager
= this.getSystemService( Context.TELEPHONY_SERVICE)
as TelephonyManager val imei =
telephonyManager.deviceId
mOlamiVoiceRecognizer!!.init(imei) //set null if you do not
want to notifyolami server. //设置回调,用于更新录音状态和数据等的界面 mOlamiVoiceRecognizer!!.setListener(mOlamiVoiceRecognizerListener) //设置支持的语言类型,默认请设置简体中文 mOlamiVoiceRecognizer!!.setLocalization(
OlamiVoiceRecognizer.LANGUAGE_SIMPLIFIED_CHINESE) mOlamiVoiceRecognizer!!.setAuthorization("51a4bb56ba954655a4fc834bfdc46af1", "asr", "68bff251789b426896e70e888f919a6d", "nli") //注册Appkey,在olami官网注册应用后生成的appkey //注册api,请直接填写“asr”,标识语音识别类型 //注册secret,在olami官网注册应用后生成的secret mOlamiVoiceRecognizer!!.setVADTailTimeout(2000) //录音时尾音结束时间,建议填//2000ms mOlamiVoiceRecognizer!!.setLatitudeAndLongitude( 31.155364678184498, 121.34882432933009) //设置经纬度信息,不愿上传位置信息,可以填0 } 代码比较简单,点击开始录音button后,启动录音,在OlamiVoiceRecognizerListener中回调处理,然后通过handler发送消息用于更新界面。来看一下初始化view的代码,看看跟java方式书写有哪些不同 private fun
initView(){ mBtnStart =
findViewById(R.id.btn_start)
asButton mBtnStop =
findViewById(R.id.btn_stop) as
Button mBtnCancel =
findViewById(R.id.btn_cancel)
asButton mBtnSend =
findViewById(R.id.btn_send) as
Button mInputTextView
= findViewById(R.id.tv_inputText)
asTextView mEditText =
findViewById(R.id.et_content)
asEditText mTextView =
findViewById(R.id.tv_result)
asTextView mTextViewVolume
= findViewById(R.id.tv_volume)
asTextView
mBtnStart!!.setOnClickListener { if
(mOlamiVoiceRecognizer != null)
mOlamiVoiceRecognizer!!.start() }
mBtnStop!!.setOnClickListener { if
(mOlamiVoiceRecognizer != null)
mOlamiVoiceRecognizer!!.stop()
mBtnStart!!.text = "开始"
Log.i("led", "MusicActivity mBtnStop
onclick 开始") }
mBtnCancel!!.setOnClickListener { if
(mOlamiVoiceRecognizer != null)
mOlamiVoiceRecognizer!!.cancel() }
mBtnSend!!.setOnClickListener { if
(mOlamiVoiceRecognizer != null)
mOlamiVoiceRecognizer!!.sendText(mEditText!!.text.toString())
mInputTextView!!.text = "输入: " +
mEditText!!.text } } 是不是感觉代码更简练了?
下面两句赋值,效果相同,第二句可以用id之间进行文本赋值,比以前简练好多。mInputTextView!!.text = "输入: " +
mEditText!!.texttv_inputText.text ="输入: " +
et_content.text 再来看看handler:private
funinitHandler() { mHandler =
object : Handler() { override
fun handleMessage(msg:Message) { when
(msg.what) {
MessageConst.CLIENT_ACTION_START_RECORED->
mBtnStart!!.text = "录音中"
MessageConst.CLIENT_ACTION_STOP_RECORED
-> mBtnStart!!.text = "识别中"
MessageConst.CLIENT_ACTION_CANCEL_RECORED->
{
mBtnStart!!.text = "开始"
mTextView!!.text = "已取消"
}
MessageConst.CLIENT_ACTION_ON_ERROR->
{
mTextView!!.text = "错误代码:" + msg.arg1
mBtnStart!!.text = "开始"
}
MessageConst.CLIENT_ACTION_UPDATA_VOLUME->
mTextViewVolume!!.text = "音量: " + msg.arg1
MessageConst.SERVER_ACTION_RETURN_RESULT->
{
if (msg.obj != null)
mTextView!!.text = "服务器返回: " + msg.obj.toString()
mBtnStart!!.text = "开始"
try {
val message = msg.obj as String
var input: String?= null
val jsonObject =JSONObject(message)
val jArrayNli =
jsonObject.optJSONObject("data").optJSONArray("nli")
val jObj =jArrayNli.optJSONObject(0)
var jArraySemantic:JSONArray? = null
if (message.contains("semantic")) {
jArraySemantic= jObj.getJSONArray("semantic")
input = jArraySemantic!!.optJSONObject(0).optString("input")
} else {
input = jsonObject.optJSONObject("data") .optJSONObject("asr").optString("result")
}
if (input != null) mInputTextView!!.text ="输入: " + input
} catch (e: Exception) {
e.printStackTrace()
}
}
}
} } } 原来的switch
case的方式,变成了when***,代码不仅简练,更贴近现代语言,更容易理解。上面的MessageConst.SERVER_ACTION_RETURN_RESULT时,获取了服务器返回的结果,紧接着对这段语义进行了简单的解析 { "data":
{ "asr":
{
"result": "我要听三国演义",
"speech_status": 0,
"final": true,
"status": 0 }, "nli":
[
{
"desc_obj": {
"result": "正在努力搜索中,请稍等",
"status": 0
},
"semantic": [
{
"app": "musiccontrol",
"input": "我要听三国演义",
"slots": [
{ "name": "songname", "value": "三国演义"
}
],
"modifier": [ "play"
],
"customer": "58df512384ae11f0bb7b487e"
}
],
"type": "musiccontrol"
} ] },
"status": "ok"} 1)解析出nli中type类型是musiccontrol,这是语法返回app的类型,而这个在线听书的demo只关心musiccontrol这个app类型,其他的忽略。2)用户说的话转成文字是在asr中的result中获取
3)在nli中的semantic中,input值是用户说的话,同asr中的result。
modifier代表返回的行为动作,此处可以看到是play就是要求播放,slots中的数据表示歌曲名称是三国演义。
那么动作是play,内容是歌曲名称是三国演义,在这个demo中调用
mBookUtil.searchBookAndPlay(songName,0,0);会先查询,查询到结果会再发播放消息要求播放,我要听三国演义这个流程就走完了。这段是在线听书应用中的语义解析,详情请看博客:http://blog.csdn.net/ls0609/article/details/71519203

6.代码下载

用Koltlin实现android平台语音识别语义理解

7.相关博客

语音在线听书博客:http://blog.csdn.net/ls0609/article/details/71519203语音记账demo:http://blog.csdn.net/ls0609/article/details/72765789基于JavaScript用olamisdk实现web端语音识别语义理解(speex压缩)http://blog.csdn.net/ls0609/article/details/73920229olami开放平台语法编写简介:http://blog.csdn.net/ls0609/article/details/71624340olami开放平台语法官方介绍:https://cn.olami.ai/wiki/?mp=nli&content=nli2.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息