溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

用Kotlin開發(fā)android平臺語音識別語義理解應用

發(fā)布時間:2020-07-17 18:44:11 來源:網(wǎng)絡 閱讀:981 作者:ls0609 欄目:移動開發(fā)

 

 Kotlin開發(fā)android平臺語音識別,語義理解應用(olamisdk


轉(zhuǎn)載請注明CSDN博文地址:http://blog.csdn.net/ls0609/article/details/75084994

本文使用Kotlin開發(fā)Android平臺的一個語音識別方面的應用,用的是歐拉密開放平臺olamisdk

1.Kotlin簡介

Kotlin是由JetBrains創(chuàng)建的基于JVM的編程語言,IntelliJ正是JetBrains的杰作,而android Studio是
基于IntelliJ修改而來的。Kotlin是一門包含很多函數(shù)式編程思想的面向?qū)ο缶幊陶Z言。

  后來了解到Kotlin原來是以一個島的名字命名的(Котлин),它是一門靜態(tài)類型編程語言,支持JVM平臺,android平臺,瀏覽器js運行環(huán)境,本地機器碼等。支持與Java,Android 100% 完全互操作。Kotlin生來就是為了彌補Java缺失的現(xiàn)代語言的特性,并極大的簡化了代碼,使得開發(fā)者可以編寫盡量少的樣板代碼。

 

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;

        Kotlinvar mVariable = 10

                mVariable = 20

                val mConstant = 10     

        Swiftvar mVariable = 10

               mVariable = 20

               let mConstant = 10           

        感覺SwiftKotlinJava簡潔,Kotlinswift很像。

 

  • 3.強制類型轉(zhuǎn)換

      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數(shù)組

       Swift 

                var tempList = ["one""two","three"]

                tempList[1] = "zero"

        Kotlin 

               val tempList = arrayOf("one""two","three")

               tempList[1] = "zero"

 

  • 5.函數(shù)

       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()

 

可見,KotlinSwift好像,現(xiàn)代語言的特征,比java這樣的高級語言更加簡化,更貼近自然語言。

 

3.開發(fā)環(huán)境

本文使用的是android studio2.0版本,啟動androd studio。 
如下圖在configure下拉菜單中選擇plugins,在搜索框中搜索Kotlin,找到結(jié)果列表中的”Kotlin”插件。

 用Kotlin開發(fā)android平臺語音識別語義理解應用


 

如下圖,找了一張還沒有安裝kotlin插件的圖

 

用Kotlin開發(fā)android平臺語音識別語義理解應用

 

點擊右側(cè)intall,安裝后重啟studio.

 

4.新建android項目

你可以像以前使用android stuio一樣新建一個andoid項目,建立一個activity。本文用已經(jīng)完成的一個demo來做示范。

如下圖是一個stuiodemo工程 

 用Kotlin開發(fā)android平臺語音識別語義理解應用


 

選擇MainActivityMessageConst兩個java文件,然后選擇導航欄上的code,在下拉菜單中選擇convert Java file to kotlin file 

 

用Kotlin開發(fā)android平臺語音識別語義理解應用

 

系統(tǒng)會自動進行轉(zhuǎn)化,轉(zhuǎn)化完后會生成對應的MainActivity.kt MessageConst.kt文件,打開MainActivity.kt,編譯器上方會提示”Kotlin not configured”,點擊一下Configure按鈕,IDE就會自動幫我們配置好了!

將兩個kt文件復制到src/kotlin目錄下,如下圖

 

 

用Kotlin開發(fā)android平臺語音識別語義理解應用

 

轉(zhuǎn)化后的文件,也許有些語法錯誤,需要按照kotlin的語法修改。

環(huán)境配置好后,來看下gradle更新有哪些區(qū)別

projectgradle代碼如下:

 

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()

    }

}

 

再來看看某個modulegradle代碼:

 

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()

}

 

如上所示,如果不是通過轉(zhuǎn)化的方式新建kotlin工程,則需要自己按照上面的gradle中增加的部分配置好。

 

5.olami語音識別應用

先貼一張識別后的效果圖: 

 

用Kotlin開發(fā)android平臺語音識別語義理解應用

 

MainActivity.kt

 

override funonCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

 

        initHandler()//初始化handler用于處理消息

 

        initView()//初始化view控件,比如點擊開始錄音的button

 

        initViaVoiceRecognizerListener()//初始化語音識別回調(diào),用于返回錄音狀態(tài)和識別結(jié)果

 

        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.

 

        //設置回調(diào),用于更新錄音狀態(tài)和數(shù)據(jù)等的界面

       mOlamiVoiceRecognizer!!.setListener(mOlamiVoiceRecognizerListener)

 

        //設置支持的語言類型,默認請設置簡體中文

       mOlamiVoiceRecognizer!!.setLocalization(

                                 OlamiVoiceRecognizer.LANGUAGE_SIMPLIFIED_CHINESE)

       mOlamiVoiceRecognizer!!.setAuthorization("51a4bb56ba954655a4fc834bfdc46af1",  

                                   "asr""68bff251789b426896e70e888f919a6d""nli")

 

        //注冊Appkey,在olami官網(wǎng)注冊應用后生成的appkey

        //注冊api,請直接填寫“asr”,標識語音識別類型

        //注冊secret,在olami官網(wǎng)注冊應用后生成的secret

 

       mOlamiVoiceRecognizer!!.setVADTailTimeout(2000)

        //錄音時尾音結(jié)束時間,建議填//2000ms

 

       mOlamiVoiceRecognizer!!.setLatitudeAndLongitude(

                                             31.155364678184498121.34882432933009)

        //設置經(jīng)緯度信息,不愿上傳位置信息,可以填0

 }

 

代碼比較簡單,點擊開始錄音button后,啟動錄音,在OlamiVoiceRecognizerListener中回調(diào)處理,然后通過handler發(fā)送消息用于更新界面。

來看一下初始化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!!.text

tv_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***,代碼不僅簡練,更貼近現(xiàn)代語言,更容易理解。

上面的MessageConst.SERVER_ACTION_RETURN_RESULT時,獲取了服務器返回的結(jié)果,緊接著對這段語義進行了簡單的解析

 

 

{

    "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)解析出nlitype類型是musiccontrol,這是語法返回app的類型,而這個在線聽書的demo只關(guān)心musiccontrolapp類型,其他的忽略。

2)用戶說的話轉(zhuǎn)成文字是在asr中的result中獲取 
3
)在nli中的semantic中,input值是用戶說的話,同asr中的result。 
modifier
代表返回的行為動作,此處可以看到是play就是要求播放,slots中的數(shù)據(jù)表示歌曲名稱是三國演義。 
那么動作是play,內(nèi)容是歌曲名稱是三國演義,在這個demo中調(diào)用 
mBookUtil.searchBookAndPlay(songName,0,0);
會先查詢,查詢到結(jié)果會再發(fā)播放消息要求播放,我要聽三國演義這個流程就走完了。

這段是在線聽書應用中的語義解析,詳情請看博客:http://blog.csdn.net/ls0609/article/details/71519203

 

6.代碼下載

Koltlin實現(xiàn)android平臺語音識別語義理解

 

7.相關(guān)博客

語音在線聽書博客:http://blog.csdn.net/ls0609/article/details/71519203

語音記賬demohttp://blog.csdn.net/ls0609/article/details/72765789

基于JavaScriptolamisdk實現(xiàn)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

 




向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI