Metadata-Version: 2.4
Name: jaketts
Version: 1.0.8
Summary: Jake's local CLI text-to-speech tool powered by Kokoro-82M
Home-page: https://github.com/ofalltrades/jaketts
Author: Jake
License: MIT
Project-URL: Source, https://github.com/ofalltrades/jaketts
Project-URL: Issues, https://github.com/ofalltrades/jaketts/issues
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Environment :: MacOS X
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Requires-Python: >=3.10,<3.13
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: PySide6-Essentials<7,>=6.8
Requires-Dist: kokoro>=0.7.0
Requires-Dist: misaki[ja,zh]>=0.9.4
Requires-Dist: sounddevice>=0.4.0
Requires-Dist: soundfile>=0.4.0
Requires-Dist: numpy<2.0.0,>=1.20.0
Requires-Dist: torch>=2.0.0
Requires-Dist: tqdm>=4.65.0
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license
Dynamic: license-file
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# 🔊 jaketts

`jaketts` — also available as the shorter `jtts` command — is a local text-to-speech utility for macOS powered by the open-weight **Kokoro-82M** model.

It can play synthesized speech directly through your speakers, save WAV files, read plain-text files, switch between Kokoro voices, adjust playback speed, and launch a Qt desktop interface when run with no arguments.

The default voice is `bm_george`.

## Features

- 🔊 Direct speaker playback
- 💾 WAV file export
- 📖 Plain-text file input
- 🗣️ Optionless voice selection
- ⏩ Adjustable speech speed with a 0.80× default
- 🌍 Multiple Kokoro language/voice families
- 🖥️ Qt desktop GUI with voice, exact speed, volume, and Stop controls
- 🔒 Local synthesis with no API key required
- ⚡ `jaketts` and `jtts` command aliases
- 🇯🇵 Automatic one-time Japanese dictionary setup when a Japanese voice is first used

## Requirements

`jaketts` currently supports Python 3.10 through Python 3.12.

On Apple Silicon, `jaketts` automatically allows PyTorch to use the MPS backend when available, with CPU fallback for unsupported operations. Heavy Kokoro/PyTorch imports remain deferred on CLI fast paths. The desktop GUI opens immediately and warms the default Kokoro model in a background thread so the first Play action is usually ready sooner.

## Installation with Homebrew

On Apple Silicon Macs running macOS 14 Sonoma or newer, install `jaketts` from the Homebrew tap:

    brew install ofalltrades/tap/jaketts

That installs both command aliases. Verify the installation with:

    jtts -v

Launch the desktop GUI:

    jtts

Or synthesize speech directly from the terminal:

    jtts "Hello from Jaketts"

