跳转至

语音识别Android SDK文档

文档修订记录

文档版本号 修订日期 修订原因
V1.0 2022.8.30 创建文档
V1.1 2023.10.18 优化文档
V1.2 2024.05.06 优化文档

概述

ASR模块主要是语音转文字的过程,支持的交互场景包括单句识别连续识别,支持的开启方式开启录音器输入音频数据流

集成步骤

1. 添加依赖库

//必须依赖库
implementation 'com.google.code.gson:gson:2.6.2'
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
implementation "org.java-websocket:Java-WebSocket:1.4.0"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.aliyun.dpa:oss-android-sdk:2.9.11'//SDKV2.4.1.25 以后需加入
//vad所需
implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.15.1'

2. 权限声明

网络权限 - 使用过程中,会有https与wss请求、网络状态检测

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> 

存储权限 - 使用过程中,会写入日志文件、保存临时音频文件(debug),请在清单中指定以下内容。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />   
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- android10 以上需要额外添加-->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

在android10及以上需要在application标签下添加如下配置

android:requestLegacyExternalStorage="true"

音频录制权限 - 在使用过程中录制音频,您的应用必须请求音频捕获权限。

<uses-permission android:name="android.permission.RECORD_AUDIO" />  

3. 配置文件

将turing_config.json配置文件放在main/assets文件夹下

{
  "authorization": {
    "apikey": "您的apikey",
    "secret": "您的secret"
  },
  "ability": {
    "asr": {
      "asrSrcFormatEnum": 0,
      "asrFormatEnum": 0,
      "asrLanguageEnum": 0,
      "asrRateEnum": 16000,
      "channel": 1,
      "enableITN": true,
      "enablePunctuation": false,
      "enableVoiceDetection": true,
      "intermediateResult": true,
      "maxEndSilence": 1000,
      "maxStartSilence": 5000,
      "vadThreshold": 0.5,
      "vadReviseTime": 1200,
      "vadState": true,
      "interactionTime": 20,
      "enableCloudVad": false,
      "enableVolume": false,
      "audioSource": 1,
      "saveAudioPath": ""
    }
  }
}

参数说明见文档末端《参数说明》#输入参数

4. 代码混淆

代码混淆文件proguard-project.txt,添加如下内容

    -keep class com.turing.**{ *;}
    -dontwarn com.turing.**

    -keep class com.tuling.**{ *;}
    -dontwarn com.tuling.**

    -keep class org.java_websocket.**{*;}
    -dontwarn org.java_websocket.**
    -keep class org.slf4j.**{*;}
    -dontwarn org.slf4j.**

    -keep class org.eclipse.** { *; }
    -dontwarn org.eclipse.**

5. SDK 初始化

使用任何能力前调用,请先调用SDK初始化代码。(SDK初始化详情见《接入指南说明文档》)

TuringInitializer.getInstance().initV3XXX()

6. 实例化

var turingAsr = TuringAsr.getInstance(this)

接口说明

public interface TuringAsrInterface {
    /**
     * 录音并识别ASR,使用全局配置文件Turing_config.json中的参数,需配置asr参数
     * @param isLoop 是否循环录音识别
     * @param isAssignAsr 是否使用配置文件中的asr参数
     * @param listener 回调接口
     */
    void startAsrWithRecorder(boolean isLoop, boolean isAssignAsr,TuringOSClientAsrListener listener);
    /**
     * 录音并识别ASR
     * @param isLoop 是否循环录音识别
     * @param asrRequestConfig asr请求参数,如设置为空,则使用Turing_config.json中的asr配置,如没有asr配置,则使用默认值
     * @param listener 回调接口
     */
    void startAsrWithRecorder(boolean isLoop, AsrRequestConfig asrRequestConfig, TuringOSClientAsrListener listener);

    /**
     * 初始化音频流识别,使用全局配置文件Turing_config.json中的参数,需配置asr参数
     * @param isAssignAsr 是否使用配置文件中的asr参数
     * @param listener 回调接口
     */
    public void initAsrStream(boolean isAssignAsr, final TuringOSClientAsrListener listener);
    /**
     * 初始化音频流识别
     * @param asrRequestConfig asr请求参数,如设置null,则使用Turing_config.json中的asr配置,如没有asr配置,则使用默认值
     * @param listener 回调接口
     */
    public void initAsrStream(AsrRequestConfig asrRequestConfig, final TuringOSClientAsrListener listener);

