Jetpack Compose Glimmer 中的语音输入指示器

适用的 XR 设备
本指南可帮助您为以下类型的 XR 设备打造优质体验。
显示眼镜

VoiceInputIndicator 是一个 Jetpack Compose Glimmer 组件,用于向用户显示声音活动。您可以使用此组件接受语音输入或其他音频,并提供视觉反馈来表明您的应用正在捕获音频。

此组件纯粹是一个视觉元素。它本身不会录制音频或处理麦克风数据。而是会响应应用提供的音频 level ,该 会直观地显示音频强度。

图 1. VoiceInputIndicator 示例。

请求投影权限

如需捕获音频数据来驱动指示器,您的应用需要 Manifest.permission.RECORD_AUDIO 权限。

为有屏眼镜构建增强现实体验时,请确保在设备和眼镜上正确请求权限。使用 ProjectedActivityCompat.requestPermissions 提示用户。

如需详细了解如何在投影环境中请求权限,请参阅请求硬件权限。

录制和标准化音频

VoiceInputIndicator 需要一个介于 0.0f 和 1.0f 之间的 Float,以直观反映音频强度。由于它纯粹作为视觉组件运行,不会捕获音频,因此您的应用必须主动监控麦克风,并将音量流式传输到指示器的 level 参数。

虽然有多种方法可以捕获音频数据,但其中一种方法是使用 SpeechRecognizer API。使用 SpeechRecognizer 时,您可以使用 RecognitionListener.onRmsChanged 回调来捕获实时音量更新,该回调会以分贝 (rmsdB) 为单位提供音频级别。

由于此原始值通常介于 0 到 10 之间,因此您必须将输出归一化为所需的 0.0f 到 1.0f 范围。您可以将此标准化音量保存在状态变量中,以便持续更新指示器。

以下示例使用 RecognitionListener 更新状态变量:

// Example state variable to hold the normalized level (0.0 to 1.0)
// that the VoiceInputIndicator component expects.
val audioLevel = MutableStateFlow(0f)

// Initialize the Android SpeechRecognizer
val speechRecognizer = SpeechRecognizer.createSpeechRecognizer(context)

// Listener to capture speech events and audio level changes
val listener = object : RecognitionListener {
    override fun onRmsChanged(rmsdB: Float) {
        // Normalize raw dB level to a 0.0-1.0 range.
        // Android SpeechRecognizer's rmsdB typically ranges from 0 to ~10.
        audioLevel.value = ((rmsdB - 1f) / 9f).coerceIn(0f, 1f)
    }

    // ... Implement other required RecognitionListener methods ...
    override fun onReadyForSpeech(params: Bundle?) {}
    override fun onBeginningOfSpeech() {}
    override fun onEndOfSpeech() {}
    override fun onError(error: Int) {}
    override fun onResults(results: Bundle?) {}
    override fun onPartialResults(partialResults: Bundle?) {}
    override fun onEvent(eventType: Int, params: Bundle?) {}
    override fun onBufferReceived(buffer: ByteArray?) {}
}

// Attach the listener to the recognizer
speechRecognizer.setRecognitionListener(listener)

// Create an intent to specify the recognition model and behavior
val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
    putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
}
// Begin listening for audio input
speechRecognizer.startListening(intent)

集成语音输入指示器

在音频串流正确标准化并作为状态公开后,您可以将其直接传递到 VoiceInputIndicator。

@Composable
fun VoiceInputExample(modifier: Modifier) {
    // Collect the flow as Compose State so the UI reacts to changes in real-time.
    val currentLevel by audioLevel.collectAsState()

    VoiceInputIndicator(
        // The VoiceInputIndicator component provides a visual "pulse" or indicator
        // that changes based on the 'level' lambda, which returns a Float between 0.0 and 1.0.
        level = { currentLevel },
        modifier = modifier
    )
}

自定义参数

VoiceInputIndicator 提供了几个参数,用于自定义其行为和外观:

  • level:一个返回 Float 的函数,该值表示语音输入的音量,范围从 0.0(静音)到 1.0(最大音量)。
  • indicatorColor:指示条的颜色。默认情况下,此属性使用 Glimmer 主题中的主要颜色;请参阅 GlimmerTheme.colors.primary。
  • modifier:要应用于指示器的标准 Compose modifier。

如果您的界面要求指示器位于可见的背景容器中,请使用 ContainedVoiceInputIndicator。此替代方案可确保指示条是透明的,从而让背景容器能够显露出来。