Skip to main content

Mimora

A local, offline pronunciation trainer. Mimora speaks a phrase, you repeat it, and it scores how close you were, highlighting the words to work on. Practice the same phrase until you are happy with the score, then move on to the next one. Everything runs on your machine: speech synthesis, speech recognition, phrase generation and scoring.

Mimora demo: one full practice loop - new phrase, speak, score, highlighted words, replay

Dark theme Light theme
Mimora pronunciation trainer, dark theme Mimora pronunciation trainer, light theme

Both themes ship with the app; drop your own <name>_schema.json into config/themes/ to add or replace one.


Why Mimora?

  • 🔒 100% offline after install - your voice never leaves your computer. No cloud, no accounts, no API keys.
  • ♾️ Unlimited, varied practice - a local LLM writes fresh phrases from your own text, so you never drill the same canned sentences.
  • 💸 No subscription - free and open source. The only cost is disk space for the models.
  • 💻 Runs on a normal PC - 16 GB RAM and no graphics card. A GPU is optional and only makes it faster.
  • 🎯 Instant, word-level feedback - a 0-100 score and the exact words to work on, with reference-vs-you replay.

Who is it for?

Anyone working on clearer speech in a new language: language learners, accent reduction and shadowing practice. You bring the text (a paragraph, a song, a script), and Mimora turns it into spoken drills.

Supported languages

The practice language is set in the settings window (Language, applies after a restart). A language can offer regional variants (Accent).

Language Variants Scoring engines
English American, British phoneme (default, calibrated), acoustic, none
Spanish (Peninsular / Castilian) Castilian phoneme (experimental, see below), none

English is fully calibrated in both variants. Spanish is an experiment while multilingual support is in development. The scoring engine itself is language-independent, but its calibration is not, and a Spanish calibration needs labeled non-native speech that is not available yet. Until it lands, Spanish takes are scored with the English calibration: usable, but not tuned. The acoustic engine uses an English recognizer and is offered for English only.

The translation panel covers 200+ languages, but that is the translation shown beside the phrase, not the practice language.


How it works

For each practice phrase Mimora runs a simple loop:

  1. Prompt - the local LLM writes a phrase from your practice text, and the TTS voice of the language speaks it (Kokoro for English, Supertonic for Spanish). The same audio is the reference for scoring.
  2. Record - press SPACE or click the mic, then repeat the phrase. The take stops on its own once you fall silent, or when you press SPACE again.
  3. Analyze - your recording is compared with the reference, and prosody (pitch and energy) is added to the result. The default phoneme engine matches espeak reference phonemes against a wav2vec2 phoneme recognizer. The acoustic engine is the alternative, selected in the settings window (Engine; settings.json "engine").
  4. Feedback - you get a score out of 100, what was recognized, and the words to improve.
  5. Loop - repeat the same phrase until you are happy with the score, then generate the next one.

You can play the reference and your own recording back to back to hear the difference.

No-LLM mode for slow machines. Set the LLM backend to off and the language model is never loaded or started. Each phrase is then a sentence of your practice text, taken verbatim and in order. This saves the GGUF download, the server subprocess, RAM and VRAM, and it starts faster. It also suits drilling a text exactly as written. Phrase length is fixed in this mode: sentences are never shortened. Together with the none scoring engine, Mimora then runs with no LLM and no recognizer model at all.

Example

Reference:  The weather is getting colder.
You said:   The weather is getting color.
Score:      82 / 100
Work on:    colder

Features

  • 🎙️ One-press recording - press once, speak, and it stops by itself when you go quiet.
  • 🗣️ One consistent reference voice - the prompt and the scored reference are the same voice, so the target never changes. Prefer variety? Turn on Random voice per phrase in the settings.
  • 🧠 Practice your own material - paste a paragraph, a song or a few sentences into the practice text panel, and the local LLM turns them into an endless stream of phrases.
  • ⚙️ Settings window (the gear button) - the practice language and its accent (both apply after a restart), the TTS voice and playback speed, Random voice per phrase (needs at least two voices of the current language), the phrase length (full phrase or a few words), the translation language shown under the phrase, and a user name that selects the per-user scoring calibration.
  • 📊 Two interchangeable scoring engines, selected in the settings window (Engine; settings.json "engine"). The default phoneme engine compares the phonemes of your take with the phonemes of the reference text. The acoustic engine compares the sound of the two recordings instead. Both are length-invariant, and both can be calibrated to your voice (python pronunciation/<engine>/calibrate.py).
  • 🔁 Replay reference vs. your recording to hear the difference.
  • 😀 Articulation face - a schematic mouth moves with the speech while audio plays, and shows a smiley for your score while idle.
  • 🧵 Responsive window - scoring and model loading never block the interface.

