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

How to Integrate Voice-to-Text Capabilities in FlutterFlow

Add speech-to-text to FlutterFlow using Custom Actions with the speech_to_text package. Build three patterns: voice-fill for form fields (mic icon suffix on TextField that dictates into the field), voice search (mic button on search bar that triggers a query on final result), and voice notes (record, transcribe, and save to Firestore). Configure localeId for multi-language support and choose between one-shot listening (stops after silence) and continuous mode (keeps listening until manually stopped). Always stop the listener on page dispose.

What you'll learn

  • How to create startListening and stopListening Custom Actions using the speech_to_text package
  • How to build a voice-fill TextField pattern with a mic icon suffix that dictates into the field
  • How to implement voice search with a mic button that triggers search on final recognition result
  • How to configure localeId for multi-language recognition and stop the listener on page dispose
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner6 min read25-35 minFlutterFlow Pro+ (Custom Actions required)March 2026RapidDev Engineering Team
TL;DR

Add speech-to-text to FlutterFlow using Custom Actions with the speech_to_text package. Build three patterns: voice-fill for form fields (mic icon suffix on TextField that dictates into the field), voice search (mic button on search bar that triggers a query on final result), and voice notes (record, transcribe, and save to Firestore). Configure localeId for multi-language support and choose between one-shot listening (stops after silence) and continuous mode (keeps listening until manually stopped). Always stop the listener on page dispose.

Adding Voice Dictation to Forms, Search, and Notes in FlutterFlow

Voice input improves accessibility and speed for mobile users. This tutorial builds three voice-to-text patterns — form field dictation, search by voice, and voice notes — using the speech_to_text package in Custom Actions with multi-language support and proper lifecycle management.

Prerequisites

  • A FlutterFlow project on the Pro plan (Custom Actions required)
  • speech_to_text package added to Pubspec Dependencies
  • Microphone permission configured in iOS Info.plist (NSMicrophoneUsageDescription) and Android manifest
  • A physical device or emulator with microphone support for testing

Step-by-step guide

1

Add speech_to_text to Pubspec and create the startListening Custom Action

Add speech_to_text: ^6.6.0 to Pubspec Dependencies. Create a Custom Action named startListening with parameters: localeId (String, default 'en_US'), onResult (Action Parameter callback returning String). Inside: create a SpeechToText instance, call initialize(). Check speech.isAvailable — if false, show a SnackBar 'Speech recognition not available on this device' and return. Call speech.listen(onResult: (result) { onResult(result.recognizedWords); }, localeId: localeId, listenMode: ListenMode.dictation) for continuous mode. Store the SpeechToText instance in a global variable so stopListening can access it.

Expected result: Calling startListening begins speech recognition and streams recognized text to the callback in real time.

2

Create the stopListening Custom Action and handle page dispose cleanup

Create a Custom Action named stopListening that calls speech.stop() on the stored SpeechToText instance. Also create a disposeSpeech Custom Action that calls speech.cancel() for use in page cleanup. On the page that uses voice input, add an On Page Dispose action trigger that calls disposeSpeech. This prevents the microphone from staying active after the user navigates away, which would drain battery and cause recording indicators to persist.

Expected result: Calling stopListening ends the current session. Navigating away automatically cancels any active speech recognition.

3

Build the voice-fill TextField pattern with mic IconButton suffix

On a form page, add a TextField (e.g., 'Description') with a suffixIcon: IconButton. The icon shows mic when Page State isListening is false, and mic_off (red) when true. On IconButton tap: if not listening → set isListening true → call startListening(localeId: selectedLocale, onResult: (text) { update TextField value to text }). If listening → call stopListening → set isListening false. The recognized text fills the TextField in real time as the user speaks. This pattern works on any TextField — address, notes, message, etc.

Expected result: Tapping the mic icon starts recording. Spoken words appear in the TextField in real time. Tapping again stops recording.

4

Build the voice search pattern with mic button on the search bar

On a search page, add a Row: Expanded TextField (hintText: 'Search...', prefixIcon: search) + IconButton (mic, primary color). On the mic button tap, call startListening with a modified callback: on each result, update the search TextField text. When the speech_to_text result has result.finalResult == true (user stopped speaking), automatically call stopListening and trigger the search action (e.g., navigate to results page or filter a ListView). Show a pulsing red dot Container next to the mic icon while listening to indicate active recording.

Expected result: Tapping the mic icon lets the user speak their search query. When they stop speaking, the search executes automatically.

5

Add multi-language support with a locale DropDown and implement voice notes save-to-Firestore

Add a DropDown widget above the form with language options: English (en_US), Spanish (es_ES), French (fr_FR), German (de_DE). Bind it to a Page State selectedLocale variable. Pass selectedLocale as the localeId parameter to startListening. For voice notes: add a dedicated section with a large mic FloatingActionButton, a Text widget bound to Page State transcriptionText showing live transcription, and a Save Button. On Save tap, create a Firestore document in voice_notes collection: text (transcriptionText), createdAt (Timestamp.now()), language (selectedLocale), userId (currentUser.uid). Clear transcriptionText after save.

