Give it a GitHub star, if you found this repo useful.
React Native bindings for Moonshine on-device speech recognition, offline transcription from decoded PCM, streaming transcription, and intent recognition across iOS, Android, and web.
- Offline transcription from decoded PCM
- Streaming transcription with incremental transcript events
- Incremental transcript events during streaming and offline processing
- Word timestamps when the required model assets are present
- Intent recognizer support
- Web backend built on
onnxruntime-web - Typed transcriber API with explicit cancellation support
yarn add @siteed/moonshine.rnFor Expo / React Native apps using Yarn Berry, node-modules is still the most
predictable setup:
nodeLinker: node-modules- Android:
minSdkVersion 35 - iOS: native rebuild required after installing or upgrading the package
- Web:
window.ortmust be available before creating a transcriber
import Moonshine from '@siteed/moonshine.rn';
const transcriber = await Moonshine.createTranscriberFromFiles({
modelArch: 'small-streaming',
modelPath: '/absolute/path/to/model-dir',
options: {
wordTimestamps: true,
},
});
const result = await transcriber.transcribe({
input: samples,
sampleRate: 16000,
});
console.log(result.text);const controller = new AbortController();
const transcriptionPromise = transcriber.transcribe({
input: samples,
sampleRate: 16000,
signal: controller.signal,
});
controller.abort();
try {
await transcriptionPromise;
} catch (error) {
if (
error &&
typeof error === 'object' &&
'code' in error &&
error.code === 'MOONSHINE_TRANSCRIPTION_CANCELLED'
) {
console.log('Transcription cancelled');
}
}const removeListener = transcriber.addListener((event) => {
switch (event.type) {
case 'lineStarted':
case 'lineUpdated':
case 'lineTextChanged':
case 'lineCompleted':
console.log(event.line);
break;
case 'transcriptionCancelled':
console.warn('Transcription cancelled');
break;
case 'error':
console.error(event.error);
break;
}
});createTranscriberFromFiles()createTranscriberFromAssets()createTranscriberFromMemory()releaseTranscriber()
loadFromFiles()loadFromAssets()loadFromMemory()initialize()release()
start()/stop()cancel()createStream()/removeStream()startStream()/stopStream()addAudio()/addAudioToStream()transcribe({ input, sampleRate, signal? })
transcribe(...) accepts decoded mono PCM samples (number[] or
Float32Array) and a required sampleRate.
This package intentionally stays at the transcription-wrapper layer. Decode
files, URIs, and other container formats upstream before calling transcribe.
In this monorepo, that responsibility belongs in audio-processing utilities
such as audio-studio, not inside moonshine.rn.
Offline transcription cancellation rejects the in-flight promise with
MOONSHINE_TRANSCRIPTION_CANCELLED, surfaces as an AbortError-style
rejection, and emits a terminal transcriptionCancelled event instead of
returning a partial success result.
createIntentRecognizer()releaseIntentRecognizer()registerIntent()/unregisterIntent()processUtterance()clearIntents()setIntentThreshold()/getIntentThreshold()getIntentCount()
Typed transcriber options include:
identifySpeakersspeakerIdClusterThresholdvadThresholdvadHopSizevadWindowDurationMsvadMaxSegmentDurationMsvadLookBehindSampleCountmaxTokensPerSecondlogApiCallslogOrtRunslogOutputTextsaveInputWavPathwordTimestamps
transcriberOptions is also available as a low-level escape hatch for
upstream native options that are not yet modeled in the typed surface.
By default, the published package uses the Maven Moonshine Android artifact. That is the intended path for external consumers.
The package also supports repo-local source builds for internal development, but that is an advanced workflow and not the default installation path.
The podspec consumes the packaged Moonshine xcframework. After upgrading the package, rebuild the native iOS app so the JS layer and native bridge stay in sync.
The web backend is package-owned and does not depend on the published
@moonshine-ai/moonshine-js runtime bundle.
Web-specific typed load-config overrides are available when needed:
webEncoderUrlwebDecoderUrlwebProgressModelBasePath
Use configureMoonshineWeb() to override the default model CDN or the
onnxruntime-web wasm base path.
Word timestamps depend on model assets, not just API flags.
- Native streaming/offline word timestamps require the attention-capable decoder assets to be present alongside the model bundle.
- On web, word timestamps require an attention-capable decoder path.
Speaker-turn / speaker-clustering hints are available, but they should be considered experimental. They are useful for tentative turn segmentation, not trusted diarization or speaker identity.
These are mainly for development inside this monorepo:
bash packages/moonshine.rn/setup.sh
bash packages/moonshine.rn/build-moonshine-android.sh
bash packages/moonshine.rn/build-moonshine-ios.sh
bash packages/moonshine.rn/build-moonshine-web.shUseful package-local checks:
yarn release:beta:preflight
yarn validate:offline:contract <model-id> [device-filter]MicTranscriberis not wrapped directly; apps are expected to own microphone capture and audio routing.- Android and Sherpa must use a compatible ONNX Runtime ABI when linked into the same app binary.
- External Android consumers still need an app configuration compatible with
minSdkVersion 35.