BaiduSpeechDemo【百度語音SDK集成】(基於v3.0.8.1)

版權聲明:本文爲HaiyuKing原創文章,轉載請註明出處!html

前言

上一篇集成的是V3.0.7.3版本的SDK《BaiduSpeechDemo【百度語音SDK集成】(基於v3.0.7.3)》,此次發現官網的SDK進行了升級,感受有必要進行從新集成。java

一、修復了APP同時集成多個SDK,不能同時使用的問題;——因此須要使用新sdk的jar文件;react

二、既然官網也使用了module方式;——那麼就不須要本身建立module了,直接在官網的core這個module中優化;android

三、修復長語音無結束回調;——增長長語音結束回調的監聽;git

本Demo中使用的appkey已失效,請自行建立應用,使用新的appkey。github

效果圖

和《BaiduSpeechDemo【百度語音SDK集成】(基於v3.0.7.3)》相似,這裏就不單獨截圖了。json

代碼分析

普通話 search搜索模型:參考SpeechBottomSheetDialog.java類app

普通話 input輸入法模型,適用於長句及長語音,有逗號分割,無語義:參考SpeechLongBottomSheetDialog.java類ide

注意:關於語音識別狀態維護,API調用的代碼,是本身根據官網demo的理解進行整理的,可能有所偏頗,僅供參考。【但願官網demo能夠添加百度APP的語音對話框效果就行了】佈局

使用步驟

1、項目組織結構圖

注意事項:

一、  導入類文件後須要change包名以及從新import R文件路徑

二、  Values目錄下的文件(strings.xml、dimens.xml、colors.xml等),若是項目中存在,則複製裏面的內容,不要整個覆蓋

2、導入步驟

(1)在項目中導入官網demo中的core這個module,同時修更名稱,修改成baiduspeech

(2)修改baiduspeech的AndroidManifest.xml(修改官網申請的應用信息)

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="test2.baidu.com.baseasr">
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application>
        <meta-data
                android:name="com.baidu.speech.APP_ID"
                android:value="11588936"/>
        <meta-data
                android:name="com.baidu.speech.API_KEY"
                android:value="XRF3IOf2tNGePzlv47cBnvF3"/>
        <meta-data
                android:name="com.baidu.speech.SECRET_KEY"
                android:value="diC8lQ7XDcGBKQ6FzCpvnan54F5CnMZI"/>
    </application>
</manifest>

(3)修改MessageStatusRecogListener.java文件【根據實際狀況進行修改】

package com.baidu.aip.asrwakeup3.core.recog.listener;

import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.baidu.aip.asrwakeup3.core.recog.RecogResult;
import com.baidu.speech.asr.SpeechConstant;

/**
 * Created by fujiayi on 2017/6/16.
 */

public class MessageStatusRecogListener extends StatusRecogListener {
    private Handler handler;

    private long speechEndTime = 0;

    private boolean needTime = true;

    private static final String TAG = "MesStatusRecogListener";

    public MessageStatusRecogListener(Handler handler) {
        this.handler = handler;
    }


    @Override
    public void onAsrReady() {
        super.onAsrReady();
        speechEndTime = 0;
        sendStatusMessage(SpeechConstant.CALLBACK_EVENT_WAKEUP_READY, "引擎就緒,能夠開始說話。");
    }

