The Problem
Web and Node applications often rely on cloud‑based STT services, adding latency, cost, and privacy concerns. Tiny‑STT provides a lightweight, local STT SDK that can be embedded in the browser or a Node process without external dependencies.
What This Does
Tiny‑STT ships three npm packages:
@tiny-stt/whistle(packages/whistle/) – a TypeScript/ESM SDK and CLI that wraps the Whisper‑derived model.@tiny-stt/react(packages/react/) – React 19 hooks that expose the SDK as a peer dependency.@tiny-stt/demo(packages/demo/) – a Vite + React demo that shows how to record and transcribe audio in the browser.
The core logic lives in packages/whistle/src/*.ts. The engine (engine.ts) starts a web or node worker, loads model weights via assets.ts, and exposes a whistle() function that streams audio to the worker and returns a transcript.
How It Is Wired
ENTRY POINTS
- CLI:
packages/whistle/src/cli.ts– parses arguments and callswhistle()fromengine.ts. - React SDK:
packages/react/src/index.tsre‑exportswhistleand exposesuseWhistlehooks. - Demo:
packages/demo/src/main.tsxbootstraps the React app, which mountsApp.tsx.
INTERNAL CALL GRAPH
App.tsx→useWhistleDemo(helper indemo/src/useWhistleDemo.ts).useWhistleDemouses the exportedwhistlefrom the SDK.whistle(inwhistle/src/engine.ts) spawns a worker: - In the browser:whistle/src/browser-worker.tsrunningbrowser.ts. - In Node:whistle/src/node-worker.tsrunningnode.ts.- The worker loads assets (
whistle/src/assets.ts) and runs the Whisper model. - The worker streams audio chunks and returns a transcript that bubbles back to the SDK, then to the React hook, and finally to the UI.
WHAT THIS CODE TOUCHES OUTSIDE ITSELF
- File system:
whistle/src/assets.tswrites and reads model files inpackages/whistle/.cache/assets. - Network: the CLI can fetch model weights from the vendor URL (handled in
install.ts). - Browser APIs:
microphone.tsusesnavigator.mediaDevices.getUserMedia. - Node APIs:
node.tsusesfsandchild_processfor local worker execution.
WHAT EACH FILE IS RESPONSIBLE FOR
cli.ts– entry for command‑line usage.engine.ts– orchestrates worker lifecycle and API.browser.ts/node.ts– worker entry points for each environment.assets.ts– resolves, downloads, and caches model binaries.validation.ts– schema checks for options.react/src/index.ts– re‑exports SDK functions and declares React hooks.demo/src/App.tsx– UI logic and state.
The module graph contains a single hub in engine.ts; any change to worker handling must touch that file. No cycles are present, so refactoring the worker logic is isolated.
How To Use It
Setup
git clone https://github.com/moses-y/tiny-stt
cd tiny-stt
pnpm install --frozen-lockfile
Prepare assets
pnpm assets:prepare # downloads model weights into packages/whistle/.cache/assets
Run the demo
pnpm demo:prepare
pnpm demo:dev # opens http://127.0.0.1:5173/
Use the SDK in Node
pnpm example:node # runs the Node example in packages/documentation/examples/node/
The CLI can be invoked directly:
npx @tiny-stt/whistle --help
Real‑World Use
A transcription microservice that receives audio uploads, calls whistle() from the SDK, and stores the resulting text in a database. The same function can run in a client‑side React component to provide instant captioning for a video call.
import { whistle } from '@tiny-stt/whistle'
const transcript = await whistle(audioBlob, { language: 'en' })
await db.saveTranscript(transcript)
Code Health & Issues
- Tests: 25 files under
packages/whistle/testsandpackages/react/tests. - CI: GitHub Actions defined in
.github/workflows/ci.yml. - Linting: Biome 2.5.15 configured in
biome.jsonc. - No lint or type errors reported by
pnpm check. - License: MIT in
LICENSE. - No missing
package.jsondependencies or orphaned files.
The Bottom Line
Tiny‑STT delivers a minimal, local STT solution with a clear, single‑hub architecture. The React wrapper and demo provide immediate proof of concept. For teams needing privacy‑preserving or offline STT, the SDK is ready for integration; for larger models or heavy traffic, consider supplementing with a dedicated inference server.