mirror of
https://github.com/souravanand001/ai-assistant-android.git
synced 2026-10-03 04:36:08 +00:00
Improved launch speed on app startup by moving init on demand.
This commit is contained in:
parent
c3bce8f807
commit
f8c9ac3bf6
6 changed files with 81 additions and 41 deletions
|
|
@ -151,13 +151,18 @@ class MainActivity : ComponentActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
var wasHandsFreeActive = false
|
||||
lifecycleScope.launch {
|
||||
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
viewModel.isHandsFreeModeActive.collect { active ->
|
||||
if (active) {
|
||||
wasHandsFreeActive = true
|
||||
startSpeechRecognition(isHandsFree = true)
|
||||
} else {
|
||||
speechRecognizerManager.stop()
|
||||
if (wasHandsFreeActive) {
|
||||
wasHandsFreeActive = false
|
||||
speechRecognizerManager.stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,14 +161,10 @@ class SpeechRecognizerManager(
|
|||
|
||||
fun preLoadModelAsync() {
|
||||
val mode = settingsRepository.getSttMode()
|
||||
if (modelManager.isModelDownloaded()) {
|
||||
if (mode == SttMode.PARAKEET && modelManager.isModelDownloaded()) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
if (mode == SttMode.PARAKEET || mode == SttMode.HYBRID || mode == SttMode.NATIVE) {
|
||||
initVad()
|
||||
initOfflineRecognizer()
|
||||
} else if (mode == SttMode.API) {
|
||||
initVad()
|
||||
}
|
||||
initVad()
|
||||
initOfflineRecognizer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,23 +4,43 @@ import android.content.Context
|
|||
import com.app.assistant.config.SpeechConfig
|
||||
import com.app.assistant.config.TtsApiProvider
|
||||
import com.app.assistant.repository.SettingsRepository
|
||||
import okhttp3.OkHttpClient
|
||||
|
||||
class ApiTtsManager(
|
||||
private val context: Context,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
private val okHttpClient: OkHttpClient,
|
||||
private val onSpeakingStateChanged: (isSpeaking: Boolean) -> Unit
|
||||
) : TtsManager {
|
||||
|
||||
private val edgeTtsApiManager = EdgeTtsApiManager(context, settingsRepository, ::handleSpeakingStateChanged)
|
||||
private val googleTtsApiManager = GoogleTtsApiManager(context, settingsRepository, ::handleSpeakingStateChanged)
|
||||
private var edgeTtsApiManager: EdgeTtsApiManager? = null
|
||||
private var googleTtsApiManager: GoogleTtsApiManager? = null
|
||||
|
||||
private fun getEdgeTtsApiManager(): EdgeTtsApiManager {
|
||||
return edgeTtsApiManager ?: EdgeTtsApiManager(
|
||||
context,
|
||||
settingsRepository,
|
||||
okHttpClient,
|
||||
::handleSpeakingStateChanged
|
||||
).also { edgeTtsApiManager = it }
|
||||
}
|
||||
|
||||
private fun getGoogleTtsApiManager(): GoogleTtsApiManager {
|
||||
return googleTtsApiManager ?: GoogleTtsApiManager(
|
||||
context,
|
||||
settingsRepository,
|
||||
okHttpClient,
|
||||
::handleSpeakingStateChanged
|
||||
).also { googleTtsApiManager = it }
|
||||
}
|
||||
|
||||
private val activeProvider: TtsApiProvider
|
||||
get() = SpeechConfig.ACTIVE_TTS_PROVIDER
|
||||
|
||||
private val currentManager: TtsManager
|
||||
get() = when (activeProvider) {
|
||||
TtsApiProvider.EDGE_TTS -> edgeTtsApiManager
|
||||
TtsApiProvider.GOOGLE_TTS -> googleTtsApiManager
|
||||
TtsApiProvider.EDGE_TTS -> getEdgeTtsApiManager()
|
||||
TtsApiProvider.GOOGLE_TTS -> getGoogleTtsApiManager()
|
||||
}
|
||||
|
||||
private fun handleSpeakingStateChanged(isSpeaking: Boolean) {
|
||||
|
|
@ -30,23 +50,27 @@ class ApiTtsManager(
|
|||
override fun speak(text: String, queueMode: Int) {
|
||||
// Stop the other manager to prevent overlapped audio if provider was changed dynamically
|
||||
when (activeProvider) {
|
||||
TtsApiProvider.EDGE_TTS -> googleTtsApiManager.stop()
|
||||
TtsApiProvider.GOOGLE_TTS -> edgeTtsApiManager.stop()
|
||||
TtsApiProvider.EDGE_TTS -> googleTtsApiManager?.stop()
|
||||
TtsApiProvider.GOOGLE_TTS -> edgeTtsApiManager?.stop()
|
||||
}
|
||||
currentManager.speak(text, queueMode)
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
edgeTtsApiManager.stop()
|
||||
googleTtsApiManager.stop()
|
||||
edgeTtsApiManager?.stop()
|
||||
googleTtsApiManager?.stop()
|
||||
}
|
||||
|
||||
override fun isSpeaking(): Boolean {
|
||||
return currentManager.isSpeaking()
|
||||
val manager = when (activeProvider) {
|
||||
TtsApiProvider.EDGE_TTS -> edgeTtsApiManager
|
||||
TtsApiProvider.GOOGLE_TTS -> googleTtsApiManager
|
||||
}
|
||||
return manager?.isSpeaking() ?: false
|
||||
}
|
||||
|
||||
override fun shutdown() {
|
||||
edgeTtsApiManager.shutdown()
|
||||
googleTtsApiManager.shutdown()
|
||||
edgeTtsApiManager?.shutdown()
|
||||
googleTtsApiManager?.shutdown()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap
|
|||
class EdgeTtsApiManager(
|
||||
private val context: Context,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
okHttpClient: OkHttpClient,
|
||||
private val onSpeakingStateChanged: (isSpeaking: Boolean) -> Unit
|
||||
) : TtsManager {
|
||||
|
||||
|
|
@ -43,7 +44,7 @@ class EdgeTtsApiManager(
|
|||
private var playbackJob: Job? = null
|
||||
private var idleTimeoutJob: Job? = null
|
||||
|
||||
private val client = OkHttpClient.Builder()
|
||||
private val client = okHttpClient.newBuilder()
|
||||
.connectTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
|
||||
.readTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
|
||||
.writeTimeout(5, java.util.concurrent.TimeUnit.SECONDS)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentHashMap
|
|||
class GoogleTtsApiManager(
|
||||
private val context: Context,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
okHttpClient: OkHttpClient,
|
||||
private val onSpeakingStateChanged: (isSpeaking: Boolean) -> Unit
|
||||
) : TtsManager {
|
||||
|
||||
|
|
@ -44,7 +45,7 @@ class GoogleTtsApiManager(
|
|||
private var generatorJob: Job? = null
|
||||
private var playbackJob: Job? = null
|
||||
|
||||
private val client = OkHttpClient.Builder()
|
||||
private val client = okHttpClient.newBuilder()
|
||||
.connectTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
|
||||
.readTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
|
||||
.writeTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
|
||||
|
|
|
|||
|
|
@ -7,43 +7,56 @@ import java.io.File
|
|||
class TtsEngineSelector(
|
||||
private val context: Context,
|
||||
private val settingsRepository: SettingsRepository,
|
||||
private val okHttpClient: okhttp3.OkHttpClient = com.app.assistant.viewmodel.MainViewModelFactory.okHttpClient,
|
||||
private val onSpeakingStateChanged: (isSpeaking: Boolean) -> Unit
|
||||
) : TtsManager {
|
||||
|
||||
private val nativeTtsManager = NativeTtsManager(context, onSpeakingStateChanged)
|
||||
private val offlineTtsManager = OfflineTtsManager(context, settingsRepository, onSpeakingStateChanged)
|
||||
private val apiTtsManager = ApiTtsManager(context, settingsRepository, onSpeakingStateChanged)
|
||||
private var nativeTtsManager: NativeTtsManager? = null
|
||||
private var offlineTtsManager: OfflineTtsManager? = null
|
||||
private var apiTtsManager: ApiTtsManager? = null
|
||||
|
||||
private fun getNativeTtsManager(): NativeTtsManager {
|
||||
return nativeTtsManager ?: NativeTtsManager(context, onSpeakingStateChanged).also { nativeTtsManager = it }
|
||||
}
|
||||
|
||||
private fun getOfflineTtsManager(): OfflineTtsManager {
|
||||
return offlineTtsManager ?: OfflineTtsManager(context, settingsRepository, onSpeakingStateChanged).also { offlineTtsManager = it }
|
||||
}
|
||||
|
||||
private fun getApiTtsManager(): ApiTtsManager {
|
||||
return apiTtsManager ?: ApiTtsManager(context, settingsRepository, okHttpClient, onSpeakingStateChanged).also { apiTtsManager = it }
|
||||
}
|
||||
|
||||
override fun speak(text: String, queueMode: Int) {
|
||||
val mode = settingsRepository.getTtsMode()
|
||||
|
||||
if (queueMode == TtsManager.QUEUE_FLUSH) {
|
||||
nativeTtsManager.stop()
|
||||
offlineTtsManager.stop()
|
||||
apiTtsManager.stop()
|
||||
nativeTtsManager?.stop()
|
||||
offlineTtsManager?.stop()
|
||||
apiTtsManager?.stop()
|
||||
}
|
||||
|
||||
when (mode) {
|
||||
TtsMode.OFFLINE -> {
|
||||
if (isOfflineModelInstalled()) {
|
||||
offlineTtsManager.speak(text, queueMode)
|
||||
getOfflineTtsManager().speak(text, queueMode)
|
||||
} else {
|
||||
nativeTtsManager.speak(text, queueMode)
|
||||
getNativeTtsManager().speak(text, queueMode)
|
||||
}
|
||||
}
|
||||
TtsMode.API -> {
|
||||
apiTtsManager.speak(text, queueMode)
|
||||
getApiTtsManager().speak(text, queueMode)
|
||||
}
|
||||
else -> {
|
||||
nativeTtsManager.speak(text, queueMode)
|
||||
getNativeTtsManager().speak(text, queueMode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
nativeTtsManager.stop()
|
||||
offlineTtsManager.stop()
|
||||
apiTtsManager.stop()
|
||||
nativeTtsManager?.stop()
|
||||
offlineTtsManager?.stop()
|
||||
apiTtsManager?.stop()
|
||||
}
|
||||
|
||||
override fun isSpeaking(): Boolean {
|
||||
|
|
@ -51,24 +64,24 @@ class TtsEngineSelector(
|
|||
return when (mode) {
|
||||
TtsMode.OFFLINE -> {
|
||||
if (isOfflineModelInstalled()) {
|
||||
offlineTtsManager.isSpeaking()
|
||||
offlineTtsManager?.isSpeaking() ?: false
|
||||
} else {
|
||||
nativeTtsManager.isSpeaking()
|
||||
nativeTtsManager?.isSpeaking() ?: false
|
||||
}
|
||||
}
|
||||
TtsMode.API -> {
|
||||
apiTtsManager.isSpeaking()
|
||||
apiTtsManager?.isSpeaking() ?: false
|
||||
}
|
||||
else -> {
|
||||
nativeTtsManager.isSpeaking()
|
||||
nativeTtsManager?.isSpeaking() ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun shutdown() {
|
||||
nativeTtsManager.shutdown()
|
||||
offlineTtsManager.shutdown()
|
||||
apiTtsManager.shutdown()
|
||||
nativeTtsManager?.shutdown()
|
||||
offlineTtsManager?.shutdown()
|
||||
apiTtsManager?.shutdown()
|
||||
}
|
||||
|
||||
private fun isOfflineModelInstalled(): Boolean {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue