Skip to content

adelbeke/react-native-speech-to-text

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

@dbkable/react-native-speech-to-text

npm version npm downloads license

A powerful, easy-to-use React Native library for real-time speech-to-text conversion. Built with the New Architecture (Turbo Modules) for optimal performance on both iOS and Android.

✨ Features

  • 🎤 Real-time transcription with partial results as you speak
  • 📱 Cross-platform support for iOS and Android
  • 🎯 Confidence scores for transcription accuracy
  • 🌍 Multi-language support
  • Event-driven architecture with listeners
  • 🔒 Built-in permission handling
  • 🏗️ New Architecture ready (Turbo Modules)
  • 📝 TypeScript definitions included
  • ⚙️ Expo Config Plugin for automatic setup

📱 Demo

iOS Android
android-preview.mov
ios-preview.MP4

📦 Installation

npm install @dbkable/react-native-speech-to-text

or

yarn add @dbkable/react-native-speech-to-text

For Expo Projects

Add the plugin to your app.json or app.config.js:

{
  "expo": {
    "plugins": ["@dbkable/react-native-speech-to-text"]
  }
}

That's it! The plugin automatically configures permissions for both iOS and Android. Run npx expo prebuild to apply the changes.

Custom Permission Messages (Optional)

You can customize the iOS permission messages:

{
  "expo": {
    "plugins": [
      [
        "@dbkable/react-native-speech-to-text",
        {
          "microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone",
          "speechRecognitionPermission": "Allow $(PRODUCT_NAME) to recognize your speech"
        }
      ]
    ]
  }
}

For Bare React Native Projects

iOS Setup

Install pods:

cd ios && pod install

Add the following to your Info.plist:

<key>NSSpeechRecognitionUsageDescription</key>
<string>This app needs speech recognition to convert your voice to text</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access to record your voice</string>

Android Setup

Add the following permission to your AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>

The package handles runtime permission requests automatically.

🚀 Quick Start

import { useState, useEffect } from 'react';
import {
  start,
  stop,
  requestPermissions,
  isAvailable,
  addSpeechResultListener,
  addSpeechErrorListener,
  addSpeechEndListener,
  type SpeechResult,
} from '@dbkable/react-native-speech-to-text';

