[6.2.0]BadCase增加语音转写

This commit is contained in:
xuxinchao
2023-11-06 20:52:53 +08:00
parent 0962d69dff
commit c851a8b7a9
13 changed files with 460 additions and 19 deletions

View File

@@ -109,7 +109,7 @@ class DevaToolsProvider : IDevaToolsProvider {
iPCReportManager.initServer()
BindingCarManager.init(mContext!!)
apmEnvProvider.init(if(DebugConfig.isDebug()) "0" else "1", "${ DebugConfig.getNetMode() }", mDockerVersion ?: "")
BadCaseManager.init()
BadCaseManager.init(mContext!!)
if (DebugConfig.isDebug()) {
SdtManager.init(mContext!!, true, DetectResultImpl())
// 监听弱网

View File

@@ -24,11 +24,11 @@ import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_DEVA
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast
import com.mogo.eagle.core.utilcode.util.*
import com.mogo.tts.base.SpeechUtils
import com.zhjt.mogo_core_function_devatools.badcase.biz.*
import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig
import com.zhjt.mogo_core_function_devatools.badcase.repository.db.entity.AutoPilotRecord
import com.zhjt.mogo_core_function_devatools.ext.enqueuePop
import kotlinx.coroutines.*
import me.jessyan.autosize.utils.AutoSizeUtils
import record_cache.RecordPanelOuterClass
@@ -41,8 +41,9 @@ internal object BadCaseManager : LifecycleEventObserver, IMoGoAutopilotRecordLis
@Volatile
private var record: AutoPilotRecord? = null
fun init() {
fun init(context: Context) {
CallerAutopilotRecordListenerManager.addListener(TAG, this)
SpeechUtils.init(context)
}
/**

View File

@@ -3,14 +3,22 @@ package com.zhjt.mogo_core_function_devatools.badcase.biz
import android.annotation.SuppressLint
import android.app.Activity
import android.graphics.PixelFormat
import android.os.Bundle
import android.os.CountDownTimer
import android.os.Handler
import android.os.SystemClock
import android.util.DisplayMetrics
import android.util.Log
import android.view.*
import android.widget.CheckBox
import android.widget.ImageView
import android.widget.TextView
import com.iflytek.cloud.ErrorCode
import com.iflytek.cloud.InitListener
import com.iflytek.cloud.RecognizerListener
import com.iflytek.cloud.RecognizerResult
import com.iflytek.cloud.SpeechError
import com.iflytek.cloud.SpeechRecognizer
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.app.AppConfigInfo
import com.mogo.eagle.core.data.deva.badcase.BagDescriptionEntity
@@ -26,9 +34,12 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast
import com.mogo.eagle.core.utilcode.util.AppUtils
import com.mogo.eagle.core.utilcode.util.BarUtils
import com.mogo.eagle.core.utilcode.util.JsonParser
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.eagle.core.utilcode.util.TimeUtils
import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.tts.base.SpeechUtils
import com.zhidao.loglib.call.LogInfoManagerFactory
import com.zhidao.loglib.upload.OnUploadListener
import com.zhidao.loglib.upload.UploadManager
@@ -39,9 +50,10 @@ import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig
import com.zhjt.mogo_core_function_devatools.badcase.record.RecordManager
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.json.JSONException
import org.json.JSONObject
import record_cache.RecordPanelOuterClass
import java.io.File
import java.lang.StringBuilder
import java.util.*
@@ -84,6 +96,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
private var audioFileName:String?=null //录音文件名称
private var uploadReason: StringBuilder = StringBuilder() //上报原因,标签
private var reasonDetail: String ?= null //语音转写
@Volatile
private var recordKey: Long = 0 //录制bag包key
@Volatile
@@ -102,6 +115,14 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
private var clickListener: ClickListener? = null
// 语音听写对象
private var mIat: SpeechRecognizer? = null
var ret = 0 // 函数调用返回值
// 用HashMap存储听写结果
private val mIatResults: HashMap<String, String> = LinkedHashMap()
init {
initFloatWindow()
}
@@ -115,6 +136,10 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
mFloatLayout = LayoutInflater.from(mActivity).inflate(R.layout.view_initiative_bad_case, null) as View
mFloatLayout.setOnTouchListener(this)
// 初始化识别无UI识别对象
// 使用SpeechRecognizer对象可根据回调消息自定义界面
mIat = SpeechRecognizer.createRecognizer(mActivity, mInitListener)
tvInitiativeNum = mFloatLayout.findViewById(R.id.tvInitiativeNum)
tvInitiativeTime = mFloatLayout.findViewById(R.id.tvInitiativeTime)
tvInitiativeIdentity = mFloatLayout.findViewById(R.id.tvInitiativeIdentity)
@@ -172,10 +197,10 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
uploadReason.append("点刹、顿挫")
}
if(audioStatus){
audioStatus = !audioStatus
setAudio(audioStatus)
audioStatus = false
setAudio(false)
Handler().postDelayed({
uploadAudio()
uploadAudio()
},1000)
}else{
uploadAudio()
@@ -200,11 +225,91 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
}
}
/**
* 初始化监听器。
*/
private val mInitListener = InitListener { code ->
Log.i(TAG, "SpeechRecognizer init() code = $code")
if (code != ErrorCode.SUCCESS) {
ToastUtils.showShort("讯飞语音听写初始化失败,错误码:$code")
}
}
/**
* 听写监听器。
*/
private val mRecognizerListener: RecognizerListener = object : RecognizerListener{
override fun onVolumeChanged(p0: Int, p1: ByteArray?) {
//showTip("当前正在说话,音量大小 = " + volume + " 返回音频数据 = " + data.length);
}
override fun onBeginOfSpeech() {
// 此回调表示sdk内部录音机已经准备好了用户可以开始语音输入
}
override fun onEndOfSpeech() {
// 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
}
override fun onResult(results: RecognizerResult?, isLast: Boolean) {
results?.let {
printResult(it)
}
}
override fun onError(p0: SpeechError?) {
// Tips
// 错误码10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
}
override fun onEvent(p0: Int, p1: Int, p2: Int, p3: Bundle?) {
// 以下代码用于获取与云端的会话id当业务出错时将会话id提供给技术支持人员可用于查询会话日志定位出错原因
// 若使用本地能力会话id为null
// if (SpeechEvent.EVENT_SESSION_ID == eventType) {
// String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
// Log.d(TAG, "session id =" + sid);
// }
}
}
/**
* 显示结果
*/
private fun printResult(results: RecognizerResult) {
val text: String = JsonParser.parseIatResult(results.resultString)
var sn: String? = null
// 读取json结果中的sn字段
try {
val resultJson = JSONObject(results.resultString)
sn = resultJson.optString("sn")
} catch (e: JSONException) {
e.printStackTrace()
}
mIatResults[sn!!] = text
val resultBuffer = java.lang.StringBuilder()
for (key in mIatResults.keys) {
resultBuffer.append(mIatResults[key])
}
Log.i(TAG, "语音内容=$resultBuffer")
reasonDetail = resultBuffer.toString()
}
var countDownTimer: CountDownTimer?=null
private fun setAudio(status: Boolean){
if(status){
//开始录音
mIat?.let {
//清空之前的内容
mIatResults.clear()
SpeechUtils.setParam(it)
// 不显示听写对话框
ret = it.startListening(mRecognizerListener)
if (ret != ErrorCode.SUCCESS) {
ToastUtils.showShort("听写失败,错误码:$ret,请点击网址https://www.xfyun.cn/document/error-code查询解决方案")
}
}
audioFileName = "Audio_${System.currentTimeMillis()}_BadCase"
RecordManager.getInstance().start(audioFileName)
//更改录音按钮背景
@@ -229,6 +334,8 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
countDownTimer?.start()
}
}else{
//停止语音听写
mIat?.stopListening()
//结束倒计时
countDownTimer?.cancel()
countDownTimer?.onFinish()
@@ -292,7 +399,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
itx["filename"] = recordFileName?:"" //bag包文件地址
itx["filesize"] = "0" //bag包文件大小
itx["key"] = recordKey.toString() //key
itx["reason"] = uploadReason.toString() //采集原因
itx["reason"] = "$uploadReason 语音内容:$reasonDetail" //采集原因
itx["duration"] = BadCaseConfig.totalDuration.toString() //采集时长固定为20S
itx["startTime"] = System.currentTimeMillis().toString() //上报时间(时间戳格式)
itx["channel"] = "1" //渠道
@@ -336,7 +443,7 @@ class InitiativeBadCaseWindow constructor(activity: Activity) : View.OnTouchList
if(receiveTime!=null){
try {
uploadStamp=TimeUtils.dateToStamp(receiveTime,"yyyyMMddHHmmss")
}catch (e: Exception){
}catch (_: Exception){
}
}
}

View File

@@ -4,15 +4,23 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.graphics.Color
import android.graphics.PixelFormat
import android.os.Bundle
import android.os.CountDownTimer
import android.os.Handler
import android.util.DisplayMetrics
import android.util.Log
import android.view.*
import android.widget.CheckBox
import android.widget.CompoundButton
import android.widget.ImageView
import android.widget.TextView
import com.google.android.flexbox.FlexboxLayout
import com.iflytek.cloud.ErrorCode
import com.iflytek.cloud.InitListener
import com.iflytek.cloud.RecognizerListener
import com.iflytek.cloud.RecognizerResult
import com.iflytek.cloud.SpeechError
import com.iflytek.cloud.SpeechRecognizer
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
import com.mogo.eagle.core.data.app.AppConfigInfo
import com.mogo.eagle.core.data.deva.badcase.BagDescriptionEntity
@@ -27,6 +35,7 @@ import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_
import com.mogo.eagle.core.utilcode.mogo.toast.TipToast
import com.mogo.eagle.core.utilcode.util.*
import com.mogo.eagle.core.utilcode.util.TimeUtils.millis2String
import com.mogo.tts.base.SpeechUtils
import com.zhidao.loglib.call.LogInfoManagerFactory
import com.zhidao.loglib.upload.OnUploadListener
import com.zhjt.mogo_core_function_devatools.R
@@ -39,6 +48,8 @@ import com.zhidao.loglib.util.FileUtil
import com.zhjt.mogo_core_function_devatools.badcase.BadCaseAnalyticsManager
import me.jessyan.autosize.utils.AutoSizeUtils
import org.greenrobot.eventbus.EventBus
import org.json.JSONException
import org.json.JSONObject
import java.io.File
/**
@@ -92,6 +103,16 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene
private lateinit var flReasonLayout: FlexboxLayout
// 语音听写对象
private var mIat: SpeechRecognizer? = null
var ret = 0 // 函数调用返回值
// 用HashMap存储听写结果
private val mIatResults: HashMap<String, String> = LinkedHashMap()
private var reasonDetail: String ?= null //语音转写
init {
initFloatWindow()
}
@@ -104,6 +125,11 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene
private fun initFloatWindow(){
mFloatLayout = LayoutInflater.from(mActivity).inflate(R.layout.view_passive_bad_case, null) as View
mFloatLayout.setOnTouchListener(this)
// 初始化识别无UI识别对象
// 使用SpeechRecognizer对象可根据回调消息自定义界面
mIat = SpeechRecognizer.createRecognizer(mActivity, mInitListener)
tvPassiveNum = mFloatLayout.findViewById(R.id.tvPassiveNum)
tvPassiveTime = mFloatLayout.findViewById(R.id.tvPassiveTime)
tvPassiveIdentity = mFloatLayout.findViewById(R.id.tvPassiveIdentity)
@@ -163,9 +189,90 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene
}
}
/**
* 初始化监听器。
*/
private val mInitListener = InitListener { code ->
Log.i(TAG, "SpeechRecognizer init() code = $code")
if (code != ErrorCode.SUCCESS) {
ToastUtils.showShort("讯飞语音听写初始化失败,错误码:$code")
}
}
/**
* 听写监听器。
*/
private val mRecognizerListener: RecognizerListener = object : RecognizerListener{
override fun onVolumeChanged(p0: Int, p1: ByteArray?) {
//showTip("当前正在说话,音量大小 = " + volume + " 返回音频数据 = " + data.length);
}
override fun onBeginOfSpeech() {
// 此回调表示sdk内部录音机已经准备好了用户可以开始语音输入
}
override fun onEndOfSpeech() {
// 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
}
override fun onResult(results: RecognizerResult?, isLast: Boolean) {
results?.let {
printResult(it)
}
}
override fun onError(p0: SpeechError?) {
// Tips
// 错误码10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
}
override fun onEvent(p0: Int, p1: Int, p2: Int, p3: Bundle?) {
// 以下代码用于获取与云端的会话id当业务出错时将会话id提供给技术支持人员可用于查询会话日志定位出错原因
// 若使用本地能力会话id为null
// if (SpeechEvent.EVENT_SESSION_ID == eventType) {
// String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
// Log.d(TAG, "session id =" + sid);
// }
}
}
/**
* 显示结果
*/
private fun printResult(results: RecognizerResult) {
val text: String = JsonParser.parseIatResult(results.resultString)
var sn: String? = null
// 读取json结果中的sn字段
try {
val resultJson = JSONObject(results.resultString)
sn = resultJson.optString("sn")
} catch (e: JSONException) {
e.printStackTrace()
}
mIatResults[sn!!] = text
val resultBuffer = java.lang.StringBuilder()
for (key in mIatResults.keys) {
resultBuffer.append(mIatResults[key])
}
Log.i(TAG, "语音内容=$resultBuffer")
reasonDetail = resultBuffer.toString()
}
private fun setAudio(status: Boolean){
if(status){
//开始录音
mIat?.let {
//清空之前的内容
mIatResults.clear()
SpeechUtils.setParam(it)
// 不显示听写对话框
ret = it.startListening(mRecognizerListener)
if (ret != ErrorCode.SUCCESS) {
ToastUtils.showShort("听写失败,错误码:$ret,请点击网址https://www.xfyun.cn/document/error-code查询解决方案")
}
}
audioFileName = "Audio_${System.currentTimeMillis()}_BadCase"
RecordManager.getInstance().start(audioFileName)
//更改录音按钮背景
@@ -190,6 +297,8 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene
countDownTimer?.start()
}
}else{
//停止语音听写
mIat?.stopListening()
//结束倒计时
countDownTimer?.cancel()
countDownTimer?.onFinish()
@@ -253,7 +362,7 @@ class PassiveBadCaseWindow constructor(activity: Activity) : View.OnTouchListene
itx["filename"] = recordFileName?:"" //bag包文件地址
itx["filesize"] = "0" //bag包文件大小
itx["key"] = recordKey?:"" //key
itx["reason"] = uploadReason //采集原因
itx["reason"] = "$uploadReason 语音内容:$reasonDetail" //采集原因
itx["duration"] = BadCaseConfig.totalDuration.toString() //采集时长固定为20S
itx["startTime"] = System.currentTimeMillis().toString() //上报时间(时间戳格式)
itx["channel"] = "0" //渠道