Jetpark Compose 语音模块

简介

在 Jetpark Compose 中添加语音功能

主体代码

import android.content.Context
import android.speech.tts.TextToSpeech
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalContext
import java.util.*

/**
 * 用于在 Jetpack Compose 中实现文本转语音功能的可组合函数。
 *
 * @param textToSpeak 要朗读的文本内容。
 * @param autoPlay 是否在初始化完成后自动播放文本,默认为 false。
 * @param language 语音的语言设置,默认为设备的默认语言。
 * @param onError 当出现错误时调用的回调函数。
 */
@Composable
fun TextToSpeechModule(
    textToSpeak: String,
    autoPlay: Boolean = false,
    language: Locale = Locale.getDefault(),
    onError: (String) -> Unit = {}
) {
    // 获取当前的上下文
    val context = LocalContext.current
    // 存储 TextToSpeech 实例
    var tts by remember { mutableStateOf<TextToSpeech?>(null) }
    // 标记 TTS 是否准备好
    var isReady by remember { mutableStateOf(false) }

    // TTS 初始化
    DisposableEffect(Unit) {
        // 创建 TextToSpeech 实例
        tts = TextToSpeech(context) { status ->
            if (status == TextToSpeech.SUCCESS) {
                // 设置语音语言
                when (tts?.setLanguage(language)) {
                    TextToSpeech.LANG_MISSING_DATA -> 
                        // 语言数据缺失时调用错误回调
                        onError("Missing language data")
                    TextToSpeech.LANG_NOT_SUPPORTED -> 
                        // 语言不支持时调用错误回调
                        onError("Language not supported")
                    else -> 
                        // 其他情况表示准备就绪
                        isReady = true
                }
            } else {
                // TTS 初始化失败时调用错误回调
                onError("TTS initialization failed")
            }
        }
        // 在组件销毁时停止并关闭 TTS
        onDispose {
            tts?.stop()
            tts?.shutdown()
        }
    }

    // 自动播放逻辑
    if (autoPlay && isReady) {
        // 当 textToSpeak 改变时触发朗读
        LaunchedEffect(textToSpeak) {
            tts?.speak(textToSpeak, TextToSpeech.QUEUE_FLUSH, null, null)
        }
    }
}

/**
 * 用于控制文本转语音功能的控制器类。
 */
class TtsController {
    // 存储 TextToSpeech 实例
    var tts: TextToSpeech? = null

    /**
     * 开始朗读指定的文本。
     *
     * @param text 要朗读的文本。
     */
    fun speak(text: String) {
        tts?.speak(text, TextToSpeech.QUEUE_FLUSH, null, null)
    }

    /**
     * 停止当前的朗读。
     */
    fun stop() {
        tts?.stop()
    }
}

/**
 * 用于在 Jetpack Compose 中记住并初始化 TtsController 实例的可组合函数。
 *
 * @param language 语音的语言设置,默认为设备的默认语言。
 * @param onError 当出现错误时调用的回调函数。
 * @return 返回初始化好的 TtsController 实例。
 */
@Composable
fun rememberTtsController(
    language: Locale = Locale.getDefault(),
    onError: (String) -> Unit = {}
): TtsController {
    // 获取当前的上下文
    val context = LocalContext.current
    // 创建并记住 TtsController 实例
    val controller = remember { TtsController() }

    DisposableEffect(Unit) {
        // 初始化 TtsController 中的 TextToSpeech 实例
        controller.tts = TextToSpeech(context) { status ->
            if (status == TextToSpeech.SUCCESS) {
                // 设置语音语言
                when (controller.tts?.setLanguage(language)) {
                    TextToSpeech.LANG_MISSING_DATA -> 
                        // 语言数据缺失时调用错误回调
                        onError("Missing language data")
                    TextToSpeech.LANG_NOT_SUPPORTED -> 
                        // 语言不支持时调用错误回调
                        onError("Language not supported")
                    else -> 
                        Unit
                }
            } else {
                // TTS 初始化失败时调用错误回调
                onError("TTS initialization failed")
            }
        }
        // 在组件销毁时停止并关闭 TTS
        onDispose {
            controller.tts?.stop()
            controller.tts?.shutdown()
            controller.tts = null
        }
    }

    return controller
}

使用方法

方式一:自动播放(文本变化时触发)

@Composable
fun AutoPlayExample() {
    var speechText by remember { mutableStateOf("Initial text") }
    
    TextToSpeechModule(
        textToSpeak = speechText,
        autoPlay = true,
        language = Locale.US,
        onError = { error -> Log.e("TTS", error) }
    )

    Button(onClick = { speechText = "New text to speak" }) {
        Text("Update Text")
    }
}

方式二:手动控制播放

@Composable
fun ManualControlExample() {
    val ttsController = rememberTtsController(
        language = Locale.UK,
        onError = { error -> Toast.makeText(context, error, Toast.LENGTH_SHORT).show() }
    )
    var inputText by remember { mutableStateOf("") }

    Column {
        TextField(
            value = inputText,
            onValueChange = { inputText = it }
        )
        
        Button(onClick = { ttsController.speak(inputText) }) {
            Text("Play")
        }
        
        Button(onClick = { ttsController.stop() }) {
            Text("Stop")
        }
    }
}

主要特性:

1. ​模块化设计:

提供两种使用模式:自动播放和手动控制
封装底层TextToSpeech的生命周期管理
​灵活参数:

textToSpeak: String  // 需要播报的文本
autoPlay: Boolean    // 是否自动播放(默认false)
language: Locale     // 语言设置(默认系统语言)
onError: (String) -> Unit // 错误回调

2. 增强功能:

自动处理文本更新(通过LaunchedEffect监听textToSpeak变化)
支持语音队列管理(QUEUE_FLUSH会中断当前播报)
提供停止播放的方法

3. 内存安全:

使用DisposableEffect自动释放资源
防止内存泄漏的销毁逻辑

4. ​扩展性:

可轻松添加语速/音调控制:

tts?.setSpeechRate(0.8f) // 语速(0.5-2.0)
tts?.setPitch(1.2f)     // 音调(0.5-2.0)

使用建议:

​长文本处理:

// 分割长文本避免内存问题
fun speakLongText(controller: TtsController, text: String) {
    text.split("\n").forEach { 
        controller.speak(it, TextToSpeech.QUEUE_ADD, null, null) 
    }
}

​多语言支持:

TextToSpeechModule(
    textToSpeak = "こんにちは",
    language = Locale.JAPANESE
)

​音频焦点管理​(可选增强):

val audioAttributes = AudioAttributes.Builder()
    .setUsage(AudioAttributes.USAGE_MEDIA)
    .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
    .build()

tts?.setAudioAttributes(audioAttributes)

这个模块化实现可以在多个Composable中复用,同时保持业务逻辑与语音功能的解耦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值