    /**
     * 初始化音频流识别
     * @param isAutoStop 是否自动停止,为false时,和上面没有isAutoStop一样,当为true时,输入的音频数据在识别到完整的结果后会自动丢弃剩余数据
     * @param isAssignAsr 是否使用配置文件中的asr参数
     * @param listener 回调接口
     */
    public void initAsrStream(boolean isAutoStop, boolean isAssignAsr, final TuringOSClientAsrListener listener);
    /**
     * 初始化音频流识别
     * @param isAutoStop 是否自动停止,为false时,和上面没有isAutoStop一样,当为true时,输入的音频数据在识别到完整的结果后会自动丢弃剩余数据
     * @param asrRequestConfig asr请求参数,如设置null,则使用Turing_config.json中的asr配置,如没有asr配置,则使用默认值
     * @param listener 回调接口
     */
    public void initAsrStream(boolean isAutoStop,AsrRequestConfig asrRequestConfig, final TuringOSClientAsrListener listener);

    /**
     * 发送音频流
     * @param dataBuffer 音频数据,建议单包长度为1280个byte,小于6400个byte
     * @param length 音频数据长度
     */
    public void sendAudio(byte[] dataBuffer, int length);

    /**
     * 停止录音
     * 该方法会将音频数据池中的数据发送完毕后正常结束Asr引擎
     */
    public void stop();

    /**
     * 重置vad
     * 如需修改vad参数,可先设置asr参数后,再调用此接口
     */
    void resetVad();
    /**
     * 释放ASR
     * 该方法会强制停止释放Asr引擎
     */
    void release();
}

接口类型:

  • 类型一:全局使用turing_config中的配置参数,需要在 turing_config.json 中添加 asr 节点,节点字段见《接入指南说明文档》配置文件参数说明。可使用TuringConfig.setConfigData设置全局配置参数,此参数在使用到配置文件的接口全局生效,适用于不频繁修改参数场景
  • 类型二:不使用 turing_config.json 中的配置,使用入参带AsrRequestConfig 的接口,此参数仅调用时生效,适用于频繁修改参数场景。

使用说明

功能描述

  • ASR模块支持SDK内部录音器或者输入音频字节流数据
  • ASR模块支持单句识别与多句识别

支持的所有方式:

使用内置录音:打开SDK录音器识别,返回ASR结果

使用外置录音:初始化ASR后,应用端实现录音功能,给图灵SDK输入音频字节流数据,返回ASR结果

ASR功能使用

接口类型

  • 类型一:全局使用turing_config中的配置参数,需要在 turing_config.json 中添加asr 节点,节点字段见《接入指南说明文档》配置文件参数说明。可使用TuringConfig.setConfigData设置全局配置参数,此参数在使用到配置文件的接口全局生效,适用于不频繁修改参数场景
  • 类型二:不使用 turing_config.json 中的配置,使用入参带AsrRequestConfig 的接口,此参数仅调用时生效,适用于频繁修改参数场景。

对象实例化

val turingAsr:TuringAsrInterface = TuringAsr.getInstance(this)

一、使用内置录音

方法一:使用全局配置文件Turing_config.json中的参数,需配置asr参数