Requirements

  • Hardware - a typical laptop or desktop: 16 GB RAM and no GPU required. On CPU the first phrases are slower. An NVIDIA GPU is optional, needs a CUDA build of PyTorch, and speeds up scoring and phrase generation.
  • Python 3.11 or 3.12. Python 3.13 and newer install only with a C++ compiler, because two dependencies publish no wheels for them. pip refuses such a version by itself; uv does not, so pass --python 3.12 to it (see below).
  • Windows is the primary target. macOS and Linux are supported as well.
  • A microphone and speakers.
  • espeak-ng is needed by phonemizer, but it is not a separate install: the library and its data ship in the espeakng-loader wheel, which comes with the dependencies. A system install stays a valid fallback, see espeak-ng.
  • PortAudio (Linux only) - the native library behind recording and playback (libportaudio2 on Debian/Ubuntu). The Windows and macOS wheels bundle it, the Linux ones do not. See Audio on Linux.

macOS notes

Apple Silicon Macs run the same pinned stack as Windows and Linux. Intel Macs (x86_64) are supported through an automatic fallback: PyTorch publishes no macOS x86_64 wheel newer than torch 2.2.2, and that torch cannot run transformers 5. The dependency markers therefore install an older stack there (torch 2.2.2, transformers 4.x, NumPy 1.x), with no manual steps. That stack does without the transformers 5.3 fix for CVE-2026-4372, which is acceptable for a local app that loads only fixed, trusted models. Every other platform keeps the hardened pins.

The local chat model is the one piece that depends on the macOS version itself, because Mimora runs llama.cpp's own llama-server binary. llama.cpp builds its Apple Silicon asset on a current macOS runner and sets no deployment target, so the binary inherits that runner's minimum: macOS 26. The Intel asset sets 13.3 explicitly. Below its minimum Mimora says so before it downloads anything and carries on without the local model, so everything else still works. To get phrase generation back on such a Mac, set the LLM backend to LM Studio, or build llama.cpp yourself and name the result in "llama_server_path". See llama-server.

tkinter comes with the python.org installer, but not with Homebrew Python. install.py adds the matching python-tk@<version> formula for the interpreter it runs in. If you set things up by hand on Homebrew Python, match your version, for example brew install python-tk@3.12.

Models

install.py downloads all of these in one run (see Install from a clone). You do not have to use it: on the first start Mimora checks what is missing, names the exact volume, and asks before anything is downloaded. Each model also has its own command, listed per row below.

The first-run window asks in three groups. The models a session cannot run without (the engine's recognizer and the language's TTS) leave you Download or Quit. The local chat model is a real choice: declining it writes "llm_backend": "off" into config/settings.json, and the settings window turns it back on. The offline translator appears only when a translation language is selected, and declining it writes "translation_language": "" the same way. Turning translation on later restarts Mimora into the same window, because with translation off nothing about the translator is downloaded or checked over the network.

Model Used by Download Notes
facebook/wav2vec2-xlsr-53-espeak-cv-ft pronunciation analysis (phoneme engine, default) 1264 MB espeak IPA phoneme recognizer; python -m mimora.model_fetch --hf
facebook/wav2vec2-large-960h pronunciation analysis (acoustic engine) 1262 MB python -m mimora.model_fetch --hf
Kokoro-82M (hexgrad/Kokoro-82M) text-to-speech (English) 363 MB python -m mimora.model_fetch --hf
Supertonic 3 (Supertone/supertonic-3) text-to-speech (Spanish) 404 MB python -m mimora.model_fetch --supertonic. Weights are OpenRAIL-M licensed (code MIT), so they are downloaded, never bundled
facebook/nllb-200-distilled-600M offline translation (translation panel) 2483 MB downloaded only once a translation language is selected
A GGUF chat model (e.g. Llama-3.2-3B-Instruct-Q4_K_M) phrase generation 2019 MB python -m mimora.gguf_fetch. Not needed with "llm_backend": "off"
llama-server binary (pinned llama.cpp release) phrase generation 641 MB CUDA, 18 MB CPU most of the CUDA figure is NVIDIA's runtime; python -m mimora.llama_server_fetch

Installation

Three ways in, in the order most people should try them:

  1. From the published wheel (below) - one command, no clone, no build toolchain. This is the recommended way.
  2. From a clone with install.py - the guided setup for a checkout. It also downloads every model up front, and it is the way to go if you intend to change the code.
  3. By hand - every command run yourself, plus the platform-specific pieces behind them: docs/installation-manual.md.

Every way installs prebuilt packages (wheels), so no compilation toolchain is needed. You need neither a C/C++ compiler nor a CUDA toolkit.

