[6.2.0]BadCase增加语音转写
This commit is contained in:
@@ -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())
|
||||
// 监听弱网
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" //渠道
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
package com.mogo.eagle.core.utilcode.util;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
|
||||
/**
|
||||
* Json结果解析类
|
||||
*/
|
||||
public class JsonParser {
|
||||
|
||||
public static String parseIatResult(String json) {
|
||||
StringBuffer ret = new StringBuffer();
|
||||
try {
|
||||
JSONTokener tokener = new JSONTokener(json);
|
||||
JSONObject joResult = new JSONObject(tokener);
|
||||
|
||||
JSONArray words = joResult.getJSONArray("ws");
|
||||
for (int i = 0; i < words.length(); i++) {
|
||||
// 转写结果词,默认使用第一个结果
|
||||
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
|
||||
JSONObject obj = items.getJSONObject(0);
|
||||
ret.append(obj.getString("w"));
|
||||
// 如果需要多候选结果,解析数组其他字段
|
||||
// for(int j = 0; j < items.length(); j++)
|
||||
// {
|
||||
// JSONObject obj = items.getJSONObject(j);
|
||||
// ret.append(obj.getString("w"));
|
||||
// }
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
public static String parseGrammarResult(String json, String engType) {
|
||||
StringBuffer ret = new StringBuffer();
|
||||
try {
|
||||
JSONTokener tokener = new JSONTokener(json);
|
||||
JSONObject joResult = new JSONObject(tokener);
|
||||
|
||||
JSONArray words = joResult.getJSONArray("ws");
|
||||
// 云端和本地结果分情况解析
|
||||
if ("cloud".equals(engType)) {
|
||||
for (int i = 0; i < words.length(); i++) {
|
||||
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
|
||||
for (int j = 0; j < items.length(); j++) {
|
||||
JSONObject obj = items.getJSONObject(j);
|
||||
if (obj.getString("w").contains("nomatch")) {
|
||||
ret.append("没有匹配结果.");
|
||||
return ret.toString();
|
||||
}
|
||||
ret.append("【结果】" + obj.getString("w"));
|
||||
ret.append("【置信度】" + obj.getInt("sc"));
|
||||
ret.append("\n");
|
||||
}
|
||||
}
|
||||
} else if ("local".equals(engType)) {
|
||||
ret.append("【结果】");
|
||||
for (int i = 0; i < words.length(); i++) {
|
||||
JSONObject wsItem = words.getJSONObject(i);
|
||||
JSONArray items = wsItem.getJSONArray("cw");
|
||||
if ("<contact>".equals(wsItem.getString("slot"))) {
|
||||
// 可能会有多个联系人供选择,用中括号括起来,这些候选项具有相同的置信度
|
||||
ret.append("【");
|
||||
for (int j = 0; j < items.length(); j++) {
|
||||
JSONObject obj = items.getJSONObject(j);
|
||||
if (obj.getString("w").contains("nomatch")) {
|
||||
ret.append("没有匹配结果.");
|
||||
return ret.toString();
|
||||
}
|
||||
ret.append(obj.getString("w")).append("|");
|
||||
}
|
||||
ret.setCharAt(ret.length() - 1, '】');
|
||||
} else {
|
||||
//本地多候选按照置信度高低排序,一般选取第一个结果即可
|
||||
JSONObject obj = items.getJSONObject(0);
|
||||
if (obj.getString("w").contains("nomatch")) {
|
||||
ret.append("没有匹配结果.");
|
||||
return ret.toString();
|
||||
}
|
||||
ret.append(obj.getString("w"));
|
||||
}
|
||||
}
|
||||
ret.append("【置信度】" + joResult.getInt("sc"));
|
||||
ret.append("\n");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ret.append("没有匹配结果.");
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
public static String parseGrammarResult(String json) {
|
||||
StringBuffer ret = new StringBuffer();
|
||||
try {
|
||||
JSONTokener tokener = new JSONTokener(json);
|
||||
JSONObject joResult = new JSONObject(tokener);
|
||||
|
||||
JSONArray words = joResult.getJSONArray("ws");
|
||||
for (int i = 0; i < words.length(); i++) {
|
||||
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
|
||||
for (int j = 0; j < items.length(); j++) {
|
||||
JSONObject obj = items.getJSONObject(j);
|
||||
if (obj.getString("w").contains("nomatch")) {
|
||||
ret.append("没有匹配结果.");
|
||||
return ret.toString();
|
||||
}
|
||||
ret.append("【结果】" + obj.getString("w"));
|
||||
ret.append("【置信度】" + obj.getInt("sc"));
|
||||
ret.append("\n");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ret.append("没有匹配结果.");
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
public static String parseLocalGrammarResult(String json) {
|
||||
StringBuffer ret = new StringBuffer();
|
||||
try {
|
||||
JSONTokener tokener = new JSONTokener(json);
|
||||
JSONObject joResult = new JSONObject(tokener);
|
||||
|
||||
JSONArray words = joResult.getJSONArray("ws");
|
||||
for (int i = 0; i < words.length(); i++) {
|
||||
JSONArray items = words.getJSONObject(i).getJSONArray("cw");
|
||||
for (int j = 0; j < items.length(); j++) {
|
||||
JSONObject obj = items.getJSONObject(j);
|
||||
if (obj.getString("w").contains("nomatch")) {
|
||||
ret.append("没有匹配结果.");
|
||||
return ret.toString();
|
||||
}
|
||||
ret.append("【结果】" + obj.getString("w"));
|
||||
ret.append("\n");
|
||||
}
|
||||
}
|
||||
ret.append("【置信度】" + joResult.optInt("sc"));
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ret.append("没有匹配结果.");
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
public static String parseTransResult(String json, String key) {
|
||||
StringBuffer ret = new StringBuffer();
|
||||
try {
|
||||
JSONTokener tokener = new JSONTokener(json);
|
||||
JSONObject joResult = new JSONObject(tokener);
|
||||
String errorCode = joResult.optString("ret");
|
||||
if (!errorCode.equals("0")) {
|
||||
return joResult.optString("errmsg");
|
||||
}
|
||||
JSONObject transResult = joResult.optJSONObject("trans_result");
|
||||
ret.append(transResult.optString(key));
|
||||
/*JSONArray words = joResult.getJSONArray("results");
|
||||
for (int i = 0; i < words.length(); i++) {
|
||||
JSONObject obj = words.getJSONObject(i);
|
||||
ret.append(obj.getString(key));
|
||||
}*/
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
}
|
||||
@@ -42,10 +42,16 @@ android {
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
jniLibs.srcDirs = ['libs']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
api fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
|
||||
BIN
tts/tts-base/libs/Msc.jar
Normal file
BIN
tts/tts-base/libs/Msc.jar
Normal file
Binary file not shown.
BIN
tts/tts-base/libs/arm64-v8a/libmsc.so
Normal file
BIN
tts/tts-base/libs/arm64-v8a/libmsc.so
Normal file
Binary file not shown.
BIN
tts/tts-base/libs/armeabi-v7a/libmsc.so
Normal file
BIN
tts/tts-base/libs/armeabi-v7a/libmsc.so
Normal file
Binary file not shown.
52
tts/tts-base/src/main/java/com/mogo/tts/base/SpeechUtils.kt
Normal file
52
tts/tts-base/src/main/java/com/mogo/tts/base/SpeechUtils.kt
Normal file
@@ -0,0 +1,52 @@
|
||||
package com.mogo.tts.base
|
||||
|
||||
import android.content.Context
|
||||
import com.iflytek.cloud.Setting
|
||||
import com.iflytek.cloud.SpeechConstant
|
||||
import com.iflytek.cloud.SpeechRecognizer
|
||||
import com.iflytek.cloud.SpeechUtility
|
||||
|
||||
object SpeechUtils {
|
||||
|
||||
private var mscInitialize: Boolean =false
|
||||
|
||||
fun init(context: Context){
|
||||
if(mscInitialize)
|
||||
return
|
||||
// 应用程序入口处调用,避免手机内存过小,杀死后台进程后通过历史intent进入Activity造成SpeechUtility对象为null
|
||||
// 如在Application中调用初始化,需要在Mainifest中注册该Applicaiton
|
||||
// 注意:此接口在非主进程调用会返回null对象,如需在非主进程使用语音功能,请增加参数:SpeechConstant.FORCE_LOGIN+"=true"
|
||||
// 参数间使用半角“,”分隔。
|
||||
// 设置你申请的应用appid,请勿在'='与appid之间添加空格及空转义符
|
||||
// 注意: appid 必须和下载的SDK保持一致,否则会出现10407错误
|
||||
SpeechUtility.createUtility(context, "appid=0c498b42")
|
||||
// 以下语句用于设置日志开关(默认开启),设置成false时关闭语音云SDK日志打印
|
||||
|
||||
// 以下语句用于设置日志开关(默认开启),设置成false时关闭语音云SDK日志打印
|
||||
Setting.setShowLog(true)
|
||||
mscInitialize = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数设置
|
||||
*/
|
||||
fun setParam(mIat: SpeechRecognizer) {
|
||||
// 清空参数
|
||||
mIat.setParameter(SpeechConstant.PARAMS, null)
|
||||
// 设置听写引擎
|
||||
mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD)
|
||||
// 设置返回结果格式
|
||||
mIat.setParameter(SpeechConstant.RESULT_TYPE, "json")
|
||||
// 设置语言
|
||||
mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn")
|
||||
//此处用于设置dialog中不显示错误码信息
|
||||
//mIat.setParameter("view_tips_plain","false");
|
||||
// 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
|
||||
mIat.setParameter(SpeechConstant.VAD_BOS, "50000")
|
||||
// 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
|
||||
mIat.setParameter(SpeechConstant.VAD_EOS, "10000")
|
||||
// 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
|
||||
mIat.setParameter(SpeechConstant.ASR_PTT, "0")
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
@@ -44,14 +44,7 @@ class IFlyTekTts : IMogoTTS, InitListener {
|
||||
|
||||
override fun init(context: Context) {
|
||||
this.context = context
|
||||
|
||||
// 应用程序入口处调用,避免手机内存过小,杀死后台进程后通过历史intent进入Activity造成SpeechUtility对象为null
|
||||
// 如在Application中调用初始化,需要在Mainifest中注册该Applicaiton
|
||||
// 注意:此接口在非主进程调用会返回null对象,如需在非主进程使用语音功能,请增加参数:SpeechConstant.FORCE_LOGIN+"=true"
|
||||
// 参数间使用半角“,”分隔。
|
||||
// 设置你申请的应用appid,请勿在'='与appid之间添加空格及空转义符
|
||||
// 注意: appid 必须和下载的SDK保持一致,否则会出现10407错误
|
||||
SpeechUtility.createUtility(context, "appid=0c498b42")
|
||||
SpeechUtils.init(context)
|
||||
ttsEngine = SpeechSynthesizer.createSynthesizer(context, this)
|
||||
updateTtsParam()
|
||||
voicerEntries = context.resources?.getStringArray(R.array.voicer_cloud_values)
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user