npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

expo-speech-transcriber

v0.1.9

Published

An iOS only on-device transcription library for React Native and Expo apps.

Downloads

1,679

Readme

expo-speech-transcriber

On-device speech transcription for Expo apps. Supports iOS (Apple Speech framework) and Android (SpeechRecognizer API).

Features

  • 🎯 On-device transcription - Works offline, privacy-focused
  • 📱 Cross-platform - iOS 13+ and Android 13+ (API 33)
  • 🚀 Multiple APIs - SFSpeechRecognizer (iOS 13+), SpeechAnalyzer (iOS 26+), and Android SpeechRecognizer
  • 📦 Easy integration - Auto-configures permissions
  • 🔒 Secure - All processing happens on device
  • ⚡ Realtime transcription - Get live speech-to-text updates with built-in audio capture
  • 📁 File transcription - Transcribe pre-recorded audio files
  • 🎤 Buffer-based transcription - Stream audio buffers from external sources for real-time transcription

Installation

npx expo install expo-speech-transcriber expo-audio

Add the plugin to your app.json:

{
  "expo": {
    "plugins": ["expo-audio", "expo-speech-transcriber"]
  }
}

Custom permission message (recommended):

Apple requires a clear purpose string for speech recognition and microphone permissions. Without it, your app may be rejected during App Store review. Provide a descriptive message explaining why your app needs access.

{
  "expo": {
    "plugins": [
      "expo-audio",
      [
        "expo-speech-transcriber",
        {
          "speechRecognitionPermission": "We need speech recognition to transcribe your recordings",
          "microphonePermission": "We need microphone access to record audio for transcription"
        }
      ]
    ]
  }
}

For more details, see Apple's guidelines on requesting access to protected resources.

Note for Android: The plugin automatically adds the RECORD_AUDIO permission to your Android manifest. No additional configuration is required.

Usage

Realtime Transcription

Start transcribing speech in real-time. This does not require expo-audio.

import { Platform } from "react-native";
import * as SpeechTranscriber from "expo-speech-transcriber";

// Request permissions
// Note: requestPermissions() is only needed on iOS
if (Platform.OS === "ios") {
  const speechPermission = await SpeechTranscriber.requestPermissions();
  if (speechPermission !== "authorized") {
    console.log("Speech permission denied");
    return;
  }
}

const micPermission = await SpeechTranscriber.requestMicrophonePermissions();
if (micPermission !== "granted") {
  console.log("Microphone permission denied");
  return;
}

// Use the hook for realtime updates
const { text, isFinal, error, isRecording } =
  SpeechTranscriber.useRealTimeTranscription();

// Start transcription
await SpeechTranscriber.recordRealTimeAndTranscribe();

// Stop when done
SpeechTranscriber.stopListening();

NOTE: See RecordRealTimeAndTrancribe for an example on how to use Real Time transcription on android.

File Transcription

Transcribe pre-recorded audio files. Our library handles transcription but not recording—use expo-audio to record audio (see expo-audio documentation), or implement your own recording logic with microphone access via requestMicrophonePermissions().

import * as SpeechTranscriber from "expo-speech-transcriber";
import { useAudioRecorder, RecordingPresets } from "expo-audio";

// Record audio with expo-audio
const audioRecorder = useAudioRecorder(RecordingPresets.HIGH_QUALITY);
await audioRecorder.prepareToRecordAsync();
audioRecorder.record();
// ... user speaks ...
await audioRecorder.stop();
const audioUri = audioRecorder.uri;

// Transcribe with SFSpeechRecognizer (preferred)
const text = await SpeechTranscriber.transcribeAudioWithSFRecognizer(audioUri);
console.log("Transcription:", text);

// Or with SpeechAnalyzer if available
if (SpeechTranscriber.isAnalyzerAvailable()) {
  const text = await SpeechTranscriber.transcribeAudioWithAnalyzer(audioUri);
  console.log("Transcription:", text);
}

For custom recording without expo-audio:

// Request microphone permission for your custom recording implementation
const micPermission = await SpeechTranscriber.requestMicrophonePermissions();
// Implement your own audio recording logic here to save a file
// Then transcribe the resulting audio file URI

Buffer-Based Transcription

Stream audio buffers directly to the transcriber for real-time processing. This is ideal for integrating with audio processing libraries like react-native-audio-api.

import * as SpeechTranscriber from "expo-speech-transcriber";
import { AudioManager, AudioRecorder } from "react-native-audio-api";

// Set up audio recorder
const recorder = new AudioRecorder({
  sampleRate: 16000,
  bufferLengthInSamples: 1600,
});

AudioManager.setAudioSessionOptions({
  iosCategory: "playAndRecord",
  iosMode: "spokenAudio",
  iosOptions: ["allowBluetooth", "defaultToSpeaker"],
});

// Request permissions
const speechPermission = await SpeechTranscriber.requestPermissions();
const micPermission = await AudioManager.requestRecordingPermissions();

