Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Create a Voice-to-Text Feature in FlutterFlow

Implement voice-to-text in FlutterFlow using Custom Actions with the speech_to_text package. Create two actions: startListening initializes SpeechToText, checks availability, and calls listen() with an onResult callback that updates Page State with recognized words in real-time. stopListening calls stop() to end recognition. Add a mic button that toggles between listening and idle states, and bind a Text widget to the transcription Page State variable for live display.

What you'll learn

  • How to set up the speech_to_text package and microphone permissions
  • How to create startListening and stopListening Custom Actions
  • How to display live transcription results using Page State binding
  • How to handle availability checks and error states for speech recognition
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner6 min read20-25 minFlutterFlow Pro+ (Custom Actions required)March 2026RapidDev Engineering Team
TL;DR

Implement voice-to-text in FlutterFlow using Custom Actions with the speech_to_text package. Create two actions: startListening initializes SpeechToText, checks availability, and calls listen() with an onResult callback that updates Page State with recognized words in real-time. stopListening calls stop() to end recognition. Add a mic button that toggles between listening and idle states, and bind a Text widget to the transcription Page State variable for live display.

Adding Speech-to-Text Dictation in FlutterFlow

Voice-to-text lets users dictate instead of type, useful for search bars, note-taking, and accessibility. Since speech recognition is a background service (not a visual widget), it is implemented as Custom Actions in FlutterFlow. This tutorial covers the full setup including permissions, real-time transcription, and UI state management.

Prerequisites

  • FlutterFlow Pro plan or higher (Custom Actions required)
  • A FlutterFlow project open in the builder
  • Microphone permissions configured in app settings
  • A physical device for testing (speech recognition requires a microphone)

Step-by-step guide

1

Add the speech_to_text dependency and configure permissions

Go to Custom Code → Pubspec Dependencies and add speech_to_text with version ^6.6.0. In your FlutterFlow project settings, ensure microphone permission is enabled for both iOS and Android. For iOS, add the NSMicrophoneUsageDescription and NSSpeechRecognitionUsageDescription permission descriptions in the iOS settings. Speech recognition requires both microphone access and speech recognition authorization on iOS.

Expected result: The speech_to_text package is added and microphone permissions are configured for both platforms.

2

Create the startListening Custom Action with real-time updates

Go to Custom Code → Custom Actions → Add. Name it startListening. Set the return type to void. Add a parameter updateTranscription of type Action (callback). In the code, create a SpeechToText instance, call initialize() to check availability, then call listen() with onResult callback that invokes the updateTranscription callback passing result.recognizedWords. Set listenFor to Duration(seconds: 30) and pauseFor to Duration(seconds: 3) for automatic stop after silence.

start_listening.dart
1import 'package:speech_to_text/speech_to_text.dart';
2
3Future startListening(
4 Future Function(String text) updateTranscription,
5) async {
6 final speech = SpeechToText();
7 bool available = await speech.initialize(
8 onError: (error) => debugPrint('STT error: $error'),
9 onStatus: (status) => debugPrint('STT status: $status'),
10 );
11 if (!available) {
12 updateTranscription('Speech recognition not available on this device');
13 return;
14 }
15 speech.listen(
16 onResult: (result) {
17 updateTranscription(result.recognizedWords);
18 },
19 listenFor: const Duration(seconds: 30),
20 pauseFor: const Duration(seconds: 3),
21 listenMode: ListenMode.dictation,
22 );
23}

Expected result: The Custom Action initializes speech recognition and starts listening with real-time word updates.

3

Create the stopListening Custom Action

Create another Custom Action named stopListening. This action creates a SpeechToText instance and calls stop() to end the current listening session. Call this when the user taps the mic button again or navigates away from the page. Without explicitly stopping, the listener continues consuming battery in the background.

stop_listening.dart
1import 'package:speech_to_text/speech_to_text.dart';
2
3Future stopListening() async {
4 final speech = SpeechToText();
5 await speech.stop();
6}

Expected result: Speech recognition stops cleanly when called.

4

Build the voice input UI with mic button and live transcription display

On your page, add Page State variables: isListening (Boolean, default false) and transcriptionText (String, default empty). Add an IconButton with a mic icon. Use Conditional Styling: if isListening is true, show mic_off icon with red color; if false, show mic icon with default color. Bind On Tap to an action flow: if not listening → set isListening true → call startListening Custom Action (pass a callback that updates transcriptionText) → else → set isListening false → call stopListening. Below the button, add a Text widget bound to transcriptionText.

Expected result: Tapping the mic button starts listening and shows recognized words in real-time below the button.

