ScreenPilot

Voices

Choose a narration voice: Edge voices over the internet, speech models on your own computer, or any program you define. Setup, limits and fixes.

ScreenPilot speaks each narration line with a voice provider. There are three. edge is the default and needs no setup. local runs speech models on your own computer. command runs any program you define that turns text into an audio file. Existing storyboards keep working: when a storyboard has no provider, it is edge.

Choose a provider#

ProviderWhat it isInternetCostQuality note
edgeMicrosoft Edge voices, in many languages, including Egyptian Arabic.Needed for every render of new lines.None.Works with no setup. It is an unofficial service and may change.
localSpeech models that run on your computer: VoiceTut and NAMAA.Only for the setup download. Not needed after.Free. Uses about 10 to 16 GB of disk.Egyptian Arabic and English. Arabic is less accurate than English. Tested on Linux with an NVIDIA GPU only.
commandA program you define in voices.json, for example Piper.Depends on the program.Depends on the program.Whatever the program produces.

Pick edge if you want it to work now. Pick local if you want no internet at render time. Pick command if you already have a speech model of your own.

Set the provider once for the whole storyboard in voice. See Output and voice for every field.

Edge voices#

Edge is the default provider. The voices are Microsoft Edge voices, fetched over the internet. The service is unofficial, so it can change or stop without notice. A video with no narration lines needs no voice, and generated clips are cached, so an unchanged line is not requested again.

"voice": { "name": "ar-EG-SalmaNeural", "rate": "+0%" }

List the voices, optionally for one language:

screenpilot voices --lang ar-EG

Examples: ar-EG-SalmaNeural, ar-EG-ShakirNeural, en-US-AndrewNeural (the default), en-US-AriaNeural.

Local models#

Local voices are speech models that run on your own computer. They are free and need no internet after setup. Install one with screenpilot voice-setup, then use it in a storyboard.

Which model to install#

  • VoiceTut speaks Egyptian Arabic and English and has 19 built-in voices. Start here. Its code is Apache-2.0; check the model page for the weights license. Its authors report a word error rate of 0.40 for Arabic against 0.07 for English, so listen to Arabic lines before you deliver. Sarah and Mohammed were tested here.
  • NAMAA speaks Egyptian Arabic only and has one voice. It is MIT licensed. Its model card says it can miss the "ق" sound and misread numbers.

Install a model#

Run this in a terminal. The MCP server has no tool for it on purpose, because it downloads many gigabytes and installs third-party code.

screenpilot voice-setup voicetut
screenpilot voice-setup namaa

What you need and what happens:

  1. Install uv. It also fetches Python 3.11, so you do not need your own Python.
  2. Run the command. It checks the free disk space first, and asks you to confirm unless you pass --yes.
  3. It creates a Python environment of its own and installs PyTorch: the CUDA build on NVIDIA GPUs, the CPU-only build on other Windows and Linux machines.
  4. It installs third-party code pinned to the commits it was tested with: OmniVoice and VoiceTut from GitHub for VoiceTut, and chatterbox-tts for NAMAA.
  5. It downloads the model and speaks one test line.
  6. It saves the Python path in voices.json (keys local.python and local.env.HF_HOME).
ModelDisk
voicetutAbout 10.5 GB, up to 15 GB while installing.
namaaAbout 5.5 GB more, on top of VoiceTut.

The models go in a folder next to the app folder, so an app update does not remove them:

  • Linux: ~/.local/share/screenpilot-voices
  • Windows: %LOCALAPPDATA%\ScreenPilot-voices
  • macOS: ~/Library/Application Support/ScreenPilot-voices
FlagWhat it does
--dir <path>Use another folder or drive.
-y, --yesDo not ask before downloading.
It can take 30 minutes or more on a slow connection. Do not close the terminal.

To use a Python you already have, set SCREENPILOT_LOCAL_PYTHON to a Python that has the model packages installed. Set SCREENPILOT_LOCAL_DEVICE to auto (default), cuda, cpu or mps to choose where the model runs.

Check the result:

screenpilot voices --provider local
screenpilot doctor

voices --provider local lists the installed models and their voices. doctor has a "local voice" check. It is skipped when you have not set up a local voice, because local voices are optional.

Use a local voice#

Set the provider and the name in the storyboard:

"voice": { "provider": "local", "name": "voicetut:Sarah", "rate": "+0%" }

For a local provider, name is one of:

  • voicetut: the default voice of that model.
  • voicetut:<Voice>: one of its voices, for example voicetut:Sarah.
  • namaa: the only NAMAA voice.

The language of each line is detected for you. A line with Arabic letters is Arabic. Any other line is English. rate (for example +10%) becomes a speed factor for VoiceTut. NAMAA ignores it.

To start a storyboard with a local voice:

screenpilot init sessions/2026-10-27_14-02 --provider local --voice voicetut:Sarah

