Skip to main content
RapidDev - Software Development Agency
App Featuresai-features18 min read

How to Add Voice Search to Your App — Copy-Paste Prompts Included

Voice search needs three pieces: a microphone button that requests permission, a speech-to-text engine (Web Speech API for zero cost on Chrome/Safari, OpenAI Whisper for Firefox/multilingual accuracy), and a handler that feeds the transcript into your existing search pipeline as if the user had typed it. With Lovable or V0 you can ship a working voice search in 3–5 hours for $0/month — the Web Speech API is free, and Whisper fallback costs pennies at typical usage volumes.

4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members

Feature spec

Intermediate

Category

ai-features

Build with AI

3–5 hours with Lovable or V0

Custom build

3–7 days custom dev

Running cost

$0/mo for Web Speech API path; $0–15/mo at 1K users with Whisper fallback

Works on

WebMobile

Everything it takes to ship Voice Search — parts, prompts, and real costs.

TL;DR

Voice search needs three pieces: a microphone button that requests permission, a speech-to-text engine (Web Speech API for zero cost on Chrome/Safari, OpenAI Whisper for Firefox/multilingual accuracy), and a handler that feeds the transcript into your existing search pipeline as if the user had typed it. With Lovable or V0 you can ship a working voice search in 3–5 hours for $0/month — the Web Speech API is free, and Whisper fallback costs pennies at typical usage volumes.

What Voice Search Actually Is

Voice search is a microphone button layered on top of your existing search feature. Users tap the mic, speak their query, and the app submits it as if they had typed it — the search results are identical. The speech input is handled by the browser's SpeechRecognition API (Web Speech API) for zero cost on Chrome and Safari, or by OpenAI Whisper for broader browser support and higher accuracy in noisy environments or non-English queries. The product decisions are: whether to auto-submit on speech pause or show the transcript first for editing, how to handle mic permission denial gracefully, and whether you need the Whisper fallback for Firefox users. Voice search does not require a new search pipeline — it feeds the existing one.

What users consider table stakes in 2026

  • Microphone button always visible in the search bar — not behind a settings screen or secondary navigation
  • Visual waveform or pulsing ring animation during active listening, so users know the mic is on
  • Automatic submission when speech pauses — no manual tap needed to confirm the query
  • Fallback text input with a clear error message when mic permission is denied, with browser-specific instructions for re-enabling
  • Search results identical to what the same text typed manually would return — voice is just an input method
  • Clear error state with a retry button when speech is not recognized or the transcript is empty

Anatomy of the Feature

Six components, none of which require a new backend search system. Voice search routes the transcript into your existing search. The permission handler and the Firefox fallback are where builds actually fail.

Layers:UIBackendService

Mic Button

UI

An icon button positioned inside the search bar (not beside it). On click, triggers getUserMedia() to request microphone permission on web, or the microphone_access Flutter permission dialog on mobile. Shows a pulsing animated ring while SpeechRecognition is active. Returns to the mic icon when recognition stops.

Note: Minimum touch target: 44×44px on mobile. The button must be inside the search bar container, not a floating element, so users associate it with search input.

Web Speech API Layer

Service

The SpeechRecognition API (window.webkitSpeechRecognition on Chrome, window.SpeechRecognition standard). Configure with interimResults: true to show live transcript as the user speaks. The onresult event fires with each recognized word; isFinal: true on the last result triggers search submission. The onend event auto-restarts if the user is still speaking.

Note: Firefox does not implement SpeechRecognition as of 2026. Check for both window.SpeechRecognition and window.webkitSpeechRecognition at runtime and route Firefox users to the Whisper fallback.

Speech-to-Text Backend (premium/fallback)

Backend

A Supabase Edge Function that receives an audio blob from the client (recorded via MediaRecorder API), calls OpenAI Whisper (/v1/audio/transcriptions) with the audio file, and returns the transcript as JSON. Used for Firefox users, multilingual queries, or high-accuracy requirements where Web Speech API's accuracy is insufficient.

