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 calls whistle() from engine.ts.
  • React SDK: packages/react/src/index.ts re‑exports whistle and exposes useWhistle hooks.
  • Demo: packages/demo/src/main.tsx bootstraps the React app, which mounts App.tsx.

INTERNAL CALL GRAPH

  1. App.tsx → useWhistleDemo (helper in demo/src/useWhistleDemo.ts).
  2. useWhistleDemo uses the exported whistle from the SDK.
  3. whistle (in whistle/src/engine.ts) spawns a worker: - In the browser: whistle/src/browser-worker.ts running browser.ts. - In Node: whistle/src/node-worker.ts running node.ts.
  4. The worker loads assets (whistle/src/assets.ts) and runs the Whisper model.
  5. 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.ts writes and reads model files in packages/whistle/.cache/assets.
  • Network: the CLI can fetch model weights from the vendor URL (handled in install.ts).
  • Browser APIs: microphone.ts uses navigator.mediaDevices.getUserMedia.
  • Node APIs: node.ts uses fs and child_process for 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/tests and packages/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.json dependencies 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.