Local-first voice dictation Chrome extension
13
stars
10
commits
JavaScript
primary language
Aug 28, 2026
updated

Local-first multilingual dictation powered by Gemma 4 E2B. Speak in any language, get polished text. Audio never leaves your device.
π Winner of 2nd prize at the Build with Gemma hackathon (Kolkata): project writeup on Kaggle.
WisprGemma is a WisprFlow-style dictation tool that runs entirely in the browser on WebGPU. I built it for anyone who wants fast voice-to-text without sending audio to a cloud API: no subscription, no API key, works offline after a one-time model download (~3.5 GB, q4f16).
One Gemma 4 model handles the full pipeline in a single pass: speech recognition, cleanup, and rewriting. No Whisper, no backend.
Pick a mode before you speak. Each one is a different prompt to the same model, not a separate pipeline.
| Mode | What you get | Best for |
|---|---|---|
| Clean dictation | Transcript with fillers removed, false starts cut, punctuation fixed. Spoken commands like "new paragraph" or "make that a bullet list" are applied, not transcribed. | Notes, docs, general dictation |
| Verbatim | Exact transcript as spoken, no cleanup | Capturing raw speech, interviews |
| Polished email | Rewritten as a concise, professional email body with grammar and punctuation fixed | Drafting emails by voice |
| Any language β English | Transcribes speech in any language and outputs polished English | Multilingual input, translation-style dictation |
| Custom style (extension only) | Transcribes first, then rewrites to follow a one-line instruction you type (e.g. "translate to German", "formal tone, short sentences") | One-off styles the presets don't cover |
Pick Custom style⦠in the dropdown to reveal a prompt box (500 characters max). Your instruction is saved locally and stays filled in the next time you open the panel; leave it empty to fall back to Clean dictation.
Web app (web/) | Chrome extension (extension/) | |
|---|---|---|
| Dictation | Hold button or Space, streaming output | Side panel + β+Shift+D (macOS) / Alt+Shift+D push-to-talk on the active page |
| Insert text | Copy from output area | Inserts into focused input, textarea, or contenteditable |
| Privacy | 100% on-device inference | Same: audio never leaves your machine |
| Stats | Words dictated, WPM, time saved, streak, 14-day chart | Separate dashboard for extension usage |
| Offline | Works after first model load | Same (separate cache per origin) |
| Extras | Editorial UI, per-utterance latency stats | Dictation history, mic permission helper tab, first-run welcome page, β/Ctrl+Shift+Space shortcut, toolbar recording badge |
npm run serve:web
Open http://localhost:3000 for the landing page, then Open the app (or go straight to /app.html). Click Load model, allow the microphone, hold Space and speak.
Requires Chrome or Edge 121+ with WebGPU enabled. First load downloads ~3.5 GB, then spends a few minutes uploading weights to the GPU.
Try it online β the web app is also deployed to GitHub Pages at https://arindam200.github.io/WisprGemma/ (a landing page with a link into the dictation tool), no install needed (same browser and download requirements apply). If you fork this repo, enable it once under Settings β Pages β Source: GitHub Actions and the deploy workflow publishes web/ on every push to main.
chrome://extensions, enable Developer modeextension/ folder β a welcome tab opens automatically on first installnpm run download-model
Downloads weights into web/models/ and serves them on port 8975. Leave it running while developing. Both the web app and extension auto-detect it.
Mic (MediaRecorder)
β decode to 16 kHz mono Float32
β worker.js (Transformers.js + Gemma 4 E2B on WebGPU)
β streamed tokens back to UI
β display / insert into page / log stats
Vanilla HTML/CSS/JS, no build step. A module Web Worker runs inference so the UI stays responsive while a 3.5 GB model loads.
Model: onnx-community/gemma-4-E2B-it-ONNX, q4f16, WebGPU via Transformers.js 4.2.0. Weights download from Hugging Face Hub on first load, then cache in the browser. Recordings stop at 30 seconds; automatic segmentation is not implemented yet.
The extension adds MV3-specific workarounds: vendored Transformers.js and ONNX Runtime WASM, plus a one-time mic permission page (Chrome cannot prompt inside the side panel).
| Layer | Technology |
|---|---|
| Model | Gemma 4 E2B instruction-tuned (gemma-4-E2B-it) |
| Inference | Transformers.js 4.2.0 |
| Runtime | WebGPU (Chrome / Edge 121+) |
| Model format | ONNX, q4f16 quantized |
| Web app | HTML, CSS, vanilla JS, ES module Web Worker |
| Extension | Chrome Manifest V3, Side Panel API, content scripts |
| Audio | MediaRecorder β Web Audio API decode β 16 kHz mono Float32 |
| Storage | localStorage (stats and cache marker) + chrome.storage.local (history and preferences) |
wisprgemma/
βββ web/ Landing page (index.html), dictation app (app.html), stats dashboard
βββ extension/ Chrome MV3 extension
βββ .github/workflows/ GitHub Pages deploy workflow
βββ package.json Convenience scripts
βββ PRIVACY.md Privacy policy (linked from the Chrome Web Store listing)
βββ serve.json Static server config
See web/README.md and extension/README.md for package-specific notes.
System-wide dictation: hold a key, speak, and polished text lands at your cursor in any app β same local Gemma pipeline, plus optional Ollama cleanup and bring-your-own-key cloud engines (OpenAI / Groq / Gemini).
cd desktop && npm install && npm start
See desktop/README.md for setup (permissions, engines) and DESKTOP_PLAN.md for the architecture and roadmap.
Audio is captured locally, processed locally, and never sent to a server. Stats and history live in browser storage on your machine only. See PRIVACY.md for the full policy.
10 commits
JavaScript
37.9%
TypeScript
27.2%
CSS
21.2%
HTML
13.4%
Local-first voice dictation Chrome extension
13
stars
10
commits
JavaScript
primary language
Aug 28, 2026
updated