//动态配置参数
TuringConfig.getInstance(this).configData.ability.asr.asrFormatEnum = type
TuringConfig.getInstance(this).configData.ability.asr.asrSrcFormatEnum = type
turingAsr.startAsrWithRecorder(
            true,
            true,
            object : TuringOSClientAsrListener {
                override fun onRecorderStart() {
                    Log.i(TAG, " =========onRecorderStart=====")
                    mUIHandler.postRunnable(Runnable { updateUI(MODE_RECORD) })
                }

                override fun onStop() {
                    Log.i(TAG, " =========onStop=====")
                    mUIHandler.postRunnable(Runnable { updateUI(MODE_NONE) })
                }

                override fun onStreamOpen() {
                    //打开内部录音的方式,该方法不会回调
                }

                override fun onResult(
                    code: Int,
                    result: String?,
                    isLast: Boolean,
                    responBean: BaseResp?
                ) {
                    Log.i(TAG, " =========onResult=====")
                    if (TextUtils.isEmpty(result))
                        return
                    mUIHandler.postRunnable(Runnable { updateResult(code, result!!, responBean) })
                }

                override fun onTimer(second: Int) {}
                override fun onError(code: Int, msg: String) {
                    Log.e(TAG, "onError  code: $code  msg:$msg")
                    mUIHandler.postRunnable(Runnable {
                        updateResult(code, msg, null)
                        updateUI(MODE_NONE)
                    })
                }

                override fun onVoiceVolume(i: Int) {
                    Log.i(TAG, "onVoiceVolume  volume: $i")
                }
            })

方法二:使用局部生效参数,可以指定AsrRequestConfig

//设置单声道,16k采样率
val asrConfig = AsrRequestConfig.Builder().channel(AsrRequestConfig.CHANNEL_IN_MONO)
    .asrRateEnum(AsrRequestConfig.RATE_16000).build()
turingAsr.startAsrWithRecorder(false,asrConfig,object : TuringOSClientAsrListener {
                override fun onRecorderStart() {
                    Log.i(TAG, " =========onRecorderStart=====")
                    mUIHandler.postRunnable(Runnable { updateUI(MODE_RECORD) })
                }

                override fun onStop() {
                    Log.i(TAG, " =========onStop=====")
                    mUIHandler.postRunnable(Runnable { updateUI(MODE_NONE) })
                }

                override fun onStreamOpen() {
                    //打开内部录音的方式,该方法不会回调
                }

                override fun onResult(
                    code: Int,
                    result: String?,
                    isLast: Boolean,
                    responBean: BaseResp?
                ) {
                    Log.i(TAG, " =========onResult=====")
                    if (TextUtils.isEmpty(result))
                        return
                    mUIHandler.postRunnable(Runnable { updateResult(code, result!!, responBean) })
                }

                override fun onTimer(second: Int) {}
                override fun onError(code: Int, msg: String) {
                    Log.e(TAG, "onError  code: $code  msg:$msg")
                    mUIHandler.postRunnable(Runnable {
                        updateResult(code, msg, null)
                        updateUI(MODE_NONE)
                    })
                }

                override fun onVoiceVolume(i: Int) {
                    Log.i(TAG, "onVoiceVolume  volume: $i")
                }
            })

二、使用外置录音

第一步:先调用初始化方法

初始化方法一:使用全局配置文件Turing_config.json中的参数,需配置asr参数

turingAsr.initAsrStream(false, true, object : TuringOSClientAsrListener {
    override fun onRecorderStart() {
        //流式输入该方法不会回调
    }

    override fun onStop() {
        Log.i(TAG, "===========onStop========")
        mUIHandler.postRunnable(Runnable { updateUI(MODE_NONE) })
    }

    override fun onStreamOpen() {
        //todo 开始输入音频数据流
        Log.i(TAG, "===========onStreamOpen========")
        startStreamEncodeInput()
    }

    override fun onResult(
        code: Int,
        result: String?,
        isLast: Boolean,
        baseResp: BaseResp?
    ) {
        Log.i(TAG, "===========onResult========")
        if (TextUtils.isEmpty(result))
            return
        mUIHandler.postRunnable(Runnable { updateResult(code, result!!, baseResp) })
    }

    override fun onTimer(second: Int) {}
    override fun onError(code: Int, msg: String) {
        Log.e(TAG, "onError  code: $code  msg:$msg")
        mUIHandler.postRunnable(Runnable {
            updateResult(code, msg, null)
            updateUI(MODE_NONE)
        })
    }

    override fun onVoiceVolume(i: Int) {}
})

初始化方法二:使用局部生效参数,可以指定AsrRequestConfig。

//设置单声道,16k采样率
val asrConfig = AsrRequestConfig.Builder().channel(AsrRequestConfig.CHANNEL_IN_MONO)
    .asrRateEnum(AsrRequestConfig.RATE_16000).build()
