whisper.rn
AGENTS.md809 starsChanged 8 months agoMITView on GitHub
whisper.rn is a React Native binding for whisper.cpp, enabling high-performance inference of OpenAI's Whisper automatic speech recognition (ASR) model on iOS and Android devices. Key Features: - Native speech-to-text transcription via whisper.cpp - NVIDIA Parakeet TDT transcription with multilingual model support - Voice Activity Detection (VAD) using Silero VAD model - Realtime transcription with auto-slicing and memory management - Core ML support for iOS (encoder acceleration) - Metal/GPU acceleration support - JSI (JavaScript Interface) bindings for efficient ArrayBuffer transfers whisper.rn…
- Deletes or force-pushes
- Installs packages
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,542 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository2 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- upgrade-react-nativeSkill
The file
We split this AGENTS.md into the rules it gives an agent
11 rules. About 0 are common, 7 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 19
Add comments appropriately, no need to explain the obvious.
- Very specific: line 168
Must be co-located with GGML model (e.g., ggml-tiny.en.bin → ggml-tiny.en-encoder.mlmodelc/)
- Distinctive: line 226
Use quantized models (q8, q5) to reduce size and improve speed on mobile
- Distinctive: line 227
Default thread count: 2 for 4-core devices, 4 for more cores
- Distinctive: line 228
Test in Release mode for accurate performance measurement
- Very specific: line 232
Use require() for bundled models/audio
- Very specific: line 233
Add .bin and .mil to Metro config assetExts
- Very specific: line 251
Use PermissionsAndroid to request runtime permission
- Distinctive: line 256
Follow standard React Native library integration
- Distinctive: line 269
Test realtime: Requires microphone permissions
- Distinctive: line 341
Use Release mode for testing
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
whisper.rn - Development Guidelines
Project Overview
whisper.rn is a React Native binding for whisper.cpp, enabling high-performance inference of OpenAI's Whisper automatic speech recognition (ASR) model on iOS and Android devices.
Key Features:
- Native speech-to-text transcription via whisper.cpp
- NVIDIA Parakeet TDT transcription with multilingual model support
- Voice Activity Detection (VAD) using Silero VAD model
- Realtime transcription with auto-slicing and memory management
- Core ML support for iOS (encoder acceleration)
- Metal/GPU acceleration support
- JSI (JavaScript Interface) bindings for efficient ArrayBuffer transfers
General
- Pay attention to code readability.
- Add comments appropriately, no need to explain the obvious.
- Apply first-principles thinking when appropriate.
Development Commands
Setup and Bootstrap
npm install # Install dependencies
npm run bootstrap # Setup example app deps + download example model assets
npm run sync:vendor # Re-vendor vendor/whisper.cpp from vendor/VERSIONS + scripts/patchesCode Quality
npm run typecheck # Type-check TypeScript files
npm run lint # Lint files with ESLint
npm run lint -- --fix # Fix lint errors
npm test # Run Jest unit testsBuild Commands
npm run build # Build TypeScript library with react-native-builder-bob
# iOS framework builds (creates prebuilt xcframework)
npm run build:ios-frameworks # Build rnwhisper.xcframework for iOS/tvOS
./scripts/build-ios.sh # Manual iOS framework build script
# Example app builds
npm run example run start # Start Metro bundler for example app
npm run example run android # Run example on Android
npm run example run ios # Run example on iOS
npm run example run pods # Install iOS pods for example
# Release builds for testing performance
npm run example run ios -- --mode Release
npm run example run android -- --mode releaseDocumentation
npm run docgen # Generate API documentation with typedocRelease
npm run release # Publish new version with release-itArchitecture
Multi-Layer Architecture
whisper.rn has a 4-layer architecture:
- JavaScript/TypeScript Layer (
src/):index.ts: Main API exports,WhisperContext,ParakeetContext, andWhisperVadContextclassesNativeRNWhisper.ts: TurboModule spec (New Architecture compatible)realtime-transcription/: Enhanced realtime transcription frameworkRealtimeTranscriber.ts: Main transcriber with VAD integrationSliceManager.ts: Audio slice memory managementadapters/: Audio stream adapters (e.g., AudioPcmStreamAdapter)
- JSI Bindings (
cpp/jsi/):RNWhisperJSI.cpp/h: High-performance JSI functions for ArrayBuffer operations- Direct memory transfer for audio data (bypasses JSON serialization)
- Thread pool for async processing
- Functions:
whisperTranscribeData,parakeetTranscribeData,whisperVadDetectSpeech
- Native Modules (
ios/,android/src/main/java/):- iOS:
RNWhisper.mm,RNWhisperContext.mm,RNWhisperVadContext.mm - Android:
RNWhisper.java,WhisperContext.java,WhisperVadContext.java - React Native bridge methods for initialization, file transcription
- Audio session management (iOS)
- Realtime recording (deprecated, use RealtimeTranscriber instead)
- iOS:
- C++ Core (
cpp/+vendor/):cpp/holds only whisper.rn's own code:rn-whisper.cpp/h(job management, transcription orchestration),rn-whisper-log.h, andjsi/- whisper.cpp is vendored under
vendor/whisper.cpp/in its upstream layout (include/,src/withwhisper.cpp,parakeet.cppandcoreml/,ggml/{include,src}with the CPU and Metal backends), pinned byvendor/VERSIONS, with whisper.rn changes kept as-p1patches inscripts/patches/whisper.cpp/. No git submodule, no symbol renaming. Seevendor/README.md. vendor/whisper.cppis also consumed by whisper.node via upstream's CMake project, so it carries upstream's build files,examples/common-whisper.*(withminiaudio.h/stb_vorbis.c) and the BLAS/CUDA/Vulkan/WebGPU backends. whisper.rn's builds never compile those;cmake/rnwhisper-sources.cmakeandwhisper-rn.podspecfilter them out (keep the two in sync).cmake/rnwhisper-sources.cmakeis the single source/include list every CMake build uses;whisper-rn.podspecmirrors it for CocoaPods
Context Management
The library uses a context-based model:
- WhisperContext: Main transcription context, initialized with a GGML model file
- Methods:
transcribe(),transcribeData(),transcribeRealtime()(deprecated),bench(),release() - Supports file paths, base64 WAV, ArrayBuffer (via JSI), and asset URIs
- Methods:
- ParakeetContext: Parakeet TDT transcription context, initialized with a Parakeet GGUF model
- Methods:
transcribe(),transcribeData(),release() - Supports WAV file paths, base64 WAV, raw PCM16 ArrayBuffer data, and asset URIs
- Methods:
- WhisperVadContext: VAD context, initialized with Silero VAD model
- Methods:
detectSpeech(),detectSpeechData(),release() - Used for voice activity detection in audio segments
- Methods:
All contexts maintain:
id: Unique context identifiergpu: Whether GPU/Metal acceleration is activereasonNoGPU: Explanation if GPU is not available
JSI Installation
JSI bindings are lazily installed on first use:
- Called automatically by
initWhisper(),initParakeet(), andinitWhisperVad() - Installs global functions including
whisperTranscribeData,parakeetTranscribeData, andwhisperVadDetectSpeech - These functions are then captured and removed from global scope
Realtime Transcription Architecture
The modern RealtimeTranscriber (in src/realtime-transcription/) provides:
- SliceManager: Manages audio slicing with circular buffer strategy
- Auto-slices at configurable duration (default: 30s)
- Keeps limited slices in memory (default: 3)
- Provides memory usage stats
- VAD Integration:
- Detects speech vs silence in audio slices
- Triggers auto-slice on speech_end events
- Configurable thresholds and presets
- Queue-based Processing:
- Transcription queue for sequential processing
- One transcription at a time
- Results stored by slice index
- Prompt Chaining:
- Optional initial prompt
- Can chain previous slice results as context
- Improves continuity in long transcriptions
- Audio Stream Adapters:
- Interface-based design for different audio sources
- Built-in:
AudioPcmStreamAdapter(uses @fugood/react-native-audio-pcm-stream) - Custom adapters can be implemented
iOS-Specific Features
Pre-built Framework:
- By default, uses
ios/rnwhisper.xcframework(pre-built) - Set
RNWHISPER_BUILD_FROM_SOURCE=1in Podfile to build from source - Framework includes Metal shaders (
.metallib)
Core ML Support:
- Accelerates encoder on iOS 15.0+
- Model files:
.mlmodelcdirectories (model.mil, coremldata.bin, weights/weight.bin) - Must be co-located with GGML model (e.g.,
ggml-tiny.en.bin→ggml-tiny.en-encoder.mlmodelc/) - Set
useCoreMLIos: falseto disable even if files exist
Build Flags:
RNWHISPER_DISABLE_COREML=1: Disable Core ML compilationRNWHISPER_DISABLE_METAL=1: Disable Metal GPU acceleration
Android-Specific Features
JNI Bridge: android/src/main/jni.cpp connects Java to C++ whisper core
Build Configuration:
- NDK version 24.0.8215888+ recommended for Apple Silicon Macs
- Supports 16KB page sizes (Android 15+)
- Proguard rule required:
-keep class com.rnwhisper.** { *; }
CMake Build: android/CMakeLists.txt controls native compilation
File Patterns and Conventions
Code Organization
- TypeScript:
src/(library),example/src/(example app) - Native iOS:
ios/*.{h,m,mm}(Objective-C/C++) - Native Android:
android/src/main/java/com/rnwhisper/*.java - C++ Core:
cpp/*.{cpp,h} - JSI Bindings:
cpp/jsi/*.{cpp,h} - Tests:
src/**/__tests__/*.test.ts
Naming Conventions
- Classes: PascalCase (
WhisperContext,RealtimeTranscriber) - Files: kebab-case for configs, PascalCase for classes
- Native modules: RNWhisper prefix (iOS/Android)
- C++ namespace:
rnwhisper - ggml/whisper.cpp symbols keep their upstream names (
ggml_*,whisper_*); the vendored sources are not renamed. Coexistence with other ggml-based libraries (e.g. llama.rn) relies on each library being its own dynamic image (two-level namespace on Apple,RTLD_LOCALplus-Bsymbolicon Android). The Objective-CGGMLMetalClassis process-global, so it is renamed per library with-DGGMLMetalClass=RNWhisperGGMLMetalClass.
Commit Messages
Follow Conventional Commits:
feat:new featuresfix:bug fixesrefactor:code refactoringdocs:documentationtest:testschore:tooling/build changes
Important Implementation Details
Audio Format Requirements
- Sample rate: 16kHz (whisper requirement)
- Channels: Mono (1 channel)
- Format: 16-bit PCM
- Input: WAV files, base64 WAV, or raw PCM data (base64 or ArrayBuffer)
Memory Management
- Contexts must be explicitly released:
context.release()orreleaseAllWhisper() - Realtime transcription: Use
maxSlicesInMemoryto control buffer size - Large models (medium/large) on iOS: Enable Extended Virtual Addressing entitlement
Performance Optimization
- Use quantized models (q8, q5) to reduce size and improve speed on mobile
- Default thread count: 2 for 4-core devices, 4 for more cores
- Test in Release mode for accurate performance measurement
- GPU/Metal acceleration: Set
useGpu: true(enabled by default)
Asset Handling
- Use
require()for bundled models/audio - Add
.binand.milto Metro configassetExts - Max file size: 2GB (RN packager limitation)
- Alternative: Download models at runtime
Deprecated APIs
transcribeRealtime(): UseRealtimeTranscriberinstead- Old API still works but lacks VAD auto-slicing and better memory management
Platform-Specific Notes
iOS
- Minimum iOS: 11.0, tvOS: 11.0
- Metal acceleration: iOS/tvOS only
- Audio Session management: Use
AudioSessionIosutilities oraudioSessionOnStartIos/audioSessionOnStopIosoptions - Microphone permission: Add
NSMicrophoneUsageDescriptionto Info.plist (tvOS: microphone not supported)
Android
- Microphone permission:
RECORD_AUDIOin AndroidManifest.xml - Use
PermissionsAndroidto request runtime permission - Supports both Old and New Architecture
Expo
- Requires prebuild:
npx expo prebuild - Follow standard React Native library integration
Testing
Unit Tests
- Jest with React Native preset
- Mock available:
jest.mock('whisper.rn', () => require('whisper.rn/jest-mock')) - Run:
npm test
Example App
- Located in
example/ - Uses tiny.en model and jfk.wav sample
- Demonstrates: Whisper and Parakeet transcription, VAD, realtime transcription
- Test realtime: Requires microphone permissions
Build System
Vendored sources (scripts/sync-vendor.sh)
- Clones/fetches the whisper.cpp commit pinned in
vendor/VERSIONSinto~/.cache/whisper.rn/ - Exports the subset whisper.rn builds into
vendor/whisper.cpp/, unchanged and in upstream layout - Applies
scripts/patches/whisper.cpp/*.patch - Regenerates
src/version.json(whisper/ggml versions + commit; the builds pass them asWHISPER_VERSION/PARAKEET_VERSION/GGML_VERSION/GGML_COMMITcompile definitions)
Its output is committed. Run it after changing vendor/VERSIONS or a patch; running it on a clean tree must produce no diff.
Patching whisper.cpp
- Edit the vendored file in place, e.g.
vendor/whisper.cpp/src/whisper.cpp - Regenerate its patch:
scripts/update-patch.sh src/whisper.cppwritesscripts/patches/whisper.cpp/whisper.cpp.patch(optional second argument names the patch; a file upstream lacks becomes a file-creating patch; text above the first---line survives regeneration, use it to say why) npm run sync:vendormust leavegit statusclean
Bootstrap (scripts/bootstrap.sh)
Developer environment only; it never touches vendor/:
example/dependencies- Example model/audio assets into
example/assets/(dummy models fromvendor/whisper.cpp/models/whenCI=true)
iOS Framework Build Process
- CMake generates Xcode project from
ios/CMakeLists.txt - Builds for multiple targets: iOS device, iOS simulator, tvOS device, tvOS simulator
- Creates universal
rnwhisper.xcframeworkwith all architectures - Includes Metal kernel sources (compiled at runtime) and the public C headers
- Script:
scripts/build-ios.sh
TypeScript Build
- Uses
react-native-builder-bob - Outputs: CommonJS, ES Module, TypeScript definitions
- Output dir:
lib/
Android Build
- Gradle + CMake
- NDK builds JNI library
- Output:
librnwhisper.so
Key Dependencies
Runtime
react-native: Core frameworkwhisper.cpp: C++ ASR engine (vendored atvendor/whisper.cpp/, seevendor/README.md)safe-buffer: Buffer polyfill
Realtime Transcription
@fugood/react-native-audio-pcm-stream: ForAudioPcmStreamAdapter- Filesystem module (e.g.,
react-native-fs): For WAV file writing
Development
react-native-builder-bob: TypeScript buildtypedoc+typedoc-plugin-markdown: API docs@commitlint,lefthook: Git hooksrelease-it: Publishing
Troubleshooting Common Issues
iOS Build Issues
- Clean derived data:
rm -rf ~/Library/Developer/Xcode/DerivedData - Clean build:
npm run clean && cd example/ios && pod install - Large models: Enable Extended Virtual Addressing entitlement
Android Build Issues
- Unknown host CPU on Apple Silicon: Use NDK 24.0.8215888+
- See
docs/TROUBLESHOOTING.mdfor more details
Performance Issues
- Use Release mode for testing
- Choose appropriate model size for device
- Adjust
maxThreadsif needed - Consider quantized models
Related Documentation
- API Docs:
docs/API/ - Tips & Tricks:
docs/TIPS.md - Troubleshooting:
docs/TROUBLESHOOTING.md - Contributing:
CONTRIBUTING.md - whisper.cpp upstream: https://github.com/ggerganov/whisper.cpp
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