Note: The Edge Function accepts multipart/form-data with the audio file and language hint. The OPENAI_API_KEY lives in Cloud tab → Secrets. Record audio at 16kHz, mono channel for best Whisper accuracy at minimum file size.

Live Transcript Display

UI

Shows interim results (greyed text) in the search bar input field as the user speaks. When the final result fires, replaces the greyed text with confirmed black text. The cursor is moved to the end of the confirmed transcript. This provides visual feedback that the mic is hearing the user.

Note: Replace the search input's value, not a separate element. The voice transcript and manual typing should be interchangeable — users should be able to start with voice and refine by typing.

Search Query Router

Backend

The transcript string is passed directly to the existing search function — Supabase full-text search with to_tsvector, Algolia, or whatever the app already uses. Voice search adds zero new search logic. The transcript must be normalized before submission: trimmed, lowercased, trailing periods and question marks removed.

Note: Normalization is critical. 'Show me running shoes.' typed into a full-text search returns different results than 'show me running shoes' — punctuation can break query parsing in some search engines.

Permission Denial Handler

UI

When getUserMedia() throws NotAllowedError, displays a tooltip or inline message: 'Microphone access is blocked. To enable: [browser-specific instructions].' Chrome: Settings → Privacy → Microphone. Safari: Preferences → Websites → Microphone. The search bar's text input remains fully functional as the fallback.

Note: Browser-specific instructions matter — users who are told 'enable microphone in settings' without knowing which settings menu get confused. Keep the permission instructions simple: one sentence per browser.

Build it — pick your path

Each tool fits this feature differently. Switch tabs to compare fit, time, the exact steps, and a copy-paste prompt.

Hand-built by developersFit for this feature:

Full control: Web Speech API for supported browsers + Whisper fallback + custom waveform visualizer + language auto-detection. Worth it when voice search is a core product feature, not an add-on.

Step by step

  1. 1Implement browser detection: Web Speech API for Chrome and Safari, MediaRecorder + Whisper Edge Function for Firefox; language auto-detect via the browser's navigator.language
  2. 2Build a custom waveform visualizer using AudioContext and AnalyserNode — getByteFrequencyData() at 60fps renders a real-time frequency bar chart next to the search bar during recording
  3. 3Add automatic silence detection: monitor AnalyserNode average amplitude; if below threshold for 1.5 seconds, stop recording and submit
  4. 4Implement query normalization: remove filler words ('um', 'uh', 'search for', 'find me'), normalize Unicode characters, strip trailing punctuation before search submission

Where this path bites

  • AudioContext waveform visualizer is technically complex and requires careful cleanup of animation frame loops and audio graph connections on component unmount
  • Cross-browser mic permission handling has numerous edge cases — iOS Safari requires SpeechRecognition to be created fresh per use; Chrome may throttle long-running recognitions

Third-party services you'll need

Voice search can run entirely free with the Web Speech API. Whisper adds paid accuracy for unsupported browsers and multilingual use:

ServiceWhat it doesFree tierPaid from
Web Speech APIBrowser-native speech-to-text; zero cost; Chrome desktop, Android Chrome, Safari iOSUnlimited, browser-nativeFree
OpenAI Whisper APIHighly accurate multilingual STT; required for Firefox; better accuracy in noisy environmentsNo free tier; pay-as-you-go$0.006 per minute of audio (approx)
Google Cloud Speech-to-TextStreaming transcription; 80+ languages; better for long-form voice input60 minutes/month$0.009–$0.016 per 15-second increment (approx)
speech_to_text (Flutter package)Open-source Flutter package using OS-level speech recognition; zero API costOpen-source, freeFree (uses device OS voices)

Swipe the table sideways to see pricing.

What it costs to run

Drag through the tiers to see how your monthly bill scales with users — no surprises later.

Estimated monthly running cost

$0/mo

Web Speech API or speech_to_text covers all usage at zero cost. No API needed for Chrome, Safari, and Android users — which is the majority of mobile traffic.

Estimates use verified 2026 pricing and assume typical usage per user. Your real bill depends on activity, storage, and third-party plans.

What breaks when AI tools build this

The failures people actually hit on their first build — the symptom, why it happens, and the exact fix.

Microphone permission popup never appears in Lovable or V0 preview

Symptom: Both tools run previews inside sandboxed iframes. The browser's getUserMedia() API only works in secure contexts (HTTPS) from a top-level document. Iframes require explicit allow='microphone' attribute on the iframe element to pass permissions through — which Lovable and V0 don't add to their preview iframes.

Fix: Publish to the production URL and test voice search there. In Lovable, use the QR code to open the published URL on your phone. In V0, deploy to Vercel before testing any microphone features. Never test mic in the embedded preview.

SpeechRecognition is undefined error in Firefox

Symptom: Firefox does not implement the Web Speech API as of 2026. If your code checks only window.SpeechRecognition without also checking window.webkitSpeechRecognition, Firefox users see a JavaScript error that breaks the search bar entirely — not a graceful fallback.

Fix: At runtime, check const SpeechRecognitionAPI = window.SpeechRecognition || window.webkitSpeechRecognition. If both are undefined, route to the Whisper Edge Function path using MediaRecorder. Show 'Use Chrome or Safari for instant voice search, or tap the mic to record a query' as a helpful tooltip.

Speech recognition stops after 5–10 seconds even with continuous: true

Symptom: Some browsers enforce undocumented time limits on SpeechRecognition sessions even when continuous: true is set. Chrome on Android limits sessions to approximately 60 seconds; some Safari versions stop at 20 seconds. The onend event fires, but if you don't handle it, the mic button appears active while recognition has silently stopped.

Fix: In the onend handler, check if the user has submitted a query. If not, restart the SpeechRecognition instance with a new object (do not reuse the stopped instance). Add a 30-second hard cap: after 30 seconds without a submission, stop and show 'Listening stopped — tap mic to try again.'

Voice search returns transcript but search results are empty

Symptom: The browser's speech recognition may return a transcript with trailing punctuation ('show me running shoes.'), filler words, or inconsistent casing ('Running Shoes'). These small differences cause full-text search queries to return zero results even though the content clearly matches — especially with strict text matching in Supabase's to_tsvector or a prefix-based search.

Fix: Normalize the transcript before passing it to the search function: transcript.trim().toLowerCase().replace(/[.!?]+$/, ''). Also strip common filler words ('um', 'uh', 'search for', 'find me', 'show me') if they appear at the start of the transcript.

iOS Safari speech recognition only works once per page load

Symptom: Safari on iOS requires a new SpeechRecognition instance to be created on every use. Reusing the same instance after calling stop() causes recognition to silently fail on subsequent mic button taps — no error is thrown, but no transcript is produced. This makes the mic button appear broken after the first successful search.

Fix: Destroy and recreate the SpeechRecognition object inside the mic button click handler every time. Do not cache the instance in state across uses. Set it to null after stop() and create a fresh one on the next tap.

Best practices

1

Always destroy and recreate the SpeechRecognition instance on each mic button tap — especially on iOS Safari where reusing a stopped instance silently fails

2

Normalize the transcript before search submission: trim whitespace, lowercase, remove trailing punctuation, strip filler words ('um', 'search for', 'show me')

3

Check for both window.SpeechRecognition and window.webkitSpeechRecognition; route to Whisper Edge Function if both are undefined rather than showing an error

4

Test on the published HTTPS URL, not in any preview iframe — getUserMedia() is blocked in sandboxed iframes regardless of the tool

5

Give the mic button a 44×44px minimum touch target and add aria-label='Search by voice' for screen reader accessibility

6

Add a 30-second timeout on active listening — restart on onend if no submission, stop and show a 'tap to retry' message after 30 seconds

7

Show the live transcript as the user speaks using interimResults: true — silence while the mic is on makes users think the feature isn't working

When You Need Custom Development

AI tools ship a working mic button with Web Speech API and Whisper fallback in hours. These requirements need a purpose-built voice pipeline:

  • App requires always-on wake-word detection ('Hey [AppName]') — the Web Speech API cannot do wake-word detection without continuous active listening, which drains battery
  • Multi-language voice search across 20+ languages with automatic language detection from speech, not user-selected locale
  • Voice search must distinguish between multiple concurrent users in a shared space — speaker diarization is not available in Web Speech API or standard Whisper
  • Compliance requirement for on-device transcription only — no audio sent to any cloud service, including OpenAI Whisper

RapidDev builds these features for production

Real auth, database, and payments — fixed price, delivered in weeks. You own 100% of the code.

Get a fixed-price quote

Frequently asked questions

Does voice search work on all mobile browsers?

Chrome on Android and Safari on iOS both support the Web Speech API. Firefox on Android does not support it as of 2026. For broad mobile coverage, implement the Whisper fallback: detect missing SpeechRecognition support at runtime and switch to MediaRecorder + the Whisper Edge Function path automatically.

How do I handle microphone permission being denied?

When getUserMedia() throws NotAllowedError, catch it and show a browser-specific help message in a tooltip or inline element: Chrome desktop — three-dot menu → Settings → Privacy and Security → Site Settings → Microphone. Safari — Preferences → Websites → Microphone. On iOS Safari — Settings app → Safari → Microphone. Keep the text input fully functional as the fallback — never disable the search bar when mic is denied.

Is Web Speech API free?

Yes. The Web Speech API is browser-native and completely free with no rate limits or API keys. The only cost is your server infrastructure for the optional Whisper fallback. At 100–1,000 users, the vast majority will use the free Web Speech API path; Whisper costs only apply to Firefox users and multilingual queries.

What is the difference between Web Speech API and Whisper?

The Web Speech API uses the browser's built-in speech recognition engine (Google's for Chrome, Apple's for Safari) and works in real time as the user speaks — no audio is sent to your backend. OpenAI Whisper is a cloud API: audio is recorded client-side, sent to your Edge Function, processed by OpenAI's server, and the transcript is returned. Whisper is more accurate for accented speech and non-English queries; Web Speech API has zero latency and zero cost.

Can voice search work offline?

The Web Speech API requires an internet connection for Chrome (it sends audio to Google's servers). Safari's implementation can use on-device models in some configurations but this is inconsistent across iOS versions. The speech_to_text Flutter package uses the OS speech engine, which on modern iOS and Android can run partially on-device for English. For guaranteed offline voice search, you need an on-device model like Whisper.cpp compiled for mobile — a significant engineering effort.

How do I show a waveform animation while listening?

For a simple pulsing ring effect, use a CSS animation (Tailwind's animate-ping or a custom keyframe scale animation) triggered by the isListening state. For a real audio waveform visualizer, use the AudioContext API: create an AnalyserNode connected to the microphone stream, call getByteFrequencyData() at 60fps inside a requestAnimationFrame loop, and render the frequency array as bars in a Canvas element. The second approach is significantly more complex but provides genuine audio-reactive feedback.

Does voice search find the same results as typed search?

Yes — once the transcript is normalized (trim, lowercase, remove trailing punctuation and filler words), it's passed directly to the same search function that handles typed queries. The search engine sees no difference. The only reason voice results diverge from typed results is unnormalized transcripts containing punctuation or filler words that typed queries wouldn't include.

How do I support multiple languages?

For Web Speech API: set the lang parameter on the SpeechRecognition instance to the user's current locale (navigator.language or your app's active language setting). For Whisper: include the detected language as the language parameter in the /v1/audio/transcriptions call — or omit it for automatic language detection. For the search backend, ensure your full-text search configuration handles the target language's stemming and character sets correctly.

RapidDev

Need this feature production-ready?

RapidDev builds voice search into real apps — auth, database, payments — at $13K–$25K.

Book a free consultation

30-min call. No commitment.

Want this built for you?

We ship production apps at a fixed price — $13K–$25K, 6–10 weeks, source code yours. You've seen what it takes; we do it every week.

Get a fixed-price quote

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.