5

Add the transcription result to a TextField for editing

Instead of just displaying the text, bind the transcription to a TextField's initial value so users can edit the result after dictation. On the startListening callback, update both the Page State variable and the TextField's controller value. After stopping, the user sees the dictated text in an editable field and can correct any recognition errors before submitting the form. This makes voice-to-text practical for forms, search, and notes.

Expected result: Dictated text appears in an editable TextField that users can review and modify.

Complete working example

start_listening.dart
1import 'package:speech_to_text/speech_to_text.dart';
2import 'package:speech_to_text/speech_recognition_result.dart';
3import 'package:speech_to_text/speech_recognition_error.dart';
4
5/// Custom Action: Start listening for speech and update transcription
6/// via callback in real-time.
7Future startListening(
8 Future Function(String text) updateTranscription,
9) async {
10 final speech = SpeechToText();
11
12 bool available = await speech.initialize(
13 onError: (SpeechRecognitionError error) {
14 debugPrint('Speech recognition error: ${error.errorMsg}');
15 if (error.permanent) {
16 updateTranscription(
17 'Speech recognition error. Please check permissions.',
18 );
19 }
20 },
21 onStatus: (String status) {
22 debugPrint('Speech recognition status: $status');
23 },
24 );
25
26 if (!available) {
27 await updateTranscription(
28 'Speech recognition is not available on this device.',
29 );
30 return;
31 }
32
33 await speech.listen(
34 onResult: (SpeechRecognitionResult result) {
35 updateTranscription(result.recognizedWords);
36 },
37 listenFor: const Duration(seconds: 30),
38 pauseFor: const Duration(seconds: 3),
39 listenMode: ListenMode.dictation,
40 cancelOnError: false,
41 partialResults: true,
42 );
43}
44
45/// Custom Action: Stop listening
46Future stopListening() async {
47 final speech = SpeechToText();
48 await speech.stop();
49}

Common mistakes when creating a Voice-to-Text Feature in FlutterFlow

Why it's a problem: Not checking speech.isAvailable before calling listen()

How to avoid: Always call speech.initialize() first and check the returned boolean. Show a user-friendly message if not available.

Why it's a problem: Forgetting to stop the listener when navigating away from the page

How to avoid: Call stopListening in the page's On Page Dispose action trigger or in the dispose method of any wrapping Custom Widget.

Why it's a problem: Not requesting both microphone and speech recognition permissions on iOS

How to avoid: Add both permission descriptions in your FlutterFlow iOS settings. The speech_to_text package prompts for both on first use.

Best practices

  • Always check speech.isAvailable before starting recognition to handle unsupported devices
  • Show a visual indicator (red recording dot, pulsing animation) when actively listening
  • Stop the speech listener on page disposal to prevent background resource consumption
  • Set partialResults to true for real-time word-by-word transcription display
  • Provide an editable TextField for the result so users can correct recognition errors
  • Use listenMode: ListenMode.dictation for free-form text and ListenMode.search for short queries
  • Request microphone and speech recognition permissions early in the app lifecycle

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

Write two FlutterFlow Custom Actions in Dart for speech-to-text using the speech_to_text package: startListening that initializes STT and updates a callback with recognized words in real-time, and stopListening that cleanly ends recognition. Include error handling and availability checks.

FlutterFlow Prompt

Add a mic icon button to my page. When tapped, it should change to a stop icon with red color. Add a text area below to display voice transcription results.

Frequently asked questions

Does speech-to-text work offline?

On iOS, speech recognition requires an internet connection by default. On Android, some languages have offline models that can be downloaded. The speech_to_text package uses the platform's built-in engine.

What languages are supported?

All languages supported by the device's speech engine. Call speech.locales() to get the list of available locales and pass the localeId to listen() for non-English recognition.

How accurate is the transcription?

Accuracy depends on the device's speech engine, background noise, and speaking clarity. Modern iOS and Android engines achieve 90-95% accuracy for clear speech in supported languages.

Can I use voice-to-text in the FlutterFlow web build?

Yes, but with limitations. Web uses the Web Speech API which is supported in Chrome and Edge but not in all browsers. It requires a secure context (HTTPS).

How do I handle continuous long-form dictation?

Set listenFor to a long duration (120 seconds) and listenMode to ListenMode.dictation. When the listener stops (after pauseFor silence), auto-restart it. Concatenate results in your Page State.

Can RapidDev help build voice-powered features?

Yes. RapidDev can implement voice commands, voice search, continuous dictation with auto-restart, and integration with external speech APIs for higher accuracy.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.