@tilawi/expo-pcm-recorder
v0.1.0
Published
Minimal Expo module that streams mono float32 microphone PCM (e.g. 16 kHz) to JS in fixed-size chunks, for on-device speech recognition.
Maintainers
Readme
@tilawi/expo-pcm-recorder
A minimal Expo module that streams raw microphone audio to JavaScript as mono float32 PCM at the sample rate you ask for (e.g. 16 kHz), in fixed-size chunks. Built for on-device speech recognition, where you want samples rather than an encoded file.
It powers voice search and memorization checks in the Tilawi Quran app, together with @tilawi/react-native-quran-asr.
- iOS:
AVAudioEngineinput tap, converted withAVAudioConverter. The audio session is set to.playAndRecord(Bluetooth allowed, mixes with and ducks other audio) and restored to its previous category when recording stops. - Android:
AudioRecordfrom theMICsource, 16-bit PCM scaled to [-1, 1], with transient audio focus while recording. - Safe to import in a build that doesn't include the native code:
isPcmRecorderAvailableis thenfalseand nothing crashes.
Install
npx expo install @tilawi/expo-pcm-recorderThen rebuild your development client (this module has native code; it doesn't work in Expo Go).
Microphone permission. This module doesn't request permission itself. Declare it and ask for it with another module that owns the same OS permission, for example expo-audio:
{ "plugins": [["expo-audio", { "microphonePermission": "Allow $(PRODUCT_NAME) to hear your recitation." }]] }import { requestRecordingPermissionsAsync } from 'expo-audio';
await requestRecordingPermissionsAsync();Usage
import {
addPcmChunkListener,
isPcmRecorderAvailable,
startPcmRecording,
stopPcmRecording,
} from '@tilawi/expo-pcm-recorder';
const chunks: number[][] = [];
const sub = addPcmChunkListener((samples) => chunks.push(samples)); // float32 in [-1, 1]
await startPcmRecording(16000, 100); // 16 kHz, one chunk every 100 ms
// ... later
await stopPcmRecording(); // remaining audio is delivered before this resolves
sub?.remove();| API | |
|---|---|
| startPcmRecording(sampleRate, intervalMs) | Start capturing. Rejects if the permission is missing, the microphone is busy, or a recording is already running. |
| stopPcmRecording() | Stop and flush the remaining audio. Safe to call when idle. |
| addPcmChunkListener(fn) | Receive number[] chunks of mono samples. Returns a subscription (null when unavailable). |
| isPcmRecorderAvailable | false when the native module isn't in the running binary. |
Android caveat: if the capture thread doesn't finish within 1 s of stopping (not observed in practice), a final chunk may arrive after stopPcmRecording() resolves.
Credits
Inspired by @siteed/audio-studio (MIT) by @deeeed; the native sources note which of its capture settings this module mirrors.
License
MIT
