Package Exports
- whisper-web-transcriber
Readme
Whisper Web Transcriber
Real-time audio transcription in the browser using OpenAI's Whisper model via WebAssembly. This package provides an easy-to-use API for integrating speech-to-text capabilities into web applications without any server-side processing.
Live Demo 🎙️
Features
- 🎙️ Real-time audio transcription from microphone
- 🌐 Runs entirely in the browser (no server required)
- 📦 Multiple Whisper model options (tiny, base, quantized versions)
- 💾 Automatic model caching in IndexedDB
- 🔧 Simple, promise-based API
- 📱 Works on all modern browsers with WebAssembly support
- 🌍 Platform-independent (same WASM works on all OS)
Installation
NPM Package
npm install whisper-web-transcriberOr using yarn:
yarn add whisper-web-transcriberCDN Usage (Bundled Version)
<!-- Single file with all dependencies included -->
<script src="https://unpkg.com/whisper-web-transcriber/dist/index.bundled.min.js"></script>Quick Start
Using NPM Package
import { WhisperTranscriber } from 'whisper-web-transcriber';
const transcriber = new WhisperTranscriber({
modelSize: 'base-en-q5_1',
onTranscription: (text) => {
console.log('Transcribed:', text);
}
});
await transcriber.loadModel();
await transcriber.startRecording();Using CDN (Bundled Version)
<script src="https://unpkg.com/whisper-web-transcriber/dist/index.bundled.min.js"></script>
<script>
const transcriber = new WhisperTranscriber.WhisperTranscriber({
modelSize: 'base-en-q5_1',
onTranscription: (text) => {
console.log('Transcribed:', text);
}
});
transcriber.loadModel().then(() => {
transcriber.startRecording();
});
</script>API Reference
Constructor Options
interface WhisperConfig {
modelUrl?: string; // Custom model URL (optional)
modelSize?: 'tiny.en' | 'base.en' | 'tiny-en-q5_1' | 'base-en-q5_1';
sampleRate?: number; // Audio sample rate (default: 16000)
audioIntervalMs?: number; // Audio processing interval (default: 5000ms)
onTranscription?: (text: string) => void;
onProgress?: (progress: number) => void;
onStatus?: (status: string) => void;
debug?: boolean; // Enable debug logging (default: false)
}Methods
loadModel(): Promise<void>- Downloads and initializes the Whisper modelstartRecording(): Promise<void>- Starts microphone recording and transcriptionstopRecording(): void- Stops recordingdestroy(): void- Cleanup resourcesgetServiceWorkerCode(): string | null- Returns the COI service worker code (bundled version only)getCrossOriginIsolationInstructions(): string- Returns setup instructions for Cross-Origin Isolation
Model Options
| Model | Size | Description |
|---|---|---|
tiny.en |
75 MB | Fastest, lower accuracy |
base.en |
142 MB | Better accuracy, slower |
tiny-en-q5_1 |
31 MB | Quantized tiny model, smaller size |
base-en-q5_1 |
57 MB | Quantized base model, good balance |
Browser Requirements
- WebAssembly support
- SharedArrayBuffer support (requires Cross-Origin Isolation)
- Microphone access permission
- Modern browser (Chrome 90+, Firefox 89+, Safari 15+, Edge 90+)
Cross-Origin Isolation Setup
WhisperTranscriber requires SharedArrayBuffer, which needs Cross-Origin Isolation. You have two options:
Option 1: Server Headers (Recommended)
Configure your server to send these headers:
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-originOption 2: Service Worker
If you can't modify server headers, use the included service worker:
For NPM users:
<!-- Include at the top of your HTML -->
<script src="node_modules/whisper-web-transcriber/dist/coi-serviceworker.js"></script>For CDN users:
// Get the service worker code
const transcriber = new WhisperTranscriber.WhisperTranscriber();
const swCode = transcriber.getServiceWorkerCode();
// Save swCode as 'coi-serviceworker.js' on YOUR domain
// Then include it in your HTML:
// <script src="/coi-serviceworker.js"></script>Important: Service workers must be served from the same origin as your page. CDN users cannot directly use the service worker from unpkg.
Serving with proper headers
For local development:
npm run demoFor production (examples):
Vercel (vercel.json):
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Cross-Origin-Embedder-Policy",
"value": "require-corp"
},
{
"key": "Cross-Origin-Opener-Policy",
"value": "same-origin"
}
]
}
]
}Nginx:
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;Complete Examples
Example 1: Using NPM Package
<!DOCTYPE html>
<html>
<head>
<title>Whisper Transcriber - NPM Version</title>
<!-- Include service worker for Cross-Origin Isolation -->
<script src="node_modules/whisper-web-transcriber/dist/coi-serviceworker.js"></script>
</head>
<body>
<button id="start">Start Recording</button>
<button id="stop">Stop Recording</button>
<div id="transcription"></div>
<script type="module">
import { WhisperTranscriber } from './node_modules/whisper-web-transcriber/dist/index.esm.js';
const transcriber = new WhisperTranscriber({
modelSize: 'tiny-en-q5_1',
onTranscription: (text) => {
document.getElementById('transcription').textContent += text + ' ';
}
});
document.getElementById('start').onclick = async () => {
await transcriber.loadModel();
await transcriber.startRecording();
};
document.getElementById('stop').onclick = () => {
transcriber.stopRecording();
};
</script>
</body>
</html>Example 2: Using CDN (Bundled Version)
<!DOCTYPE html>
<html>
<head>
<title>Whisper Transcriber - CDN Version</title>
<!-- Note: You still need to handle Cross-Origin Isolation -->
<!-- Either configure server headers OR save and include the service worker -->
</head>
<body>
<button id="start">Start Recording</button>
<button id="stop">Stop Recording</button>
<div id="transcription"></div>
<!-- Single script include -->
<script src="https://unpkg.com/whisper-web-transcriber/dist/index.bundled.min.js"></script>
<script>
const transcriber = new WhisperTranscriber.WhisperTranscriber({
modelSize: 'tiny-en-q5_1',
onTranscription: (text) => {
document.getElementById('transcription').textContent += text + ' ';
}
});
// Check if Cross-Origin Isolation is enabled
if (!window.crossOriginIsolated) {
console.log(transcriber.getCrossOriginIsolationInstructions());
}
document.getElementById('start').onclick = async () => {
await transcriber.loadModel();
await transcriber.startRecording();
};
document.getElementById('stop').onclick = () => {
transcriber.stopRecording();
};
</script>
</body>
</html>Bundled vs Standard Version
Bundled Version (index.bundled.js)
- ✅ Single file - All workers and dependencies included
- ✅ CDN-friendly - No CORS issues with web workers
- ✅ Zero configuration - Works out of the box (except for Cross-Origin Isolation)
- ❌ Larger initial download - ~220KB uncompressed, ~95KB minified
- 📦 Best for: Quick prototypes, CDN usage, simple deployments
Standard Version (index.js)
- ✅ Smaller initial size - Core library only
- ✅ Modular loading - Workers loaded on demand
- ❌ Requires all files - Must serve worker files from same origin
- ❌ More complex setup - Need to copy files from node_modules
- 📦 Best for: Production apps with bundlers, optimized loading
Performance Considerations
- Transcription is CPU-intensive
- Larger models provide better accuracy but require more processing power
- Quantized models (Q5_1) offer good balance between size and quality
- First-time model loading may take time (models are cached afterward)
Troubleshooting
"SharedArrayBuffer is not defined"
You need to enable Cross-Origin Isolation. See the Cross-Origin Isolation Setup section.
"Failed to load worker" when using CDN
Use the bundled version (index.bundled.min.js) instead of the standard version.
"Microphone access denied"
Ensure your site is served over HTTPS (or localhost) and the user has granted microphone permissions.
Service worker not working
- Service workers must be served from the same origin as your page
- Check browser console for specific error messages
- Ensure the service worker file is accessible at the correct path
Technical Details
Built using:
- whisper.cpp compiled to WebAssembly
- Web Audio API for microphone access
- IndexedDB for model caching
- Service Worker for Cross-Origin Isolation
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Acknowledgments
- whisper.cpp by Georgi Gerganov
- OpenAI Whisper for the original model