The Homebrew formula is maintained at [ofalltrades/homebrew-tap](https://github.com/ofalltrades/homebrew-tap).

## Installation from PyPI

Install the published package into your preferred Python environment:

```bash
python -m pip install jaketts
```

That installs both commands:

```bash
jaketts --version
jtts --version
```

Japanese support uses the full UniDic dictionary. The required Python packages are installed by pip, and the first time you select a Japanese voice, `jaketts` automatically downloads the UniDic dictionary into the same Python environment. This is a one-time download of roughly 526 MB.

## Installation from GitHub

Clone the repository, enter it, and install it in editable mode:

```bash
git clone https://github.com/ofalltrades/jaketts.git
cd jaketts
python -m pip install -e .
```

Editable mode means changes to `jaketts.py` are used immediately without reinstalling the package. Re-run `python -m pip install -e .` after changing package metadata or dependencies.

If you prefer an isolated virtual environment:

```bash
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install -e .
```

To update a source checkout later:

```bash
git pull --ff-only origin main
```

If the update changed dependencies or package metadata, follow it with:

```bash
python -m pip install -e .
```

## Usage

### Launch the desktop GUI

Run either command with no arguments:

```bash
jaketts
```

or:

```bash
jtts
```

The GUI launches in its own process, so the terminal prompt is returned immediately while the desktop window remains open. It begins warming the default speech engine in the background while you enter text. The speed control combines a slider with a typeable exact-value field, and Stop immediately ends the current playback/generation job without closing the window.

### Speak text using the default voice

```bash
jtts "Three Rings for the Elven-kings under the sky."
```

### Choose a voice

Voice IDs are passed directly without a `--voice` flag:

```bash
jtts af_sarah "Hello from an American female voice."
```

```bash
jtts am_adam "Hello from an American male voice."
```

The voice can appear before or after the text:

```bash
jtts "This also uses Adam." am_adam
```

If no recognized voice ID is supplied, `bm_george` is used.

### Japanese voices

Japanese voices work without a separate setup command:

```bash
jtts jf_alpha "こんにちは世界"
```

On the first Japanese invocation only, `jaketts` downloads the full UniDic dictionary automatically. Later Japanese invocations reuse the downloaded dictionary.

### Read a text file

```bash
jtts story.txt
```

With an explicit voice:

```bash
jtts am_adam story.txt
```

### Save to the default output file

A bare `-o` or `--output` saves to `output.wav`:

```bash
jtts -o "Save this narration."
```

This also works when a voice immediately follows `-o`:

```bash
jtts -o am_adam "Save this using Adam."
```

### Save to a custom WAV file

```bash
jtts -o narration.wav "Save this narration."
```

or:

```bash
jtts --output narration.wav am_adam "Save this narration."
```

Equals syntax is also supported:

```bash
jtts --output=narration.wav "Save this narration."
```

### Change speech speed

The default speed is `0.8` (shown as `0.80×` in the GUI).

```bash
jtts -s 1.25 "Speak this a little faster."
```

```bash
jtts --speed 0.9 am_adam "Speak this a little slower."
```

Equals syntax is supported as well:

```bash
jtts --speed=1.1 "Slightly faster speech."
```

### Flexible argument ordering

The CLI normalizes recognized options and voice IDs before handing them to `argparse`, so these layouts are valid:

```bash
jtts am_adam "Hello" -o hello.wav
jtts -o hello.wav "Hello" am_adam
jtts "Hello" -s 1.1 am_adam -o hello.wav
jtts am_adam "Hello" -o
```

### Show the installed version

`-v` is the version flag:

```bash
jtts -v
```

or:

```bash
jtts --version
```

## Voice reference

Some commonly useful Kokoro voices include:

| Voice ID | Family | Description |
| --- | --- | --- |
| `bm_george` | British English | Default narrator |
| `bm_lewis` | British English | Male British voice |
| `bf_emma` | British English | Female British voice |
| `af_heart` | American English | Expressive female voice |
| `af_sarah` | American English | Female American voice |
| `am_adam` | American English | Male American voice |
| `ff_sixtine` | French | Female French voice |
| `jf_alpha` | Japanese | Female Japanese voice |
| `pf_doris` | Portuguese | Female Portuguese voice |
| `zf_xiaobei` | Chinese | Female Chinese voice |

The complete supported voice list is defined in `VOICE_WHITELIST` inside `jaketts.py` and is also available in the desktop GUI.

## Testing

The repository includes an integration test matrix covering output routing, flexible argument ordering, speed options, version flags, text-file input, default voice behavior, and multilingual voice routing.

Run it with:

```bash
./test_app.sh
```

The test script creates temporary WAV/text artifacts and removes them automatically when the test run exits.

## Development

Install the clone in editable mode:

```bash
python -m pip install -e .
```

The package version is defined in `setup.py`. `jaketts.py` reads the installed package metadata using `importlib.metadata`, so the runtime version output does not need a second hardcoded version string.

Before building a release:

```bash
./test_app.sh
rm -rf dist build *.egg-info
python -m build
python -m twine check dist/*
```

## License

See `LICENSE` for the project's license terms.
