用Kotlin开发android平台语音识别,语义理解应用(olamisdk)
本文使用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!
- 1
- 2
- 3
- 1
- 2
- 3
- 2.變量和常量
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 3.強制類型轉換
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 4數組
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
- 5.函數
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 6.類聲明及用法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
可見,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()} }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
再來看看某個module的gradle代碼:
apply plugin: 'com.android.application' apply plugin: 'kotlin-android'//此處多了這條插件聲明android {compileSdkVersion 14buildToolsVersion "24.0.0"defaultConfig {applicationId "com.olami"minSdkVersion 8targetSdkVersion 14}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('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() }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
如上所示,如果不是通過轉化的方式新建kotlin工程,則需要自己按照上面的gradle中增加的部分配置好。
5.olami語音識別應用
先貼一張識別后的效果圖:?
在MainActivity.kt中
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)initHandler()//初始化handler用于處理消息initView()//初始化view控件,比如點擊開始錄音的buttoninitViaVoiceRecognizerListener()//初始化語音識別回調,用于返回錄音狀態和識別結果init()//初始化語音識別對象}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
代碼比較簡單,點擊開始錄音button后,啟動錄音,在OlamiVoiceRecognizerListener中回調處理,然后通過handler發送消息用于更新界面。
來看一下初始化view的代碼,看看跟java方式書寫有哪些不同
private fun initView() {mBtnStart = findViewById(R.id.btn_start) as ButtonmBtnStop = findViewById(R.id.btn_stop) as ButtonmBtnCancel = findViewById(R.id.btn_cancel) as ButtonmBtnSend = findViewById(R.id.btn_send) as ButtonmInputTextView = findViewById(R.id.tv_inputText) as TextViewmEditText = findViewById(R.id.et_content) as EditTextmTextView = findViewById(R.id.tv_result) as TextViewmTextViewVolume = findViewById(R.id.tv_volume) as TextViewmBtnStart!!.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}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
是不是感覺代碼更簡練了??
下面兩句賦值,效果相同,第二句可以用id之間進行文本賦值,比以前簡練好多。
- 1
- 2
- 1
- 2
再來看看handler:
private fun initHandler() {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.arg1mBtnStart!!.text = "開始"}MessageConst.CLIENT_ACTION_UPDATA_VOLUME -> mTextViewVolume!!.text= "音量: " + msg.arg1MessageConst.SERVER_ACTION_RETURN_RESULT -> {if (msg.obj != null)mTextView!!.text = "服務器返回: " + msg.obj.toString()mBtnStart!!.text = "開始"try {val message = msg.obj as Stringvar input: String? = nullval jsonObject = JSONObject(message)val jArrayNli = jsonObject.optJSONObject("data").optJSONArray("nli")val jObj = jArrayNli.optJSONObject(0)var jArraySemantic: JSONArray? = nullif (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()}}}}}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
原來的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
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
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/73920229
olami開放平臺語法編寫簡介:http://blog.csdn.net/ls0609/article/details/71624340
olami開放平臺語法官方介紹:https://cn.olami.ai/wiki/?mp=nli&content=nli2.html
轉載請注明CSDN博文地址:http://blog.csdn.net/ls0609/article/details/75084994
總結
以上是生活随笔為你收集整理的用Kotlin开发android平台语音识别,语义理解应用(olamisdk)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 那些年Android黑科技①:只要活着,
- 下一篇: 语音识别,语义理解一站式解决(andro