Install from PyPI (recommended)

Mimora is an application rather than a library, so install it with a tool installer instead of adding it to an everyday environment. uv is the recommended one: it is the only installer that supplies both the Python version and the CUDA build of PyTorch by itself.

uv is a single binary and needs no Python of its own:

# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

brew install uv, winget install --id=astral-sh.uv -e, scoop install main/uv and pipx install uv install it as well. If you already have uv, check the version (uv --version) and update it with uv self update: the GPU flag below needs 0.9.20 or newer.

Then install Mimora and start it:

uv tool install mimora --python 3.12
mimora

--python 3.12 is not optional. A uv tool environment ignores the package's requires-python, so without the flag uv installs into whatever interpreter it finds first. uv downloads a 3.12 itself if the machine has none.

Windows with an NVIDIA GPU - add --torch-backend auto, so uv resolves the CUDA build of torch instead of PyPI's CPU-only wheel. Do not add this flag on Linux or macOS - see GPU support for what it does there.

uv tool install mimora --python 3.12 --torch-backend auto

pipx gives the same result except for that index: an index cannot be named in a published package's metadata, so on Windows with an NVIDIA card the CUDA build is a second command.

pipx install --python 3.12 mimora
pipx runpip mimora install torch --index-url https://download.pytorch.org/whl/cu124 --force-reinstall

pip works too, into a virtual environment of Python 3.11 or 3.12:

python -m venv .venv
.venv\Scripts\activate            # Windows
# source .venv/bin/activate       # macOS / Linux

pip install mimora
mimora

On Linux one native library comes from the system rather than from a wheel: sudo apt-get install libportaudio2 (see Audio on Linux). Add a monochrome emoji font as well, or the mic button draws blank boxes (see Emoji icons on Linux).

The install itself downloads no models. The first start does, and it asks first (see Models). Those downloads and your settings live in the operating system's user-data directory (see Where Mimora keeps your files), which is outside the installed package and therefore survives both of these:

uv tool upgrade mimora            # pipx: pipx upgrade mimora
uv tool uninstall mimora          # pipx: pipx uninstall mimora

Uninstalling removes the program, not the models. Delete the data directory by hand to reclaim that space.

Install from a clone with install.py

Use this one to work on Mimora itself, or to have every model in place before the first start.

install.py does the whole setup: it checks the native pieces pip cannot supply (tkinter and PortAudio on Linux, the MSVC runtime on Windows), installs the Python dependencies, reports which espeak-ng library the engines will use, detects an NVIDIA GPU and installs the matching CUDA build of torch, downloads the Hugging Face models into model_cache/, installs the pinned llama-server binary into bin/llama/, and downloads the GGUF chat model into models/.

git clone https://github.com/vikonix/Mimora.git Mimora
cd Mimora

# Create and activate a virtual environment, then run the installer INSIDE it
# (the script installs into whatever interpreter runs it):
python -m venv .venv
.venv\Scripts\activate            # Windows
# source .venv/bin/activate       # macOS / Linux

python install.py

The installer prints each step and its exact command, then asks before it runs it (answer Y to run, n to abort, s to skip). Anything already installed is offered as reinstall-or-skip rather than blindly redone. The full run is logged to logs/install.log. Expect several minutes, mostly downloads, and roughly 10 GB of disk once all packages and models are in place.

Useful flags:

  • --yes - run non-interactively (skips already-installed steps; add --reinstall to force them)
  • --dry-run - print the steps and commands without executing anything
  • --cpu - skip the GPU (CUDA) installs
  • --skip-models / --skip-gguf - skip the model / GGUF downloads

The espeak-ng step reports the library the engines resolve to, which on a normal install is the bundled one. It offers a system install only if none is found, and on Windows it just prints instructions. On Windows, Developer Mode lets the model cache use symlinks; without it the installer copies files instead, which always works but uses more disk.

Manual installation

Every step run by hand, plus the native pieces behind it - espeak-ng, PortAudio on Linux, the emoji font, the CUDA build of PyTorch, the llama-server binary and the GGUF chat model: docs/installation-manual.md.


Usage

Installed from PyPI, Mimora is a console script:

mimora

From a clone, run it in the same virtual environment you installed into, so that the app uses the interpreter that has the dependencies:

.venv\Scripts\activate            # Windows
# source .venv/bin/activate       # macOS / Linux

python main.py

