How-to guides

Add Text to Speech to an Expo App

Add a read-aloud button with Expo Speech, stop the previous utterance before starting another, and give the person a visible Stop control. Voice selection and device audio settings are part of the feature.

Updated 28 October 2026

What you will build

A screen that speaks a short piece of text and can stop it. The example handles completion and errors and stops speech when the screen unmounts. It does not record the microphone or create a downloadable audio file.

  1. Step 1Choose the text
  2. Step 2Read it aloud
  3. Step 3Stop or finish

The example uses the Expo Speech API documented for SDK 58. Voice availability varies by device and language. Expo specifically warns that physical iOS devices produce no speech in silent mode.

Build it in Newly

Open your project in Newly and describe the behavior you want. Use this suggested prompt as a starting point, then review the generated changes and follow the checks below.

Suggested prompt
Add a Read aloud button to the article screen using expo-speech. Read the visible article text, stop an existing utterance before starting a new one, and provide a Stop button. Show reading, finished and error states. Stop speech when the reader leaves this screen. Start with short text and the current language; only offer voices returned by the device. Do not add microphone permission or claim that the feature exports an audio file.

  1. 1. Start with one short passage

    Ask Newly to connect the Read aloud button to the text already displayed on the screen. Trim empty input and check Speech.maxSpeechInputLength before speaking. Long articles need a chunking and navigation design rather than one unrestricted call.

  2. 2. Give the user control

    Stop the existing utterance before speaking again so repeated taps do not queue the article several times. Connect the speech callbacks to visible status text. Add Stop, and stop playback when this screen leaves the navigation tree. If your navigator keeps screens mounted, also stop speech on its blur event.

  3. 3. Choose voices from the device

    If you add a voice menu, populate it from getAvailableVoicesAsync and store a preference only when the selected voice is available. Keep a default-language fallback for a new phone. Test the language you actually publish, including punctuation and abbreviations.

Expo implementation example

Install the dependencies in your Expo project. Expo resolves native package versions for your installed SDK.

Install command
npx expo install expo-speech

Code example
import { useEffect, useRef, useState } from "react";
import { Button, Text, View } from "react-native";
import * as Speech from "expo-speech";

const passage = "Your next appointment is tomorrow at nine.";

export default function ReadAloud() {
  const [status, setStatus] = useState("Ready");
  const starting = useRef(false);
  const mounted = useRef(true);

  useEffect(() => {
    mounted.current = true;
    return () => {
      mounted.current = false;
      void Speech.stop().catch(() => undefined);
    };
  }, []);

  function report(message: string) {
    if (mounted.current) setStatus(message);
  }

  async function readAloud() {
    if (starting.current) return;
    starting.current = true;
    try {
      const text = passage.trim();
      if (!text || text.length > Speech.maxSpeechInputLength) {
        report("Choose a shorter passage.");
        return;
      }
      await Speech.stop();
      if (!mounted.current) return;
      Speech.speak(text, {
        language: "en-US",
        onStart: () => report("Reading aloud"),
        onDone: () => report("Finished"),
        onStopped: () => report("Stopped"),
        onError: () => report("Speech is unavailable. Try another voice."),
      });
    } catch {
      report("Could not start speech. Please try again.");
    } finally {
      starting.current = false;
    }
  }

  async function stop() {
    try {
      await Speech.stop();
      report("Stopped");
    } catch {
      report("Could not stop speech. Please try again.");
    }
  }

  return (
    <View style={{ gap: 16, padding: 24 }}>
      <Text>{passage}</Text>
      <Button title="Read aloud" onPress={readAloud} />
      <Button title="Stop" onPress={stop} />
      <Text accessibilityLiveRegion="polite">{status}</Text>
    </View>
  );
}

Use a physical device to verify sound. In navigation systems that retain mounted screens, add a focus/blur listener as well as unmount cleanup. For long text, add chunk boundaries, progress and cancellation before extending this example.

Test before publishing

  • Read a short passage, stop it and restart it without hearing duplicate queued readings.
  • Leave the screen while speech is active and confirm it stops.
  • On a physical iPhone, compare silent mode on and off; check media volume and the selected audio output.
  • Try a language or voice missing from another device and verify the fallback.
  • Keep visible text and normal screen-reader navigation available when speech fails.

Run these checks in your own project on iOS and Android. A browser preview does not establish native permission, hardware or background behavior.

Common problems

The iPhone is silent

Check silent mode, volume and audio routing on the physical device. A successful speak call does not prove that the user heard anything.

Pause works on iOS but fails on Android

Expo documents pause and resume as unavailable on Android. Use Stop across platforms; if you need resumable reading, retain the current passage and restart at a deliberate boundary.

Questions about text to speech

Does text to speech need microphone permission?

Speaking supplied text does not record the microphone. Do not add microphone access for this feature. Speech recognition is a separate feature with different APIs and permission requirements.

Will the same voice exist on every phone?

No. Query the voices available on the device and provide a fallback. A saved voice identifier may be unavailable after a device change or a voice removal.

Does read aloud replace accessibility support?

No. Keep the text readable and controls accessible to VoiceOver and TalkBack. An optional read-aloud button does not replace screen-reader labels, focus behavior or scalable text.

Can Expo Speech export an MP3?

Expo Speech exposes speaking and playback controls, rather than an audio-file export method. Choose a separate synthesis or recording solution if the product needs a downloadable file.

Sources and API references

Keep building

Build this feature in Newly