← all apps

maha-transcriber-reader

Maha Transcriber and Reader - speech to text and text to speech in one page. Keys stay on your device.

runs onWebtechnologyHTML, one page, Expo / React Native, Groq, Gemini, AssemblyAI, Edge TTSrepositoryhttps://github.com/markoboskoauroville/maha-transcriber-readerlast push2026-08-06
GitHubopen the app
# Maha Transcriber and Reader

Two tools that live in one page. **Transcribe** turns what you say into text.
**Read** speaks text back to you and lights up each word as it is said. They
sit side by side and you can send text from one to the other.

**Open it:** https://markoboskoauroville.github.io/maha-transcriber-reader/

Nothing to install. Your keys stay on your own machine.

---

## First five minutes

1. Open the page.
2. Click the **gear** on the transcribe side.
3. **LOAD KEYS FROM FILE** and pick a plain text file from your disk that has
   your API keys in it. Any layout will do — see below.
4. Press **TEST ALL**. Keys that work say so.
5. Press **REC**, talk, press it again. The text appears and the page moves you
   to the transcribe tab.

For reading you need no keys at all. Paste text into the **paste** tab and it
starts speaking immediately in your computer's own voice. Better voices are one
click away if you have a key — see below.

---

## Voices: eight providers, four free and four premium

The reader speaks with your computer's own voice by default: no key, no
network, no cost. Pick a different provider at the top of the **text** tab and
load a key to upgrade.

Each one was chosen against three tests rather than reputation.

**Does it work from a browser at all?** Every provider here was checked with a
real CORS preflight from this site. Hugging Face's inference API and Replicate
send no allow-origin header, so a page cannot call them however good they are.
They are not listed.

**Does it speak Croatian?** Several of 2026's favourites — Cartesia, Deepgram
Aura — are English-first. They are excellent and they are not here.

**Is it honestly in its category?** "Free" means a real free tier or open
weights, not a trial.

### Free

| | why it is here | Croatian |
|---|---|---|
| **Browser** *(default)* | no key, offline, and the only engine that reports each word exactly as spoken | if your OS has a Croatian voice |
| **Gemini TTS** | Google's free tier, expressive, and the same key the grammar buttons use | not listed; it will try |
| **Groq PlayAI** | a genuinely free tier and the fastest of them all | no |
| **DeepInfra Kokoro** | Kokoro-82M, open weights, pennies an hour | no |

### Premium

| | why it is here | Croatian |
|---|---|---|
| **Azure Speech** | **Gabrijela and Srecko — the same voices the desktop app uses**, because edge-tts *is* this service. 140+ languages, cheapest premium option | **yes, two native voices** |
| **ElevenLabs** | the most expressive voices made, 70+ languages | **yes** |
| **OpenAI** | 50+ languages, and you describe how to read rather than marking up text | yes, English-tuned |
| **Google Cloud TTS** | native Croatian neural voices, 1M free characters a month | **yes** |

**If you read Croatian, use Azure.** It is the same voice you already know from
the desktop app, and it is the cheapest of the four.

**One honest limit.** Only the browser engine reports when each word is
actually spoken. API voices arrive as finished audio, so words are placed
against the clip's duration — accurate to about a word, and the interface says
"word timing estimated" when that is what you are getting. The desktop build
reads the waveform and lands within 8 ms.

---

## Cookies must be allowed, or the keys are forgotten

There is no server, so there is nowhere else to keep your keys. They are stored
in a **cookie on your own device**. If cookies are blocked for this site, the
app still works but you will have to load the key file again on every visit,
and an orange bar at the top will tell you so.

**Allowing cookies:**

* **Chrome / Edge** — click the icon at the left of the address bar →
  *Cookies and site data* → *Allow*
* **Safari** — Settings → Privacy → untick *Block all cookies*
* **Firefox** — the shield icon in the address bar → turn protection off for
  this site
* **Brave** — the lion icon → *Shields down* for this site

The cookie never leaves your browser. Keys are sent only to the provider they
belong to — AssemblyAI or Google — and never to this site, which is a folder of
static files with no back end at all.

Press **FORGET KEYS** in settings to erase them.

---

## The key file

Point the app at any text file. It reads the whole thing, picks out anything
that looks like a key, sorts it by provider and ignores everything else. Notes,
invoices, URLs and prose in the same file are all fine.

```
assemblyai
  3d6bffd8aa11bb22cc33dd44ee55ae3e

gemini
  AQ.Ab8RN6JxKqWvT2mHy...

azure
  aabbccddeeff00112233445566778899

elevenlabs
  sk_0123456789abcdef...

openai
  sk-proj-AbCdEfGh...

groq
  gsk_kEsY...

deepinfra
  ZyXwVuTsRqPoNmLkJiHgFeDcBa0123456
```

Nine providers are recognised. **Azure and AssemblyAI keys are the same shape**
— 32 hex characters — so nothing but the heading can tell them apart. Keep
those two under headings and everything else sorts itself out.

Headings are optional when the keys carry a recognisable prefix.

**Two Gemini formats are both accepted.** Google is moving Gemini keys from the
old `AIza…` Standard format to the new `AQ.Ab…` Auth format. New keys from AI
Studio are already `AQ.`, unrestricted `AIza` keys began being refused in
June 2026, and `AIza` Standard keys are due to stop working entirely in
September 2026. Both shapes are recognised, and a key under a `gemini` heading
is accepted whatever it looks like — the shape is a hint, never a gate. The
provider decides, which is what **TEST ALL** asks it to do.

A bare 32-character string of hex is AssemblyAI's format. It is also what an
MD5, a git SHA and a UUID look like, so it is only taken when the file says so
with a heading or the word on the line — or when the file names no provider at
all and is therefore just a list of keys.

This is the same file the desktop version uses. `~/Documents/maha_api_keys.txt`
works in both.

---

## Using it

| | |
|---|---|
| **SPLIT / TABS** | both apps at once, or one at a time |
| **SWAP** | put the reader on the left |
| **REC** | the pill *is* the record button — press, talk, press |
| **X** | throw the recording away |
| **SEND TO READER →** | hand the text across to the other side |
| **paste** tab | read whatever is on the clipboard, straight away |
| **edit** | change the words, then it re-reads them |

Recording asks for microphone permission the first time.

---

## What this version cannot do

Being a page rather than a program costs three things. The desktop version has
them all.

**No MP3 export.** The browser will not hand over the audio it synthesises, so
there is nothing to save.

**No audio shrinking.** The desktop version runs ffmpeg to reduce recordings to
mono 16 kHz Opus, about 36× smaller, before uploading. A page has no ffmpeg.
Recordings go up as the browser made them — already Opus, so the difference is
smaller than it sounds, but uploads are slower on a weak connection. This is
why there is no audio setting: an option that cannot do anything is worse than
no option.

**No queue.** If the network drops mid-upload the job fails and you press the
button again. Nothing is lost, but nothing resumes by itself either.

**Voices come from your operating system.** macOS and Windows ship Croatian.
Some Linux and Android builds do not, and then only English appears.

---

## Files

```
index.html   the shell: two frames and the top bar
tx.html      transcribe
rd.html      read
keys.js      the key parser and the cookie store
app.js       shared helpers
app.css      the shared stylesheet
```

The two apps are **separate documents in separate frames** on purpose. They
share a stylesheet and nothing else — no ids, no scripts, no state. Two
documents cannot leak into one another the way two halves of one page can, and
that is the whole reason for the arrangement. They talk by `postMessage`, with
the origin checked on both ends.

See **HELP.md** for the longer walkthrough.