@@ -219,25 +219,56 @@ data class MessageData(
219219### SpeechToTextButton
220220
221221` SpeechToTextButton ` provides speech-to-text functionality with animated waveform visualization
222- and automatic permission handling. When not recording, it displays a microphone icon button.
223- When recording, it transforms into a circular button with animated bars that respond to voice input.
222+ and automatic permission handling. Clicking the button toggles recording on and off. When not recording,
223+ it displays a microphone icon button. When recording, it transforms into a circular button with animated
224+ bars that respond to voice input levels.
224225
225226** Basic Usage:**
226227
227228``` kotlin
228229import io.getstream.chat.android.ai.compose.ui.component.SpeechToTextButton
230+ import io.getstream.chat.android.ai.compose.ui.component.rememberSpeechToTextButtonState
229231
230232@Composable
231233fun MyComposer () {
232234 var text by remember { mutableStateOf(" " ) }
233235
234- SpeechToTextButton (
235- onTextRecognized = { recognizedText ->
236- // Called with partial results as user speaks
237- // At the end this callback is invoked with the full recognized text
236+ val speechState = rememberSpeechToTextButtonState(
237+ onFinalResult = { recognizedText ->
238+ // Called with the final result when recording stops
238239 text = recognizedText
239240 }
240241 )
242+
243+ SpeechToTextButton (
244+ state = speechState
245+ )
246+ }
247+ ```
248+
249+ ** Usage with Real-time Streaming:**
250+
251+ ``` kotlin
252+ @Composable
253+ fun MyComposer () {
254+ var text by remember { mutableStateOf(" " ) }
255+
256+ val speechState = rememberSpeechToTextButtonState(
257+ onPartialResult = { partialText ->
258+ // Called with partial results as user speaks (real-time streaming)
259+ // This updates continuously as speech is detected
260+ text = partialText
261+ },
262+ onFinalResult = { finalText ->
263+ // Called with the final result when recording stops
264+ // This is the complete, finalized transcription
265+ text = finalText
266+ }
267+ )
268+
269+ SpeechToTextButton (
270+ state = speechState
271+ )
241272}
242273```
243274
@@ -249,29 +280,39 @@ import io.getstream.chat.android.ai.compose.ui.component.rememberSpeechToTextBut
249280
250281@Composable
251282fun MyComposer () {
252- val speechState = rememberSpeechToTextButtonState()
253283 var text by remember { mutableStateOf(" " ) }
254284
255285 // Remember the text that existed before starting speech recognition
256- val textBeforeSpeech = remember { mutableStateOf(" " ) }
286+ var textBeforeSpeech by remember { mutableStateOf(" " ) }
287+
288+ val speechState = rememberSpeechToTextButtonState(
289+ onPartialResult = { partialText ->
290+ // Update with partial results in real-time
291+ text = if (textBeforeSpeech.isBlank()) {
292+ partialText
293+ } else {
294+ " $textBeforeSpeech $partialText "
295+ }
296+ },
297+ onFinalResult = { finalText ->
298+ // Append final recognized text after the text which is already in the composer
299+ text = if (textBeforeSpeech.isBlank()) {
300+ finalText
301+ } else {
302+ " $textBeforeSpeech $finalText "
303+ }
304+ }
305+ )
257306
258307 // Capture text when recording starts
259308 LaunchedEffect (speechState.isRecording()) {
260309 if (speechState.isRecording()) {
261- textBeforeSpeech.value = text
310+ textBeforeSpeech = text
262311 }
263312 }
264313
265314 SpeechToTextButton (
266- state = speechState,
267- onTextRecognized = { recognizedText ->
268- // Append recognized text after the text which is already in the composer
269- text = if (textBeforeSpeech.value.isBlank()) {
270- recognizedText
271- } else {
272- " ${textBeforeSpeech.value} $recognizedText "
273- }
274- }
315+ state = speechState
275316 )
276317
277318 // Check if currently recording
@@ -281,17 +322,61 @@ fun MyComposer() {
281322}
282323```
283324
325+ ** Customization:**
326+
327+ ``` kotlin
328+ val speechState = rememberSpeechToTextButtonState(
329+ onPartialResult = { partialText ->
330+ // Handle partial results (optional)
331+ },
332+ onFinalResult = { finalText ->
333+ // Handle final result
334+ }
335+ )
336+
337+ SpeechToTextButton (
338+ state = speechState,
339+ idleContent = { onClick ->
340+ // Custom content when not recording
341+ IconButton (onClick = onClick) {
342+ Icon (Icons .Default .Mic , " Voice input" )
343+ }
344+ },
345+ recordingContent = { onClick, rmsdB ->
346+ // Custom content when recording
347+ // rmsdB is the current audio level (0-10) for visualization
348+ IconButton (onClick = onClick) {
349+ // Your custom recording visualization
350+ }
351+ }
352+ )
353+ ```
354+
284355** Features:**
356+ - Click to toggle recording on/off
285357- Automatic audio permission requests (RECORD_AUDIO)
286- - Animated waveform visualization during recording
287- - Real-time streaming of recognized text (partial results)
358+ - Animated waveform visualization during recording that responds to audio levels
359+ - Real-time streaming of recognized text (partial results as speech is detected)
360+ - Final result callback when recording stops
288361- Automatic UI transformation between idle and recording states
289362- State tracking for recording status
290363
291364** Parameters:**
292365- ` modifier ` : Modifier to be applied to the root container
293- - ` state ` : Optional state holder for tracking recording status (defaults to remembered state)
294- - ` onTextRecognized ` : Callback invoked with each partial result as speech is detected
366+ - ` state ` : Optional state holder for tracking recording status and receiving recognized text.
367+ Defaults to a remembered state with an empty callback. To receive text, create a state using
368+ ` rememberSpeechToTextButtonState ` with your callbacks and pass it here.
369+ - ` idleContent ` : The composable content to display when not recording. Receives an onClick callback
370+ that toggles recording. Defaults to a microphone icon button.
371+ - ` recordingContent ` : The composable content to display when recording. Receives an onClick callback
372+ that stops recording and the current audio level (rmsdB) for visualization. Defaults to animated bars.
373+
374+ ** rememberSpeechToTextButtonState Parameters:**
375+ - ` onPartialResult ` : Optional callback invoked when text chunks are recognized during recording.
376+ Called with each partial result as speech is detected, enabling real-time text streaming.
377+ Use this to update your UI in real-time as the user speaks.
378+ - ` onFinalResult ` : Required callback invoked when the final result is available after recording stops.
379+ Called with the complete, finalized transcription. This is the definitive result of the speech recognition.
295380
296381** SpeechToTextButtonState API:**
297382
0 commit comments