Skip to content
Back to skills

Manimvox Voice

ASecurity

Choosing and preparing the narration voice for a manimvox video: the ten engines (Kokoro default, Piper, macOS say, edge-tts, OpenAI, ElevenLabs, Sarvam AI, Gnani.ai, XTTS-v2, F5-TTS), their licences and privacy, listing voices, fixing pronunciation in series.json, voice-cloning consent, a music bed under the narration, burned-in captions, and subtitles. Use when the user asks for a different, online or cloned voice, or a word is mispronounced.

  • 4 stars
  • 0 votes
  • 1 copy
  • 4 views
  • Added October 24, 2026
ai-agentspythongobashsqlapi

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 24, 2026

npx -y skills add LaplacianAI/manimvox --skill manimvox-voice --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Manimvox Voice?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Manimvox Voice
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/laplacianai-manimvox-voice/badge)](https://www.skillsdirectory.com/skills/laplacianai-manimvox-voice)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: manimvox-voice
description: "Choosing and preparing the narration voice for a manimvox video: the ten engines (Kokoro default, Piper, macOS say, edge-tts, OpenAI, ElevenLabs, Sarvam AI, Gnani.ai, XTTS-v2, F5-TTS), their licences and privacy, listing voices, fixing pronunciation in series.json, voice-cloning consent, a music bed under the narration, burned-in captions, and subtitles. Use when the user asks for a different, online or cloned voice, or a word is mispronounced."
license: MIT
---

# manimvox voice

The narration voice is separate from the animation. Pick it, get it ready, and fix how words sound, without touching the scenes.

## How a voice is chosen

A voice is written `engine:voice`, for example `kokoro:af_heart`. manimvox takes the first of these that is set:

1. `--voice` on `manimvox render`
2. `voice` in `series.json`
3. the `MANIMVOX_VOICE` environment variable
4. `kokoro:af_heart`

If the voice is missing, not installed or lacks its key, the render stops with a one-line reason. manimvox never switches voice silently, and neither should you: when a voice fails, tell the user and ask. If you cannot ask, you may use only a voice that is local and already ready (`manimvox voices` shows it as ready): Kokoro if its model is present, else `say` on macOS. Never use the `fake:` test engine for a final render. Say in your report which voice you used instead and why (`say` is non-commercial). Otherwise stop and report what is needed: a go-ahead for the download, the install or the online service.

See what exists:
- `manimvox voices` lists every engine: ready or not, its licence, whether text goes online, whether it is non-commercial.
- `manimvox voices <engine>` lists one engine's voices. For `edge` and `elevenlabs` this goes online.

## Choosing an engine

Default to Kokoro unless the user asks for something else.

| Engine | Voice example | Pick it when | Needs | Flags |
|---|---|---|---|---|
| Kokoro | `kokoro:af_heart` | the default; offline, good quality | extra `kokoro`, 354 MB model | none |
| Piper | `piper:en_US-libritts_r-medium` | many offline voices and languages | extra `piper`, ~80 MB per voice | GPL-3.0 package; each voice has its own licence (the default is CC BY 4.0) |
| macOS say | `say:Samantha` | a quick local check on a Mac | nothing, macOS only | non-commercial |
| edge-tts | `edge:en-US-AriaNeural` | free online voices | extra `edge` | online: text goes to Microsoft |
| OpenAI | `openai:alloy`, `openai:tts-1-hd/onyx` | the user asks for it and has a key | extra `cloud`, `OPENAI_API_KEY` | online, paid; say the voice is AI-generated |
| ElevenLabs | `elevenlabs:<voice id>` | the user asks for it and has a key | extra `cloud`, `ELEVENLABS_API_KEY` | online; the free tier requires attribution |
| Sarvam AI | `sarvam:shubh`, `sarvam:anushka@hi-IN` | narration in an Indian language, or Indian English; the user has a key | extra `cloud`, `SARVAM_API_KEY` | online, paid |
| Gnani.ai | `gnani:Kaveri`, `gnani:Shivani@ta-IN` | the same, or Hinglish (`@hi-en`) | extra `cloud`, `GNANI_API_KEY` | online, paid |
| XTTS-v2 | `xtts:clone=voice.wav` | a voice the user owns and consents to clone | extra `xtts`, ~1.9 GB plus PyTorch | non-commercial |
| F5-TTS | `f5:clone=voice.wav` | the same, with a transcript | extra `f5`, ~1.3 GB plus PyTorch | non-commercial |

Add an extra with the command `manimvox doctor` names: `uv tool install --force "manimvox[kokoro,<extra>]"` for a uv install, `pip install "manimvox[kokoro,<extra>]"` for pip (name every extra wanted, and keep kokoro). Licences were summarised, not legally reviewed: tell the user to verify upstream before commercial use.

## Ask before anything leaves the machine or downloads

- Before the first render with an online engine, ask, and say that the narration text is sent to that service. Nothing else is sent.
- Before a model download, say what it is and its size, and ask. Kokoro and Piper files are verified by hash.
- Before installing a package (an extra), ask.
- With the user's go-ahead, pass `--yes` (or set `MANIMVOX_ASSUME_YES=1`) so the prompts do not stop the run. Without it, a declined or unanswered download stops the render.
- Name non-commercial engines (`say`, XTTS-v2, F5-TTS) as non-commercial to the user whenever you suggest them.

## Getting a voice ready

`manimvox voices --prepare ENGINE[:VOICE] [--yes]` does everything a render would do before the first line, so failures show up early. With only `ENGINE` it uses that engine's default voice. It checks:

- the extra is installed;
- the model files are present (and offers to download them);
- the voice exists: Kokoro, Piper, edge and `say` name close matches when it does not; OpenAI, Sarvam and Gnani check the name and the language; ElevenLabs checks the voice id with the service;
- the key variable is set, for OpenAI, ElevenLabs, Sarvam and Gnani;
- for XTTS-v2 and F5-TTS, that the recording exists, and for F5-TTS that `voice.txt` is beside it.

It ends with `ready: engine:voice`.

Piper's default voice is `en_US-libritts_r-medium`. A local Piper `.onnx` file is also accepted, as a path from the project root.

## Cloning a voice

Only with the person's agreement, and only a voice the user owns or has permission to use. Do not clone a public figure or a recording the user cannot account for.

- Use a clean 6 to 30 second recording of one speaker.
- Write it as `xtts:clone=voice.wav` or `f5:clone=voice.wav`. The path is relative to the project root.
- F5-TTS also needs the exact words spoken in the recording, in `voice.txt` beside `voice.wav`. Without it the render stops.
- Both engines are non-commercial, and each needs a large model download: ask first.

## Pronunciation

If a word is mispronounced, fix it in the voice, not in the text on screen.

- `series.json` holds `pron`, a list of `[regex, spoken]` pairs. They change what the voice says and never the subtitles or the on-screen text:

  ```json
  "pron": [["\\bNumPy\\b", "num pie"], ["\\bkubectl\\b", "cube control"]]
  ```

- Common terms are already handled: API, JSON, SQL, and snake_case words.
- For one line only, pass `tts="..."` to `narrate`, `say`, `steps` or `intro`; the written `text` still shows in the subtitles. `pron` still applies to a `tts` string.
- To hear what Kokoro will say, print its phonemes. `manimvox voices` shows where its models live (`models in <dir>`); use that folder:

  ```bash
  uv run python -c "from kokoro_onnx import Kokoro; k = Kokoro('<dir>/kokoro-v1.0.onnx', '<dir>/voices-v1.0.bin'); print(k.tokenizer.phonemize('Then lead calls the graph tool.', 'en-us'))"
  ```

  If `manimvox voices` does not show the folder, the cache rule is: `$MANIMVOX_CACHE`, else `%LOCALAPPDATA%\manimvox` on Windows, else `$XDG_CACHE_HOME/manimvox` or `~/.cache/manimvox`; then `kokoro/`.
- Change the spelling until the phonemes read right (for example, spell out "lead" as "led" for the metal), add the pair to `pron`, and re-render. Cached audio is keyed by the spoken text, so only changed lines are re-synthesised.

## Speed

System voices often speak faster than the default (about 190 words a minute against about 170). Whenever you use one, chosen or as a fallback, check the speech rate after the render (words in the `.srt` divided by the sum of its cue durations; the check is in [narration](../manimvox-creative/references/narration.md#length)) and lower `speed` in `series.json` only if it is above 175 words a minute (0.9 first).

Every narration line is levelled to `loudness` in `series.json` (LUFS, −16 by default), so voices sound equally loud; leave it unless the user asks for a different level, and never set it to `null` to fix a quiet voice.

`speed` in `series.json` is a number above 0, `1.0` by default. ElevenLabs accepts only 0.7 to 1.2, Sarvam 0.5 to 2.0 (0.3 to 3.0 on `bulbul:v2`) and Gnani 0.85 to 1.15; each stops the render outside its range.

Sarvam and Gnani voices are `[model/]voice[@language]`: the language goes after `@` (`sarvam:priya@ta-IN`, `gnani:Avinash@hi-IN`). Write the narration in the script of that language. Sarvam defaults to `en-IN`; Gnani detects the language when none is given.

## Subtitles, captions and music

**Subtitles.** Every render writes `out/<stem>.srt` from the on-screen text (the `text` of each line, not `tts`).

**Configuration.** `series.json` may hold a `post` object, which `manimvox render` applies after the audio check:

```json
"post": {"music": "music/bed.mp3", "music_db": -16, "duck_db": -12, "captions": "burn", "end_card": ["Sources: FACTS.md"], "card_seconds": 3}
```

- `music` is a file in the project. It loops or is cut to the episode, fades in and out, and dips `duck_db` under every narration line. `music_db` (default -16) is its level; `duck_db` (default -12) is the extra cut while someone speaks. Both are numbers from -60 to 0.
- `captions` is `"srt"` (the default, ship the `.srt` only) or `"burn"` (draw the subtitles into the picture as well). Burned captions cover the bottom of the stage, so keep notes clear of it or ship the `.srt` only. Burned captions are drawn without complex-script shaping; for Arabic, CJK or other complex scripts ship the `.srt` instead.
- `end_card` adds up to 4 lines (80 characters each) on a closing card; a single string is accepted. `card_seconds` (default 3, from 1 to 10) is how long it shows.

**Music rights.** manimvox ships no music and never downloads any. Use only a file the user provides and has the right to use; ask before fetching any music. With no way to ask, render without music.

**The audio check** runs on the narration alone, so music never hides a silent line. With `post.music` set, `manimvox check audio` checks the narration-only render in `build/` and says so.

## When it fails

Each failure is one line. What to do:

| The line says | Do |
|---|---|
| not installed: `uv tool install --force "manimvox[kokoro,X]"` (or `pip install "manimvox[kokoro,X]"`) | ask, then install that extra (keep every extra already wanted) |
| set `OPENAI_API_KEY` / `ELEVENLABS_API_KEY` / `SARVAM_API_KEY` / `GNANI_API_KEY` | the user sets the variable; never write a key into a file in the project |
| rejected the key (HTTP 401) | the key is wrong or expired; the user fixes it |
| rerun with `--yes` / model files are missing | ask about the download, then `manimvox voices --prepare ENGINE --yes` |
| no voice 'X' (did you mean ...) | use the suggestion or `manimvox voices <engine>` |
| `say` is macOS only | choose another engine |
| F5-TTS needs the words spoken | write `voice.txt` beside the recording |
| ElevenLabs, Sarvam or Gnani speaks at speed X to Y | change `speed` in `series.json` |
| `audio check` fails after a render | the report lists silent lines: rerun `manimvox check audio <episode>`, then re-render; if one line keeps failing, reword it |

Never install, download, go online or clone a voice to get past a failure without the user's explicit go-ahead. If you cannot ask, the answer is no: stop and report what you need.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in ai-agents →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.