    @Override
    public void onAsrBegin() {
        super.onAsrBegin();
        sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_BEGIN, "檢測到用戶說話");
    }

    @Override
    public void onAsrEnd() {
        super.onAsrEnd();
        speechEndTime = System.currentTimeMillis();
        sendMessage("【asr.end事件】檢測到用戶說話結束");
    }

    @Override
    public void onAsrPartialResult(String[] results, RecogResult recogResult) {
        sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL,
                "臨時識別結果,結果是「" + results[0] + "」;原始json:" + recogResult.getOrigalJson());
        super.onAsrPartialResult(results, recogResult);
    }

    @Override
    public void onAsrFinalResult(String[] results, RecogResult recogResult) {
        super.onAsrFinalResult(results, recogResult);
        //String message = "識別結束,結果是」" + results[0] + "」";//why 實際中能夠去掉,不須要
        String message = recogResult.getOrigalJson();//{"results_recognition":["什麼什麼"],"origin_result":{"corpus_no":6522034498058113957,"err_no":0,"result":{"word":["什麼什麼"]},"sn":"bfa8b286-ab0e-4f86-9209-1d36d38b1224","voice_energy":16191.7705078125},"error":0,"best_result":"什麼什麼","result_type":"final_result"}
        sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL,
                message + ";原始json:" + recogResult.getOrigalJson());
        if (speechEndTime > 0) {
            long currentTime = System.currentTimeMillis();
            long diffTime = currentTime - speechEndTime;
            //message += ";說話結束到識別結束耗時【" + diffTime + "ms】";// why 實際中能夠去掉,不須要

        }
        speechEndTime = 0;
        sendMessage(message, status, true);
    }

    @Override
    public void onAsrFinishError(int errorCode, int subErrorCode, String descMessage,
                                 RecogResult recogResult) {
        super.onAsrFinishError(errorCode, subErrorCode, descMessage, recogResult);
        //String message = "識別錯誤, 錯誤碼:" + errorCode + " ," + subErrorCode + " ; " + descMessage;// why 實際中能夠去掉,不須要
        String message = recogResult.getOrigalJson();//{"origin_result":{"sn":"","error":7,"desc":"No recognition result match","sub_error":7001},"error":7,"desc":"No recognition result match","sub_error":7001}
        sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL, message);
        if (speechEndTime > 0) {
            long diffTime = System.currentTimeMillis() - speechEndTime;
            //message += "。說話結束到識別結束耗時【" + diffTime + "ms】";// why實際中能夠去掉,不須要
        }
        speechEndTime = 0;
        sendMessage(message, status, true);
        speechEndTime = 0;
    }

    @Override
    public void onAsrOnlineNluResult(String nluResult) {
        super.onAsrOnlineNluResult(nluResult);
        if (!nluResult.isEmpty()) {
            sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL, "原始語義識別結果json:" + nluResult);
        }
    }

    @Override
    public void onAsrFinish(RecogResult recogResult) {
        super.onAsrFinish(recogResult);
        sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_FINISH, "識別一段話結束。若是是長語音的狀況會繼續識別下段話。");

    }

    /**
     * 長語音識別結束
     */
    @Override
    public void onAsrLongFinish() {
        super.onAsrLongFinish();
        sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_LONG_SPEECH, "長語音識別結束。");
    }


    /**
     * 使用離線命令詞時,有該回調說明離線語法資源加載成功
     */
    @Override
    public void onOfflineLoaded() {
        sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_LOADED, "離線資源加載成功。沒有此回調可能離線語法功能不能使用。");
    }

    /**
     * 使用離線命令詞時,有該回調說明離線語法資源加載成功
     */
    @Override
    public void onOfflineUnLoaded() {
        sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_UNLOADED, "離線資源卸載成功。");
    }

    @Override
    public void onAsrExit() {
        super.onAsrExit();
        sendStatusMessage(SpeechConstant.CALLBACK_EVENT_ASR_EXIT, "識別引擎結束並空閒中");
    }

    private void sendStatusMessage(String eventName, String message) {
        message = "[" + eventName + "]" + message;
        sendMessage(message, status);
    }

    private void sendMessage(String message) {
        sendMessage(message, WHAT_MESSAGE_STATUS);
    }

    private void sendMessage(String message, int what) {
        sendMessage(message, what, false);
    }


    private void sendMessage(String message, int what, boolean highlight) {


        if (needTime && what != STATUS_FINISHED) {
            message += "  ;time=" + System.currentTimeMillis();
        }
        if (handler == null) {
            Log.i(TAG, message);
            return;
        }
        Message msg = Message.obtain();
        msg.what = what;
        msg.arg1 = status;
        if (highlight) {
            msg.arg2 = 1;
        }
        msg.obj = message + "\n";
        handler.sendMessage(msg);
    }
}

至此,百度語音SDK集成到baiduspeech中了,下一步就是建立UI對話框(建議再單首創建一個新的module)。

(4)新建baiduspeechdialog這個module

一、在baiduspeechdialog的build.gradle中引用recyclerview【版本號和項目的appcompat保持一致】【由於demo中用到了】【注意:還須要導入baiduspeech這個module

apply plugin: 'com.android.library'

android {
    compileSdkVersion 27



    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:27.1.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    //RecyclerView compile 'com.android.support:recyclerview-v7:27.1.1' //baiduspeech implementation project(':baiduspeech')
}

二、對話框類、列表適配器類、佈局文件xml文件、圖片資源、動畫style樣式等複製到baiduspeechdialog中【參考《BaiduSpeechDemo【百度語音SDK集成】(基於v3.0.7.3)》】