Local-first multilingual dictation powered by Gemma 4 E2B. Speak in any language, get polished text. Audio never leaves your device.
π Winner of 2nd prize at the Build with Gemma hackathon (Kolkata): project writeup on Kaggle.
WisprGemma is a WisprFlow-style dictation tool that runs entirely in the browser on WebGPU. I built it for anyone who wants fast voice-to-text without sending audio to a cloud API: no subscription, no API key, works offline after a one-time model download (~3.5 GB, q4f16).
One Gemma 4 model handles the full pipeline in a single pass: speech recognition, cleanup, and rewriting. No Whisper, no backend.
Pick a mode before you speak. Each one is a different prompt to the same model, not a separate pipeline.
| Mode | What you get | Best for |
|---|---|---|
| Clean dictation | Transcript with fillers removed, false starts cut, punctuation fixed. Spoken commands like "new paragraph" or "make that a bullet list" are applied, not transcribed. | Notes, docs, general dictation |
| Verbatim | Exact transcript as spoken, no cleanup | Capturing raw speech, interviews |
| Polished email | Rewritten as a concise, professional email body with grammar and punctuation fixed | Drafting emails by voice |
| Any language β English | Transcribes speech in any language and outputs polished English | Multilingual input, translation-style dictation |
| Custom style (extension only) | Transcribes first, then rewrites to follow a one-line instruction you type (e.g. "translate to German", "formal tone, short sentences") | One-off styles the presets don't cover |
Pick Custom style⦠in the dropdown to reveal a prompt box (500 characters max). Your instruction is saved locally and stays filled in the next time you open the panel; leave it empty to fall back to Clean dictation.
Web app (web/) | Chrome extension (extension/) | |
|---|---|---|
| Dictation | Hold button or Space, streaming output | Side panel + β+Shift+D (macOS) / Alt+Shift+D push-to-talk on the active page |
| Insert text | Copy from output area | Inserts into focused input, textarea, or contenteditable |
| Privacy | 100% on-device inference | Same: audio never leaves your machine |
| Stats | Words dictated, WPM, time saved, streak, 14-day chart | Separate dashboard for extension usage |
| Offline | Works after first model load | Same (separate cache per origin) |
| Extras | Editorial UI, per-utterance latency stats | Dictation history, mic permission helper tab, first-run welcome page, β/Ctrl+Shift+Space shortcut, toolbar recording badge |
npm run serve:web
Open http://localhost:3000 for the landing page, then Open the app (or go straight to /app.html). Click Load model, allow the microphone, hold Space and speak.
Requires Chrome or Edge 121+ with WebGPU enabled. First load downloads ~3.5 GB, then spends a few minutes uploading weights to the GPU.
Try it online β the web app is also deployed to GitHub Pages at https://arindam200.github.io/WisprGemma/ (a landing page with a link into the dictation tool), no install needed (same browser and download requirements apply). If you fork this repo, enable it once under Settings β Pages β Source: GitHub Actions and the deploy workflow publishes web/ on every push to main.
chrome://extensions, enable Developer modeextension/ folder β a welcome tab opens automatically on first installnpm run download-model
Downloads weights into web/models/ and serves them on port 8975. Leave it running while developing. Both the web app and extension auto-detect it.
Mic (MediaRecorder)
β decode to 16 kHz mono Float32
β worker.js (Transformers.js + Gemma 4 E2B on WebGPU)
β streamed tokens back to UI
β display / insert into page / log stats
Vanilla HTML/CSS/JS, no build step. A module Web Worker runs inference so the UI stays responsive while a 3.5 GB model loads.
Model: onnx-community/gemma-4-E2B-it-ONNX, q4f16, WebGPU via Transformers.js 4.2.0. Weights download from Hugging Face Hub on first load, then cache in the browser. Recordings stop at 30 seconds; automatic segmentation is not implemented yet.
The extension adds MV3-specific workarounds: vendored Transformers.js and ONNX Runtime WASM, plus a one-time mic permission page (Chrome cannot prompt inside the side panel).
| Layer | Technology |
|---|---|
| Model | Gemma 4 E2B instruction-tuned (gemma-4-E2B-it) |
| Inference | Transformers.js 4.2.0 |
| Runtime | WebGPU (Chrome / Edge 121+) |
| Model format | ONNX, q4f16 quantized |
| Web app | HTML, CSS, vanilla JS, ES module Web Worker |
| Extension | Chrome Manifest V3, Side Panel API, content scripts |
| Audio | MediaRecorder β Web Audio API decode β 16 kHz mono Float32 |
| Storage | localStorage (stats and cache marker) + chrome.storage.local (history and preferences) |
wisprgemma/
βββ web/ Landing page (index.html), dictation app (app.html), stats dashboard
βββ extension/ Chrome MV3 extension
βββ .github/workflows/ GitHub Pages deploy workflow
βββ package.json Convenience scripts
βββ PRIVACY.md Privacy policy (linked from the Chrome Web Store listing)
βββ serve.json Static server config
See web/README.md and extension/README.md for package-specific notes.
System-wide dictation: hold a key, speak, and polished text lands at your cursor in any app β same local Gemma pipeline, plus optional Ollama cleanup and bring-your-own-key cloud engines (OpenAI / Groq / Gemini).
cd desktop && npm install && npm start
See desktop/README.md for setup (permissions, engines) and DESKTOP_PLAN.md for the architecture and roadmap.
Audio is captured locally, processed locally, and never sent to a server. Stats and history live in browser storage on your machine only. See PRIVACY.md for the full policy.
10 commits
JavaScript
37.9%
TypeScript
27.2%
CSS
21.2%
HTML
13.4%