// Stream audio buffers to transcriber
recorder.onAudioReady(({ buffer }) => {
  const channelData = buffer.getChannelData(0);
  SpeechTranscriber.realtimeBufferTranscribe(
    channelData, // Float32Array or number[]
    16000, // sample rate
  );
});

// Use the hook to get transcription updates
const { text, isFinal, error } = SpeechTranscriber.useRealTimeTranscription();

// Start streaming
recorder.start();

// Stop when done
recorder.stop();
SpeechTranscriber.stopBufferTranscription();

See the BufferTranscriptionExample for a complete implementation.

API Reference

requestPermissions()

Request speech recognition permission.

Platform: iOS only. On Android, speech recognition permission is handled through requestMicrophonePermissions().

Returns: Promise<PermissionTypes> - One of: 'authorized', 'denied', 'restricted', or 'notDetermined'

Example:

import { Platform } from "react-native";

if (Platform.OS === "ios") {
  const status = await SpeechTranscriber.requestPermissions();
}

requestMicrophonePermissions()

Request microphone permission.

Returns: Promise<MicrophonePermissionTypes> - One of: 'granted' or 'denied'

Example:

const status = await SpeechTranscriber.requestMicrophonePermissions();

recordRealTimeAndTranscribe()

Start real-time speech transcription. Listen for events via useRealTimeTranscription hook.

Returns: Promise<void>

Example:

await SpeechTranscriber.recordRealTimeAndTranscribe();

stopListening()

Stop real-time transcription.

Returns: void

Example:

SpeechTranscriber.stopListening();

isRecording()

Check if real-time transcription is currently recording.

Returns: boolean

Example:

const recording = SpeechTranscriber.isRecording();

transcribeAudioWithSFRecognizer(audioFilePath: string)

Transcribe audio from a pre-recorded file using SFSpeechRecognizer. I prefer this API for its reliability.

Platform: iOS only

Requires: iOS 13+, pre-recorded audio file URI (record with expo-audio or your own implementation)

Returns: Promise<string> - Transcribed text

Example:

const transcription = await SpeechTranscriber.transcribeAudioWithSFRecognizer(
  "file://path/to/audio.m4a"
);

transcribeAudioWithAnalyzer(audioFilePath: string)

Transcribe audio from a pre-recorded file using SpeechAnalyzer.

Platform: iOS only

Requires: iOS 26+, pre-recorded audio file URI (record with expo-audio or your own implementation)

Returns: Promise<string> - Transcribed text

Example:

const transcription = await SpeechTranscriber.transcribeAudioWithAnalyzer(
  "file://path/to/audio.m4a"
);

isAnalyzerAvailable()

Check if SpeechAnalyzer API is available.

Platform: iOS only. Always returns false on Android.

Returns: boolean - true if iOS 26+, false otherwise

Example:

if (SpeechTranscriber.isAnalyzerAvailable()) {
  // Use SpeechAnalyzer
}

useRealTimeTranscription()

React hook for real-time transcription state.

Returns: { text: string, isFinal: boolean, error: string | null, isRecording: boolean }

Example:

const { text, isFinal, error, isRecording } =
  SpeechTranscriber.useRealTimeTranscription();

realtimeBufferTranscribe(buffer, sampleRate)

Stream audio buffers for real-time transcription. Ideal for integration with audio processing libraries.

Parameters:

  • buffer: Float32Array | number[] - Audio samples
  • sampleRate: number - Sample rate in Hz (e.g., 16000)

NOTE We currently support transcription for mono audio only. Natively, the channel is set to 1.

Returns: Promise<void>

Example:

const audioBuffer = new Float32Array([...]);
await SpeechTranscriber.realtimeBufferTranscribe(audioBuffer, 16000);

stopBufferTranscription()

Stop buffer-based transcription and clean up resources.

Returns: void

Example:

SpeechTranscriber.stopBufferTranscription();

Example

See the example app for a complete implementation demonstrating all APIs.

Requirements

iOS

  • iOS 13.0+
  • Expo SDK 52+
  • Development build (Expo Go not supported - why?)

Android

  • Android 13+ (API level 33)
  • Expo SDK 52+
  • Development build (Expo Go not supported)

Limitations

  • English only - Currently hardcoded to en_US locale
  • File size - Best for short recordings (< 1 minute)
  • Recording not included - Real-time transcription captures audio internally; file transcription requires pre-recorded audio files (use expo-audio or implement your own recording with requestMicrophonePermissions())
  • Android file transcription - File-based transcription (transcribeAudioWithSFRecognizer, transcribeAudioWithAnalyzer) is iOS only. Android supports real-time transcription
  • Android API level - Android requires API level 33+ (Android 13)

License

MIT

Contributing

Contributions welcome! Please open an issue or PR on GitHub.

Author

Dave Mkpa Eke - GitHub | X