The MCP tools voices and storyboard_init take a provider argument too, and so does the voice object in a take.json.

Mix models in one video#

A narration line can set its own voice. It replaces the name and keeps the provider. So you can speak Arabic lines with NAMAA and English lines with VoiceTut:

"voice": { "provider": "local", "name": "voicetut:Sarah" },
"narration": [
  { "at": 1, "text": "Invoices can now repeat on a schedule." },
  { "at": 6, "text": "ويمكنك إيقافها في أي وقت.", "voice": "namaa" }
]

Tips#

  • Keep lines short. A long line freezes the video to make room.
  • Generated clips are cached, so rendering again is fast. Only lines you change are spoken again.
  • Listen to Arabic lines before you deliver, and check any numbers.

Limits and measured numbers#

These numbers were measured on one machine: an NVIDIA RTX 2050 with 4 GB of memory.

ModelPeak GPU memorySpeed
VoiceTut2.1 GBAbout 1.4 times slower than real time: a 3 s line takes about 4 to 5 s.
NAMAA3.2 GB, tight on a 4 GB card that also runs the desktop.Similar to VoiceTut.
  • The model loads once per render. That takes about 20 s.
  • On a CPU it is much slower. This was not measured.
  • Arabic is less accurate than English. NAMAA can miss the "ق" sound and misread numbers.
Tested on Linux with an NVIDIA GPU only. Windows and macOS were not tested.

Your own model#

A command voice runs a program of your choice. The program receives the text and writes an audio file. Piper, Kokoro or a script that calls a model you trust all work.

Define the voice in voices.json, in the config folder:

  • Linux and macOS: ~/.config/screenpilot/voices.json
  • Windows: %APPDATA%\screenpilot\voices.json

Set SCREENPILOT_VOICES_FILE to use another path. This file is yours. It lives outside the storyboard on purpose: a storyboard from an AI or from someone else must never be able to run programs.

The fields#

{
  "commands": {
    "my-voice": {
      "command": ["program", "arg", "{out}"],
      "stdin": "{text}",
      "ext": "wav",
      "timeout": 120,
      "env": {}
    }
  }
}
FieldMeaning
commandThe program and its arguments. No shell is used, so the text cannot inject commands. A leading ~/ in an argument means your home folder.
stdinOptional. Text piped to the program, usually {text}.
extExtension of the file the program writes. Default wav. Any format ffmpeg reads works.
timeoutSeconds allowed for one line. Default 120.
envOptional. Extra environment variables for the program.

The placeholders you can use in command and stdin:

PlaceholderReplaced with
{text}The narration line.
{rate}The voice rate, for example +10%.
{speed}The rate as a speed factor, for example 1.1.
{lang}ar for a line with Arabic letters, otherwise en.
{out}The path the program must write the audio to.

The program must write the audio to {out}.

Example: Piper#

This example shows the shape of the file. It was not run here, so check the paths and flags against your Piper install.

{
  "commands": {
    "piper-amy": {
      "command": ["piper", "--model", "~/models/en_US-amy-medium.onnx", "--output_file", "{out}"],
      "stdin": "{text}"
    }
  }
}

Then use it in the storyboard. The name is the key you defined:

"voice": { "provider": "command", "name": "piper-amy" }

screenpilot voices --provider command lists the voices defined in your voices.json.

Wrap any model in a script#

If a model has no command line, write a small script of your own and point command at it:

{
  "commands": {
    "my-model": {
      "command": ["python3", "~/tts/say.py", "{lang}", "{out}"],
      "stdin": "{text}",
      "timeout": 300
    }
  }
}

The script ~/tts/say.py is yours. It reads the text from stdin, reads the language from its first argument, and writes the audio file to the path in its second argument. Raise timeout for a slow model.

Troubleshooting#

You seeWhat to do
No local voice engine is set up, and it says to run voice-setup.Run screenpilot voice-setup voicetut. Or set SCREENPILOT_LOCAL_PYTHON to a Python that has a model installed.
The GPU ran out of memory. The message suggests SCREENPILOT_LOCAL_DEVICE=cpu.Set SCREENPILOT_LOCAL_DEVICE=cpu. It is slower. Or use voicetut, which needs less GPU memory than namaa.
An unknown local voice, with a list of the valid models.Use voicetut, voicetut:<Voice> or namaa. List what is installed with screenpilot voices --provider local.
A command voice finished but wrote no audio, and the message names voices.json.Check that the program writes its audio to {out} and that ext matches the file it writes. Run the program by hand with a real path.
The voice engine stopped, followed by its last lines of output.Read those lines: they are what the engine printed before it stopped. Run screenpilot doctor and read the "local voice" check.
voice-setup says it needs uv.Install uv and run the command again.
voice-setup says there is not enough disk space.Free space, or pass --dir to use another drive.
More answers are on the FAQ. The command line is in voice-setup and voices.