Skip to content

Voice to Text

Prov1.3.0

Turn voice notes and recordings into text, fully on-device

Voice to Text is a Pro app

It needs a free KimtOS account and a Pro subscription. Everything still runs on your device — Pro unlocks the app, it does not send your data anywhere. Install it without Pro and the app opens to an upgrade wall. See what Pro includes

Overview

Voice to Text turns spoken audio into text. Record a voice note from your microphone or import an existing audio file, and the app transcribes it and hands you back a copy-ready transcript. It is part of the kimtos new-tab app suite.

Everything is fully on-device. There is no backend, no account, and no upload: the speech-recognition model runs inside your browser, and both your audio and the resulting transcripts stay on the machine.

Highlights

  • Record or import — capture a voice note from your microphone, or drop in an audio file (mp3, m4a, wav, ogg, opus, and more).
  • On-device transcription — speech is recognized locally with a Whisper model running on WebAssembly; nothing is sent to a server.
  • Transcript card — the finished text in a labelled card with a word count, Copy, Download .txt, and Start over.
  • History sidebar — every transcript is saved with its original recording, so you can reopen it, replay the audio, and copy the text later.
  • Multi-select delete — switch the sidebar into select mode (or drag across rows) to remove several transcripts at once, with one-tap undo.
  • Model & language settings — choose Tiny (fast, smaller download) or Base (more accurate), and optionally pin a language or leave it on auto-detect.
  • Hand off to Denoise — if the Denoise app is installed, send a recording there to clean it up before or after transcribing.

Privacy model

Voice to Text never uploads your audio:

  • Transcription runs in your browser via WebAssembly — the recording is decoded and recognized entirely on-device.
  • The model downloads once. The first run fetches the model files (about 145 MB for Tiny, 280 MB for Base). After that they are cached, so later runs work offline with no further download.
  • Your data stays local. Transcripts and their recordings live in your browser's local storage; there are no servers, accounts, or third-party calls.

Accuracy

Whisper supports many languages, but English is the most accurate. Leaving the language blank lets the model auto-detect; if you know the language, setting it explicitly (e.g. en, ar) can help. The Base model is more accurate than Tiny at the cost of a larger download and more memory while transcribing.

Getting Started

Open Voice to Text from the dock. You start on the input screen, ready to record or import a voice note.

Provide audio

There are two ways to give the app something to transcribe:

  • Record — click the microphone to start capturing, with a live timer; click again to stop. The clip appears in a small player so you can preview it. Two independent switches beside the button choose what is captured, Mic and System — either, or both. System audio alone never asks for your microphone, so a call playing in another window can be transcribed with the mic blocked or missing; during a recording the switches mute and unmute each source instead.
  • Import — click the dropzone to pick an audio file, or drag and drop one onto it. Common formats are supported (mp3, m4a, wav, ogg, opus, flac, and more).

If the audio source goes away while you are recording — you end the screen share, or another app takes the microphone — the recording stops there and tells you why, keeping everything captured up to that point. It never keeps running against a source that is no longer sending anything.

When a clip is ready, click Extract text to transcribe it.

Progress steps

Transcription shows a progress bar that moves through a few phases:

  1. Downloading model — only on the first run (or after changing the model). A progress bar tracks the download; once cached, this step is skipped.
  2. Decoding audio — your clip is decoded to the format the model expects.
  3. Transcribing — the model recognizes the speech and produces text.

The transcript card

When it finishes, you get a transcript card showing the recognized text and a word count, plus:

  • Copy — copy the full transcript to the clipboard.
  • Download .txt — save the text as transcript.txt.
  • Start over — return to the input screen for a new recording.

The original recording sits above the transcript with a player, so you can replay it while reading. A recording with no sound in it is never handed to the model — the card shows No speech detected rather than a transcript of silence.

History sidebar

Every successful transcript is saved to the history sidebar on the left, newest first, with a short snippet of the text. From here you can:

  • Open a past transcript to view its text and replay its audio.
  • Copy text or Download .txt from the row's menu.
  • Delete several at once — click Select (or just drag across rows), tick the transcripts you want, then Delete (N). A toast lets you undo for a few seconds.

History keeps the most recent transcripts (older ones are trimmed automatically).

Settings

Open the app's settings (Settings ▸ Apps) to adjust:

  • ModelTiny (fast, ~145 MB) or Base (more accurate, ~280 MB). Larger is more accurate but means a bigger download and more memory.
  • Language — leave blank to auto-detect, or set a code like en or ar.
  • Record my microphone and Record system audio — two independent switches; any combination is valid. You also set them each time you record. On macOS Chrome can capture a tab's audio but not another application's.