turingAsr.initAsrStream(false,asrConfig,object : TuringOSClientAsrListener {
    override fun onRecorderStart() {
        //流式输入该方法不会回调
    }

    override fun onStop() {
        Log.i(TAG, "===========onStop========")
        mUIHandler.postRunnable(Runnable { updateUI(MODE_NONE) })
    }

    override fun onStreamOpen() {
        //todo 开始输入音频数据流
        Log.i(TAG, "===========onStreamOpen========")
        startStreamEncodeInput()
    }

    override fun onResult(
        code: Int,
        result: String?,
        isLast: Boolean,
        baseResp: BaseResp?
    ) {
        Log.i(TAG, "===========onResult========")
        if (TextUtils.isEmpty(result))
            return
        mUIHandler.postRunnable(Runnable { updateResult(code, result!!, baseResp) })
    }

    override fun onTimer(second: Int) {}
    override fun onError(code: Int, msg: String) {
        Log.e(TAG, "onError  code: $code  msg:$msg")
        mUIHandler.postRunnable(Runnable {
            updateResult(code, msg, null)
            updateUI(MODE_NONE)
        })
    }

    override fun onVoiceVolume(i: Int) {}
})

第二步:调用发送音频的方法

//伪代码,自行实现录音,并传入音频数据
private fun startStreamEncodeInput() {
    turingAsr.sendAudio(buffer, length)
}

第三步:结束录音,返回ASR结果

正常返回此次结果。如果没有使用vad,或者需要提前结束录音,可以调用此方法结束录音;如果使用了vad,则可不调此方法

turingAsr.stop()

VAD说明

概述:语音活性检测 (Voice activity detection,VAD),是一项用于语音处理的技术,目的是检测语音信号是否存在。

VAD可用于主动结束录音,支持离线VAD和云端VAD,离线VAD支持设置前端静音超时、后端静音超时,推荐使用离线VAD

使用离线vad:

设置enableVoiceDetection=true,enableCloudVad=false

使用云端vad:

设置enableVoiceDetection=false,enableCloudVad=false

修改VAD参数

若在不同场景下,想要修改vad的参数,可先调用resetVad()方法,再重新设置vad参数,如下:

turingAsr.resetVad()
val asrConfig = AsrRequestConfig.Builder().maxStartSilence(4000).maxEndSilence(1000).vadThreshold(0.6f)
    .asrRateEnum(AsrRequestConfig.RATE_16000).build()
turingAsr.startAsrWithRecorder(false,asrConfig,turingOSClientPlayListener)

VAD相关参数,在asr模块中设置,详细说明见AsrRequestConfig

备注:此功能需要开通权限才能使用,如需要使用VAD功能,请联系图灵技术支持

参数说明

输入参数

AsrRequestConfig

对应turing_config.json中的asr参数

参数 类型 是否必须 说明
asrSrcFormatEnum int N 当不使用内部录音器的时候该值为必填,音频格式: asrFormatEnum=0:PCM asrFormatEnum=1:OPUS asrFormatEnum=2:SPEEX,默认-1,不使用外部录音
asrFormatEnum int Y 音频格式: asrFormatEnum=0:PCM asrFormatEnum=1:OPUS asrFormatEnum=2:SPEEX
asrLanguageEnum int Y 语言: asrLanguageEnum=0:中文(开启后支持中英文混合识别) asrLanguageEnum=1:英文
asrRateEnum int Y 音频采样率: asrRateEnum=0:8k(PCM) asrRateEnum=1:16k(PCM, OPUS, SPEEX)
intermediateResult boolean N 是否返回中间ASR结果(默认false)
enableITN boolean N 返回结果的数字格式规则为阿拉伯数字格式(默认true)
enablePunctuation boolean N 是否开启标点符号添加(默认true)
enableVoiceDetection boolean N 是否开启离线VAD(默认false): 启动后需要同时设置maxStartSilence和maxEndSilence的值
maxStartSilence Integer N 允许的最大开始静音(单位是毫秒),即为说话前的超时时间,超时后结束录音,asr回调接口会回调onResult,code=5002,需要先设置enableVoiceDetection为true
maxEndSilence Integer N 允许的最大结束静音(单位是毫秒),即为说话后的超时时间, 超时后结束录音,返回识别结果,需要先设置enableVoiceDetection为true
vadThreshold float N 声音检测灵敏度,范围0-1,越小则越容易检测到声音,默认0.8
vadReviseTime Integer N 设置VAD修正时间,针对VAD提前异常结束问题,在这个时间内,如果VAD出现 了FINISH状态则会跳过此事件,这个值不建议设置太大,否则可能会忽略正常的VAD 事件
vadState boolean N 是否返回VAD状态,默认false,设置true时,在turingOSClientAsrListener.onResult()中会返回code=TuringCode.VAD_STATE_BEGIN或TuringCode.VAD_STATE_FINISH
interactionTime int N ASR最大录音时间
enableCloudVad boolean N 是否开启云端VAD(默认false)
enableVolume boolean N 使用内部录音时,是否返回声音音量变化,true则回调void onVoiceVolume(int i)
saveAudioPath String N 保存本地音频路径,设置后会保存录音到本地,不设置则不保存