Expected result: Users select a language, dictate in that language, see the transcription live, and save voice notes to Firestore.

Complete working example

Voice-to-Text Custom Actions
1// Custom Action: startListening
2// Pubspec: speech_to_text: ^6.6.0
3
4import 'package:speech_to_text/speech_to_text.dart' as stt;
5
6// Global instance for cross-action access
7stt.SpeechToText? _speech;
8
9Future<void> startListening({
10 String localeId = 'en_US',
11 required Future Function(String text) onResult,
12}) async {
13 _speech = stt.SpeechToText();
14 final available = await _speech!.initialize(
15 onError: (error) => print('STT error: ${error.errorMsg}'),
16 );
17
18 if (!available) {
19 // Show SnackBar: 'Speech recognition not available'
20 return;
21 }
22
23 _speech!.listen(
24 onResult: (result) {
25 onResult(result.recognizedWords);
26 },
27 localeId: localeId,
28 listenMode: stt.ListenMode.dictation, // continuous
29 // Use stt.ListenMode.search for one-shot (stops after silence)
30 );
31}
32
33// Custom Action: stopListening
34Future<void> stopListening() async {
35 await _speech?.stop();
36}
37
38// Custom Action: disposeSpeech (call on page dispose)
39Future<void> disposeSpeech() async {
40 await _speech?.cancel();
41 _speech = null;
42}
43
44// Custom Function: getAvailableLocales
45// Returns list of supported languages
46Future<List<Map<String, String>>> getAvailableLocales() async {
47 final speech = stt.SpeechToText();
48 await speech.initialize();
49 final locales = await speech.locales();
50 return locales.map((l) => {
51 'id': l.localeId,
52 'name': l.name,
53 }).toList();
54}

Common mistakes

Why it's a problem: Not stopping the speech listener when the user navigates away from the page

How to avoid: Call speech.cancel() in the page's On Page Dispose action trigger. This ensures the listener stops regardless of how the user leaves the page.

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

How to avoid: Always call initialize() first, check the returned boolean. If false, show a user-friendly message and fall back to manual text input.

Why it's a problem: Using ListenMode.search when the user needs continuous dictation for long text

How to avoid: Use ListenMode.dictation for form fields and notes where users speak multiple sentences. Use ListenMode.search only for short search queries where auto-stop is desired.

Best practices

  • Always call speech.cancel() on page dispose to release the microphone and stop background recording
  • Check speech.isAvailable before calling listen() and show a fallback message on unsupported devices
  • Use ListenMode.dictation for long-form input and ListenMode.search for short queries that should auto-stop
  • Show a visual recording indicator (pulsing red dot or red mic icon) so users know the mic is active
  • Store the SpeechToText instance globally so both startListening and stopListening can access it
  • Pass localeId to support multiple languages — do not hardcode to English only
  • Debounce the onResult callback when updating search queries to avoid triggering searches on every partial word

Still stuck?

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

ChatGPT Prompt

I want to add voice-to-text to FlutterFlow form fields and search bars using the speech_to_text package. Show me Custom Actions for startListening and stopListening, the voice-fill TextField suffix pattern, multi-language localeId support, and how to stop the listener on page dispose.

FlutterFlow Prompt

Add a microphone icon button to the right side of a text field. When tapped, it should start recording speech and fill the text field with what the user says. Add another tap to stop recording.

Frequently asked questions

Which languages does speech_to_text support?

It depends on the device. Call speech.locales() after initialization to get the list of supported languages. Most iOS and Android devices support 30+ languages including English, Spanish, French, German, Chinese, Japanese, and Arabic.

Can I use voice-to-text on FlutterFlow web projects?

Partially. The speech_to_text package uses the Web Speech API on Chrome-based browsers. It works on Chrome desktop and Android Chrome but does not work on Safari or Firefox.

How do I handle noisy environments where recognition is poor?

Show the partial transcription in real time so users can see what was recognized and correct it. Add a clear button to restart dictation. There is no way to improve accuracy from the app side — it depends on the device's speech engine.

What is the difference between continuous and one-shot listening modes?

ListenMode.dictation (continuous) keeps listening until you call stop(), good for long-form text. ListenMode.search (one-shot) automatically stops after a brief silence, good for short search queries.

Can I use voice-to-text offline without internet?

On iOS, speech recognition requires internet by default but supports offline mode for downloaded languages in iOS 13+. On Android, offline recognition is available if the language pack is downloaded in device settings.

Can RapidDev help build voice-powered features for my app?

Yes. RapidDev can implement voice search, voice commands, real-time transcription, multi-language dictation, voice-to-text with AI post-processing, and speech-based navigation.

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.