First-run model download

The very first transcription (or the first after switching models) downloads the model once. The suite's onboarding can warm this up ahead of time by prefetching the model in the background, so your first real transcription is instant. Either way, once the files are cached the app works offline and only uses memory while it is actively transcribing.

Architecture

Voice to Text follows the suite convention: the app itself is a thin descriptor built on a shared factory, and the heavy lifting is a self-contained, on-device transcription engine. The code lives in extension/src/apps/televoica/.

Modules

FileRole
apps/televoica/index.tsThe app descriptor — name, accent, settings (model, language, recording source), and the audio-input and transcribe wiring. Built by the shared factory.
lib/createMediaTextApp.tsThe "media in → text out" factory — input screen, live progress, the transcript card, the history sidebar, and multi-select delete.
lib/engines/transcribe.tsThe transcription engine — loads Whisper via Transformers.js (WebAssembly), decodes audio, runs recognition, and disposes the session.
lib/speechSpans.tsThe speech gate — finds the stretches of a recording that hold speech, so the quiet ones are never shown to the model.
lib/engines/transcriptFormat.tsTranscript assembly — paragraphs from the model's segments, plus the repetition and density guards that catch invented text.
components/audioInput.tsThe reusable audio input — record from the mic (with a timer) or drag/drop and import a file.
components/resultView.tsThe transcript card — text area, word count, and Copy / Download / Start over actions.
components/historySidebar.tsThe history sidebar — list of past transcripts with open, per-row menu, and drag/select bulk delete.
lib/dataStore.tsThe local data store — transcript records and their audio blobs, kept in IndexedDB.

Data flow

The factory collects a clip from the audio input, runs it through transcribeAudio, and renders the result. On success it saves the transcript text and the original recording to the per-app history, so a past run can be reopened and replayed.

The transcription engine

engines/transcribe.ts runs entirely on-device:

  • Model. A Whisper automatic-speech-recognition pipeline is loaded with @huggingface/transformers, on the wasm device with fp32 weights. (The quantized exports of these models ship broken scales that crash the runtime, so full precision is used for reliability.)
  • Audio decoding. Any browser-supported clip is decoded to the mono 16 kHz Float32 samples Whisper expects, mixing down multi-channel audio.
  • The speech gate. Whisper never declines: shown silence or room tone it invents text, and once it starts it repeats one phrase for hundreds of characters. So speechSpans measures the samples first and returns only the stretches that hold speech; each is transcribed on its own and everything between them is withheld from the model. A recording with no speech in it never loads the model at all, and shows "No speech detected".
  • Recognition. Each stretch is transcribed in 30-second chunks with overlap; an optional language is passed through when set.
  • The output guards. Energy alone cannot tell a voice from music, so the transcript is checked as well: a phrase repeated four times or more is collapsed to one, and a long stretch of sound that comes back as a couple of words is dropped rather than shown. Both are pure functions in engines/transcriptFormat.ts.
  • Caching & memory. The model files are cached after the first download (in Cache Storage), so later runs need no network. The in-memory session is the heavy part (hundreds of MB), so the pipeline is disposed after each run to free the tab's memory while idle — the cached files keep the next run fast.

Onboarding can call prefetchModel to download and cache the model ahead of time (then immediately dispose the session), so the first real transcription is instant.

Persistence

Each transcript is one IndexedDB record alongside a blob for its recording:

{ id, text, at, blobKey, mime, name }   // record
blobKey -> the original audio clip       // blob

The list is capped to the most recent entries; older ones are trimmed on save. Deleting a transcript removes its record and its audio blob. Uninstalling the app can clear the whole history collection and its blobs, and free the cached Whisper model files.

Changelog

1.3.0 — 2026-08-17

  • Mic and System audio are two independent switches now, not one either/or choice: record either, or both at once.
  • System audio on its own never asks for your microphone, so a call playing in another window can be transcribed even when your mic is blocked or missing.
  • A microphone the browser or your operating system is blocking now says so, and names the setting to change, instead of the recording quietly failing.
  • Either source can be muted and unmuted during a recording without ending it.

1.2.1 — 2026-07-23

  • Transcripts no longer contain sentences that were never spoken: the quiet parts of a recording are found first and never sent to the model, which is what it was inventing from
  • A phrase repeated over and over is recognised as the model getting stuck and collapsed to one, instead of filling the transcript
  • A recording that holds no speech now says "No speech detected" rather than returning made-up text

1.2.0 — 2026-07-22

  • Transcripts now come out in paragraphs — a pause in the speech starts a new one — instead of one unbroken line, so the downloaded text file is readable too