opus格式要求:

  • pcm转为opus裸包之后在头部增加8个字节,其中第3,4字节代表音频片段数据长度{head(8byte 3,4位存数据长度)+data} + {head(8byte 3,4位存数据长度)+data} + ...
  • 每次调用opensocket上传音频片段必须完整
  • 大端模式

回调接口

TuringOSClientAsrListener

录音或者音频流输入时,ASR通道状态、ASR识别结果以及对话结果都使用该接口回调,具体参考下面对应方法的示例说明;

public interface TuringOSClientAsrListener {

    /**
     * 当使用SDK录音器开启的识别,此方法会在录音开始后回调
     * 一般用于UI显示开始录音,更新UI需要放到主线程,不能再此回调方法中更新
     */
    void onRecorderStart();

    /**
     * asr识别停止,包括请求Error或者外部调用client.stopAsr都会回调
     */
    void onStop();

    /**
     * 允许输入音频数据流,在该方法回调之后开始调用sendAudio
     */
    void onStreamOpen();

    /**
     *
     * 请求结果返回
     *
     * @param code 具体参考code说明
     * @param result 返回的json字符串
     * @param isLast Asr识别结果;last : 是否是最终结果
     * @param baseResp  返回的json字符串转换的Java对象
     */
    void onResult(int code, String result, boolean isLast, BaseResp baseResp);

    /**
     * Asr识别单论交互倒计时 最大值20s
     * 单句语音识别场景下的倒计时限制,连续识别不受影响
     *
     * @param second
     */
    void onTimer(int second);

    /**
     * 请求发生错误的信息
     *
     * @param code
     * @param msg
     */
    void onError(int code, String msg);

    /**
     * 使用内部录音时,返回声音音量变化,该方法的回调需要先设置参数enableVolume为true
     *
     */
    void onVoiceVolume(int i);

}

输出参数

ASR识别结果

返回的结果在TuringOSClientAsrListener的onResult方法中,其中String result为json字符串,BaseResp baseResp为result转换为json后的java对象。

json示例如下:

{
    "asrResponse":{
        "binarysId":"0a2071a8-2bb6-4fae-b109-32bee00c1726",
        "state":200,
        "value":"深圳明天的天气"
    },
    "code":200,
    "globalId":"98412368730000000",
    "message":"success"
}

BaseResp说明

参数 类型 说明
code int 请求响应Code,具体可参考Code说明
message String 请求响应的消息描述
localAudioFile String 本地音频文件路径
asrResponse AsrResponse(Object) ASR识别结果
  • 当code=200表示识别成功;
  • 当code=5002时表示没有任何有效人声输入;
  • 其他code表示识别异常,参考Code说明

AsrResponse参数说明

参数 类型 是否必须 取值范围 说明
binarysId String Y - asr二进制参数Id
value String Y - asr识别内容
state int Y 200,210 210:asr识别中间结果返回,200:asr识别完成结果
  • AsrRequestConfig的参数intermediateResult设置为true之后,语音识别会实时返回识别结果;
  • state=210表示此次返回的识别结果为中间结果,此时onResult方法中的isLast为fasle;
  • state=200表示此次返回的识别结果为最终结果,此时onResult方法中的isLast为true。