On the first launch the app loads the TTS and recognizer models and starts the LLM server. Cached models are just a load that takes a moment; a missing model is downloaded first, which takes a while. Once the app shows Ready:

  1. Edit the Practice text panel, or keep the default.
  2. Click Next phrase ▶. Mimora generates a phrase and speaks it.
  3. Press SPACE (or click the mic button) and repeat the phrase. The take stops on silence, or on a second SPACE.
  4. Read your score and verdict on the phrase card. Mispronounced words are underlined, and a click plays one slowly. The WORK ON badges name the sounds to fix, and a click gives an example word. Earlier takes stay in the attempt history below.
  5. Use Reference ▶ (or Slow ▶) and My recording ▶ to compare, then repeat the phrase or generate the next one.

The first few phrases run noticeably slowly while the models warm up. This is normal, and the speed settles after the first few requests.

Press ESC or close the window to quit. The LLM server subprocess is terminated cleanly.

Where Mimora keeps your files

Running from a clone, everything stays inside the project directory: config/, models/, model_cache/, bin/llama/ and logs/.

Installed as a package, the same layout moves under the operating system's user-data directory, because the package's own directory is rebuilt on the next upgrade:

OS Location
Windows %APPDATA%\Mimora\
macOS ~/Library/Application Support/Mimora/
Linux $XDG_DATA_HOME/mimora/ (default ~/.local/share/mimora/)

The MIMORA_HOME environment variable puts that directory anywhere else, and it overrides both cases. Use it to move several gigabytes of downloads to another drive, to escape a roaming Windows profile that would copy them over the network at every login, or to run two configurations side by side.

Paths inside config/settings.json resolve against that file's own directory. The settings window writes absolute paths, which work everywhere. A relative path is read as relative to the settings file you are editing. Keys you leave out follow their own defaults instead, which are resolved for you.

Most settings are editable in the settings window. For the rest, config/settings.example.json documents every key next to its default. Copy it to config/settings.json to start, or edit that file directly. The file and every key in it are optional, and anything missing falls back to the built-in default.


GPU / CPU notes

On a single GPU the recognizer, the TTS voice, the translator and llama.cpp can compete for VRAM. Mimora keeps them apart: the LLM runs in a separate process, the practice loop runs its phases one after another, and the translator defaults to the CPU. If VRAM is still tight, set WAV2VEC2_DEVICE = "cpu" in mimora/config.py; short phrases score acceptably on the CPU.


Known limitations

  • Spanish scoring is experimental, because the calibration is per-language and no Spanish one exists yet (see Supported languages). The app logs a startup warning, and the settings window shows a notice.
  • Only mistakes the recognizer hears become word errors. A distorted word that is still recognized may not appear in the list. The phoneme distance, the DTW of the acoustic engine and the prosody part compensate for this in the score.
  • Scoring is heuristic and depends on your voice and microphone. After a practice session you can re-anchor the active engine to your own data: python pronunciation/phoneme/calibrate.py or python pronunciation/acoustic/calibrate.py, where --dry-run previews the change. Every take's raw components are logged to logs/phoneme_samples.jsonl (or logs/acoustic_samples.jsonl) and to logs/main.log.

Credits

  • OpenPronounce (MIT) - the pronunciation-scoring core reused in pronunciation/acoustic/.
  • Kokoro-82M - text-to-speech (English variants).
  • Supertonic 3 (supertonic-py, code MIT, weights OpenRAIL-M) - text-to-speech (Spanish variant), ONNX runtime.
  • wav2vec2-xlsr-53-espeak-cv-ft (Hugging Face Transformers) - espeak-style IPA phoneme recognizer for the default phoneme engine.
  • Wav2Vec2 (Hugging Face Transformers) - acoustic embeddings and transcription (acoustic engine).
  • NLLB-200 (Hugging Face Transformers) - offline translation for the translation panel.
  • espeak-ng / phonemizer-fork - reference phonemization (espeak IPA).
  • panphon - articulatory feature distance used by the phoneme edit-distance scoring.
  • llama.cpp - local LLM inference; the official llama-server binary is run as a subprocess.

License

See LICENSE. The reused OpenPronounce components are MIT-licensed; their attribution is retained in pronunciation/acoustic/speech.py.

Model weights have their own licenses. The Supertonic 3 TTS weights in particular are licensed under OpenRAIL-M (the supertonic package code is MIT), so Mimora never bundles them: they are downloaded into model_cache/supertonic3/ by install.py or on the first run.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mimora-1.1.0-py3-none-any.whl (365.1 kB view details)

Uploaded Python 3

File details

Details for the file mimora-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: mimora-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 365.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.4

File hashes

Hashes for mimora-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 24c9a597bda0cd80294a9273ff11c7d98b75101b8f4397598aa305107c0a50e9
MD5 59f564ef8668b95e92722eda38e6ad86
BLAKE2b-256 29b99d6769969f6b8e2adef29ead269fc296922c09207c522168bfb8833f399a

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.1.0 This release

1 file

1.1.0rc1

1 file

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page