三、SpeechBottomSheetDialog.java和SpeechLongBottomSheetDialog.java在V3.0.7.3版本和V3.0.8.1版本的區別

3.一、須要將Logger修改成MyLogger

修改成:

3、使用方法

(1)由於須要使用到運行時權限,因此參考《Android6.0運行時權限(基於RxPermission開源庫)》在APP的build.gradle中引入第三方庫

(2)在APP的build.gradle中引入baiduspeechdialog

 

(3)在Activity中調用

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.why.project.baiduspeechdemo.MainActivity">

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.448"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.325"/>

    <Button
        android:id="@+id/btn_openSpeechDialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="32dp"
        android:text="打開搜索模型語音識別對話框"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.419"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/btn_openSpeechLongDialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:text="打開input輸入模型語音識別對話框"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.4"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_openSpeechDialog"/>

</android.support.constraint.ConstraintLayout>
activity_main.xml

 

package com.why.project.baiduspeechdemo;

import android.Manifest;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.tbruyelle.rxpermissions2.RxPermissions;
import com.why.project.baiduspeechdialog.dialog.SpeechBottomSheetDialog;
import com.why.project.baiduspeechdialog.dialog.SpeechLongBottomSheetDialog;

import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();

    private Button mOpenSpeechDialogBtn;
    private Button mOpenSpeechLongDialogBtn;
    private TextView mResultTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        onePermission();

        initViews();
        initEvents();
    }

    private void initViews() {
        mOpenSpeechDialogBtn = findViewById(R.id.btn_openSpeechDialog);
        mOpenSpeechLongDialogBtn = findViewById(R.id.btn_openSpeechLongDialog);
        mResultTv = findViewById(R.id.tv_result);
    }

    private void initEvents() {
        mOpenSpeechDialogBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //打開百度語音對話框
                SpeechBottomSheetDialog speechBottomSheetDialog = SpeechBottomSheetDialog.getInstance(MainActivity.this); speechBottomSheetDialog.seOnResultListItemClickListener(new SpeechBottomSheetDialog.OnResultListItemClickListener() { @Override public void onItemClick(String title) { //填充到輸入框中
 mResultTv.setText(title); } }); speechBottomSheetDialog.show(getSupportFragmentManager(), TAG);
            }
        });
        mOpenSpeechLongDialogBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //打開百度語音對話框
                SpeechLongBottomSheetDialog speechLongBottomSheetDialog = SpeechLongBottomSheetDialog.getInstance(MainActivity.this); speechLongBottomSheetDialog.seOnResultListItemClickListener(new SpeechLongBottomSheetDialog.OnResultListItemClickListener() { @Override public void onItemClick(String title) { //填充到輸入框中
                        mResultTv.setText(mResultTv.getText()+title); } }); speechLongBottomSheetDialog.show(getSupportFragmentManager(), TAG);
            }
        });

    }

    /**只有一個運行時權限申請的狀況*/
    private void onePermission(){
        RxPermissions rxPermissions = new RxPermissions(MainActivity.this); // where this is an Activity instance
        rxPermissions.request(Manifest.permission.RECORD_AUDIO,
                Manifest.permission.READ_PHONE_STATE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) //權限名稱,多個權限之間逗號分隔開
                .subscribe(new Consumer<Boolean>() {
                    @Override
                    public void accept(Boolean granted) throws Exception {
                        Log.e(TAG, "{accept}granted=" + granted);//執行順序——1【多個權限的狀況,只有全部的權限均容許的狀況下granted==true】
                        if (granted) { // 在android 6.0以前會默認返回true
                            // 已經獲取權限
                        } else {
                            // 未獲取權限
                            Toast.makeText(MainActivity.this, "您沒有受權該權限,請在設置中打開受權", Toast.LENGTH_SHORT).show();
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        Log.e(TAG,"{accept}");//多是受權異常的狀況下的處理
                    }
                }, new Action() {
                    @Override
                    public void run() throws Exception {
                        Log.e(TAG,"{run}");//執行順序——2
                    }
                });
    }
}

混淆配置

#=====================百度語音混淆=====================
-keep class com.baidu.speech.**{*;}

參考資料

http://ai.baidu.com/tech/speech

項目demo下載地址

https://github.com/haiyuKing/BaiduSpeechNewDemo

相關文章
相關標籤/搜索