export default function App() {
  const [transcript, setTranscript] = useState('');
  const [isListening, setIsListening] = useState(false);

  useEffect(() => {
    // Listen for results
    const resultListener = addSpeechResultListener((result: SpeechResult) => {
      setTranscript(result.transcript);
      console.log('Confidence:', result.confidence);
    });

    // Listen for errors
    const errorListener = addSpeechErrorListener((error) => {
      console.error('Speech error:', error);
      setIsListening(false);
    });

    // Listen for end of speech
    const endListener = addSpeechEndListener(() => {
      setIsListening(false);
    });

    // Cleanup
    return () => {
      resultListener.remove();
      errorListener.remove();
      endListener.remove();
    };
  }, []);

  const handleStart = async () => {
    try {
      const available = await isAvailable();
      if (!available) {
        alert('Speech recognition not available');
        return;
      }

      const hasPermission = await requestPermissions();
      if (!hasPermission) {
        alert('Permission denied');
        return;
      }

      await start({ language: 'en-US' });
      setIsListening(true);
    } catch (error) {
      console.error(error);
    }
  };

  const handleStop = async () => {
    try {
      await stop();
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <View>
      <Text>{transcript || 'Press start to begin'}</Text>
      <Button
        title={isListening ? 'Stop' : 'Start'}
        onPress={isListening ? handleStop : handleStart}
      />
    </View>
  );
}

📚 API Reference

Methods

start(options: SpeechToTextOptions): Promise<void>

Starts speech recognition.

await start({ language: 'en-US' });

Options:

  • language (string, required): Language code (e.g., "en-US", "fr-FR", "es-ES", "de-DE")

Throws:

  • PERMISSION_DENIED: User denied permissions
  • NOT_AVAILABLE: Speech recognition not available
  • START_FAILED: Failed to start recognition

stop(): Promise<void>

Stops speech recognition and sends the final transcript.

await stop();

requestPermissions(options?: PermissionOptions): Promise<boolean>

Requests necessary permissions for speech recognition.

const granted = await requestPermissions({
  title: 'Microphone Permission',
  message: 'This app needs access to your microphone for speech recognition',
  buttonPositive: 'OK',
});

Options (Android only):

  • title (string, optional): Dialog title
  • message (string, optional): Dialog message
  • buttonNeutral (string, optional): Neutral button text
  • buttonNegative (string, optional): Negative button text
  • buttonPositive (string, optional): Positive button text

Returns: boolean - true if permission granted, false otherwise


isAvailable(): Promise<boolean>

Checks if speech recognition is available on the device.

const available = await isAvailable();
if (!available) {
  console.log('Speech recognition not supported');
}

Returns: boolean


Event Listeners

addSpeechResultListener(callback: (result: SpeechResult) => void): EmitterSubscription

Listens for transcription results (both partial and final).

const listener = addSpeechResultListener((result) => {
  console.log('Transcript:', result.transcript);
  console.log('Confidence:', result.confidence);
  console.log('Is final:', result.isFinal);
});

// Don't forget to remove the listener
listener.remove();

SpeechResult:

  • transcript (string): The recognized text
  • confidence (number): Confidence score from 0.0 to 1.0
  • isFinal (boolean): true for final result, false for partial

addSpeechErrorListener(callback: (error: SpeechError) => void): EmitterSubscription

Listens for error events.

const listener = addSpeechErrorListener((error) => {
  console.error('Error code:', error.code);
  console.error('Error message:', error.message);
});

listener.remove();

SpeechError:

  • code (string): Error code (see Error Codes)
  • message (string): Human-readable error message

addSpeechEndListener(callback: () => void): EmitterSubscription

Called when speech recognition ends.

const listener = addSpeechEndListener(() => {
  console.log('Speech recognition ended');
});

listener.remove();

Types

interface SpeechToTextOptions {
  language: string; // e.g., "en-US", "fr-FR", "es-ES"
}

interface PermissionOptions {
  title?: string;
  message?: string;
  buttonNeutral?: string;
  buttonNegative?: string;
  buttonPositive?: string;
}

interface SpeechResult {
  transcript: string;
  confidence: number;
  isFinal: boolean;
}

interface SpeechError {
  code: SpeechErrorCode | string;
  message: string;
}

enum SpeechErrorCode {
  PERMISSION_DENIED = 'PERMISSION_DENIED',
  NOT_AVAILABLE = 'NOT_AVAILABLE',
  REQUEST_FAILED = 'REQUEST_FAILED',
  START_FAILED = 'START_FAILED',
  STOP_FAILED = 'STOP_FAILED',
  AUDIO_ERROR = 'AUDIO_ERROR',
  CLIENT_ERROR = 'CLIENT_ERROR',
  NETWORK_ERROR = 'NETWORK_ERROR',
  NETWORK_TIMEOUT = 'NETWORK_TIMEOUT',
  RECOGNIZER_BUSY = 'RECOGNIZER_BUSY',
  SERVER_ERROR = 'SERVER_ERROR',
  UNKNOWN_ERROR = 'UNKNOWN_ERROR',
}

⚙️ Expo Plugin Configuration

If you're using Expo, the plugin automatically configures native permissions for you.

Basic Usage

{
  "expo": {
    "plugins": ["@dbkable/react-native-speech-to-text"]
  }
}

With Custom Permission Messages

{
  "expo": {
    "plugins": [
      [
        "@dbkable/react-native-speech-to-text",
        {
          "microphonePermission": "Custom message for microphone access",
          "speechRecognitionPermission": "Custom message for speech recognition"
        }
      ]
    ]
  }
}

Plugin Options

Option Type Default Description
microphonePermission string "Allow $(PRODUCT_NAME) to access your microphone to record audio for speech recognition" iOS only: Custom message for NSMicrophoneUsageDescription
speechRecognitionPermission string "Allow $(PRODUCT_NAME) to use speech recognition to convert your voice to text" iOS only: Custom message for NSSpeechRecognitionUsageDescription

What the Plugin Does

The Expo Config Plugin automatically:

  • iOS: Adds NSMicrophoneUsageDescription and NSSpeechRecognitionUsageDescription to Info.plist
  • Android: Adds RECORD_AUDIO permission to AndroidManifest.xml

After adding or modifying the plugin configuration, run:

npx expo prebuild

🌍 Supported Languages

You can use any standard locale identifier. Here are some examples:

  • English: en-US, en-GB, en-AU
  • French: fr-FR, fr-CA
  • Spanish: es-ES, es-MX
  • German: de-DE
  • Italian: it-IT
  • Portuguese: pt-BR, pt-PT
  • Japanese: ja-JP
  • Chinese: zh-CN, zh-TW
  • Korean: ko-KR
  • Arabic: ar-SA

Availability depends on the device and platform. Use isAvailable() to check.

🔧 Troubleshooting

"Permission denied" error

Expo users: If you've added the plugin to your app.json, permissions should be configured automatically. Make sure to run npx expo prebuild after adding the plugin.

Bare React Native - iOS:

  • Make sure you've added NSSpeechRecognitionUsageDescription and NSMicrophoneUsageDescription to your Info.plist
  • Check that the user granted permissions in Settings > Your App

Bare React Native - Android:

  • Ensure RECORD_AUDIO permission is in AndroidManifest.xml
  • Call requestPermissions() before start()

"Speech recognition not available"

  • iOS: Speech recognition requires iOS 10+ and is not available in the simulator for some iOS versions. Test on a real device.
  • Android: Ensure Google app or speech recognition service is installed and up to date.
  • Some older devices may not support speech recognition.

No partial results showing

  • Partial results are enabled by default on both platforms
  • On Android, partial results appear after a short delay
  • If you're only seeing final results, check that you're handling the isFinal flag correctly

Recognition stops automatically

  • iOS: May stop automatically after detecting silence
  • Android: Configured with 2-second pause detection and 10-second minimum recording
  • Call start() again to restart recognition

Low confidence scores

  • Speak clearly and in a quiet environment
  • Ensure the device microphone is not obstructed
  • Try a different language/locale that better matches the speaker's accent

Network errors

Some speech recognition services require internet connectivity:

  • iOS: On-device recognition available on iOS 13+ for some languages
  • Android: Depends on the device's speech recognition provider

Ensure the device has internet access for best results.

🤝 Contributing

We welcome contributions! Here's how to get started:

  1. Fork the repository on GitHub
  2. Clone your fork locally
  3. Create a branch for your feature: git checkout -b my-feature
  4. Make your changes and add tests if applicable
  5. Test thoroughly on both iOS and Android
  6. Commit your changes: git commit -am 'feat: add amazing feature' (follow Conventional Commits)
  7. Push to your fork: git push origin my-feature
  8. Open a Pull Request on GitHub

Development Setup

# Clone the repo
git clone https://github.com/adelbeke/react-native-speech-to-text.git
cd react-native-speech-to-text

# Install dependencies
yarn install

# Run the example app
yarn example ios
# or
yarn example android

Code Style

This project uses ESLint and Prettier. Run:

yarn lint
yarn typescript

For more details, see CONTRIBUTING.md.

📄 License

MIT © Arthur Delbeke

🙏 Acknowledgments

Built with create-react-native-library

🔗 Links


Made with ❤️ for the React Native community

About

Cross-platform speech recognition library for React Native using native APIs (Speech Framework & SpeechRecognizer)

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

No packages published