|
|
@@ -1,10 +1,13 @@
|
|
|
package com.nova.brain.glass.helper
|
|
|
|
|
|
import android.util.Log
|
|
|
+import com.nova.brain.glass.BuildConfig
|
|
|
import com.nova.brain.glass.model.RecognizeAction
|
|
|
import com.rokid.online.speech.AsrClient
|
|
|
import com.rokid.online.speech.OnlineSpeechSdk
|
|
|
import com.rokid.online.speech.OnlineSpeechSdkConfig
|
|
|
+import com.rokid.online.speech.TtsClient
|
|
|
+import com.rokid.online.speech.open.AndroidPcmTtsStreamPlayer
|
|
|
import com.rokid.online.speech.open.OpenSdkAudioSource
|
|
|
import com.xuqm.base.extensions.showMessage
|
|
|
|
|
|
@@ -12,14 +15,14 @@ object AsrHelper : OfflineCmdListener {
|
|
|
|
|
|
private const val TAG = "AsrHelper"
|
|
|
|
|
|
- // 配置信息,从 online-speech-sdk-demo 参考项目复制
|
|
|
- private const val DOMAIN = "api-test.rokid.com"
|
|
|
- private const val ASR_PATH = "/ar/audio/api/ws/asr/streaming"
|
|
|
- private const val TTS_PATH = "/ar/audio/api/ws/tts"
|
|
|
- private const val AK = ""
|
|
|
- private const val SK = ""
|
|
|
- private const val UID = "demo-user"
|
|
|
- private const val DEVICE_ID = "demo-device"
|
|
|
+ // 配置信息来自 BuildConfig(在 app/build.gradle 的 buildConfigField 中维护)
|
|
|
+ private val DOMAIN get() = BuildConfig.SPEECH_DOMAIN
|
|
|
+ private val AK get() = BuildConfig.SPEECH_AK
|
|
|
+ private val SK get() = BuildConfig.SPEECH_SK
|
|
|
+ private val UID get() = BuildConfig.SPEECH_UID
|
|
|
+ private val DEVICE_ID get() = BuildConfig.SPEECH_DEVICE_ID
|
|
|
+ private val ASR_PATH get() = BuildConfig.SPEECH_ASR_PATH
|
|
|
+ private val TTS_PATH get() = BuildConfig.SPEECH_TTS_PATH
|
|
|
|
|
|
// 唤醒词:Nova Nova
|
|
|
private const val WAKE_WORD = "Nova Nova"
|
|
|
@@ -27,10 +30,15 @@ object AsrHelper : OfflineCmdListener {
|
|
|
|
|
|
private var sdk: OnlineSpeechSdk? = null
|
|
|
private var asr: AsrClient? = null
|
|
|
+ private var tts: TtsClient? = null
|
|
|
private val audioSource = OpenSdkAudioSource()
|
|
|
+ private val ttsPlayer = AndroidPcmTtsStreamPlayer()
|
|
|
|
|
|
private var isConnected = false
|
|
|
private var isMicRunning = false
|
|
|
+ private var isTtsConnected = false
|
|
|
+
|
|
|
+ private const val WAKE_RESPONSE = "在呢,您请说"
|
|
|
|
|
|
// 拼接每次识别会话中的中间结果
|
|
|
private var currentPartial = ""
|
|
|
@@ -63,13 +71,15 @@ object AsrHelper : OfflineCmdListener {
|
|
|
|
|
|
sdk = OnlineSpeechSdk(cfg)
|
|
|
asr = sdk!!.createAsrClient().attachAudioSource(audioSource).also { setupAsrCallbacks(it) }
|
|
|
+ tts = sdk!!.createTtsClient().attachStreamPlayer(ttsPlayer).also { setupTtsCallbacks(it) }
|
|
|
|
|
|
// 注册离线关键词 Nova Nova,GlassSdk 触发后启动 ASR
|
|
|
OfflineCmdServiceHelper.registerAsrWakeWord()
|
|
|
OfflineCmdServiceHelper.addOnLineListener(this)
|
|
|
|
|
|
- // 自动建立 ASR 连接
|
|
|
+ // 自动建立 ASR / TTS 连接
|
|
|
asrConnect()
|
|
|
+ tts?.connect()
|
|
|
|
|
|
Log.d(TAG, "AsrHelper init done")
|
|
|
}
|
|
|
@@ -150,11 +160,40 @@ object AsrHelper : OfflineCmdListener {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- // 离线关键词回调:匹配唤醒词时启动麦克风
|
|
|
+ private fun setupTtsCallbacks(ttsClient: TtsClient) {
|
|
|
+ ttsClient.setListener(object : TtsClient.Listener {
|
|
|
+ override fun onOpen() {
|
|
|
+ isTtsConnected = true
|
|
|
+ Log.d(TAG, "TTS websocket open")
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onFinished(taskId: String) {
|
|
|
+ Log.d(TAG, "TTS ended: $taskId, starting mic")
|
|
|
+ asrStartMic()
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onError(code: Int, message: String) {
|
|
|
+ Log.e(TAG, "TTS error code=$code msg=$message, fallback to mic")
|
|
|
+ asrStartMic()
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onClosed(code: Int, reason: String) {
|
|
|
+ isTtsConnected = false
|
|
|
+ Log.d(TAG, "TTS closed code=$code reason=$reason")
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 离线关键词回调:唤醒词触发时先 TTS 播报,播报结束后启动麦克风
|
|
|
override fun onOfflineCmd(cmd: String) {
|
|
|
if (cmd == WAKE_WORD) {
|
|
|
- Log.d(TAG, "Wake word triggered, starting mic")
|
|
|
- asrStartMic()
|
|
|
+ Log.d(TAG, "Wake word triggered")
|
|
|
+ if (isTtsConnected) {
|
|
|
+ tts?.speak(WAKE_RESPONSE)
|
|
|
+ } else {
|
|
|
+ Log.w(TAG, "TTS not connected, starting mic directly")
|
|
|
+ asrStartMic()
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -165,10 +204,13 @@ object AsrHelper : OfflineCmdListener {
|
|
|
isMicRunning = false
|
|
|
}
|
|
|
asr?.close()
|
|
|
+ tts?.close()
|
|
|
sdk?.close()
|
|
|
asr = null
|
|
|
+ tts = null
|
|
|
sdk = null
|
|
|
isConnected = false
|
|
|
+ isTtsConnected = false
|
|
|
Log.d(TAG, "AsrHelper closed")
|
|
|
}
|
|
|
}
|