Metadata-Version: 2.4
Name: espeakng-runtime
Version: 0.1.2
Summary: Small Python runtime adapter for eSpeak NG phonemization
Author: espeakng-runtime contributors
License-Expression: Apache-2.0
Project-URL: Repository, https://github.com/buchwandler/espeakng-runtime
Project-URL: Issues, https://github.com/buchwandler/espeakng-runtime/issues
Project-URL: Documentation, https://github.com/buchwandler/espeakng-runtime#readme
Project-URL: Changelog, https://github.com/buchwandler/espeakng-runtime/blob/main/docs/changelog.md
Keywords: espeak,espeak-ng,phonemizer,ipa,tts,g2p
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: bundled
Requires-Dist: espeakng-loader>=0.2.4; extra == "bundled"
Provides-Extra: dev
Requires-Dist: build>=1; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Requires-Dist: tomli>=2; python_version < "3.11" and extra == "dev"
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-cov>=5; extra == "dev"
Requires-Dist: ruff>=0.16; extra == "dev"
Requires-Dist: twine>=5; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx>=8; extra == "docs"
Requires-Dist: myst-parser>=4; extra == "docs"
Requires-Dist: sphinx-rtd-theme>=3; extra == "docs"
Dynamic: license-file

[![PyPI - Version](https://img.shields.io/pypi/v/espeakng-runtime)](https://pypi.org/project/espeakng-runtime/)
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/espeakng-runtime)
![PyPI - Downloads](https://img.shields.io/pypi/dm/espeakng-runtime)
[![codecov](https://codecov.io/gh/buchwandler/espeakng-runtime/graph/badge.svg?token=spJ8cG3cEK)](https://codecov.io/gh/buchwandler/espeakng-runtime)

# espeakng-runtime

A small Python runtime adapter for **eSpeak NG** phonemization.

The package deliberately does not implement G2P policy for Kokoro, Piper, or any
other model. It centralizes the shared eSpeak plumbing:

- executable, shared-library, and data discovery
- optional `espeakng-loader` integration
- native `ctypes` execution with process-wide locking
- CLI fallback
- voice enumeration
- IPA phonemization and batching
- exact native clause/terminator output when the loaded library exposes
  `espeak_TextToPhonemesWithTerminator`
- explicit runtime diagnostics/capabilities

## Layout

This project intentionally uses a flat package layout (no `src/` directory):

```text
espeakng_runtime/
tests/
pyproject.toml
```

## Versioning

The version is dynamic and comes from Git tags through `setuptools-scm`.
For source archives without Git metadata, the MVP falls back to `0.1.dev0` so
an unpacked zip remains installable.

```bash
git tag v0.1.0
python -m build
```

## Install

Use a system eSpeak/eSpeak NG installation:

```bash
pip install espeakng-runtime
```

Or install the optional binary/data loader:

```bash
pip install "espeakng-runtime[bundled]"
```

## Quick start

```python
from espeakng_runtime import EspeakRuntime

with EspeakRuntime(mode="auto") as espeak:
    print(espeak.info)
    print(espeak.phonemize("Hello world", voice="en-us"))
    print(espeak.phonemize("Hello world", voice="en-us", separator="_"))
    print(espeak.clauses("Hello, world!", voice="en-us"))
```

`mode` is `"auto"`, `"native"`, or `"cli"`. `auto` prefers a working native
library and falls back to the command-line executable.

Voice arguments are caller-facing requests, not necessarily native identifiers. The runtime enumerates the active inventory and resolves language requests such as `en-gb` to the concrete identifier accepted by the installed eSpeak version. Resolution is cached per runtime instance, and ordinary language requests never select MBROLA voices implicitly. Use an explicit `mb/...` or `mb-...` request, or `resolve_voice(..., allow_mbrola=True)`, when MBROLA selection is intended.

The `voice` argument is a public eSpeak voice/language selector. Native mode first attempts an explicit voice-name lookup and, when that fails and the native API supports it, retries the selector as a language property. This allows common locale selectors such as `de-de`, `en-gb`, and `fr-fr` to behave consistently with the CLI backend.
`RuntimeInfo.version_tuple` exposes the numeric components of the reported eSpeak version, for example `(1, 48, 15)`. Runtime cleanup is deterministic with `close()` or a context manager. Closing releases the Python runtime ownership; because eSpeak native state is process-global and older releases may be unsafe to terminate/reinitialize repeatedly, the initialized library remains resident for the Python process lifetime. Subsequent compatible runtimes reuse it, while conflicting library or data paths are rejected. Abandoned runtimes release their Python ownership during garbage-collection finalization.
For Piper-style exact clause handling, request an exact-capable runtime:

```python
from espeakng_runtime import EspeakRuntime

with EspeakRuntime(mode="auto", prefer_exact_clauses=True) as espeak:
    clauses = espeak.clauses("Hello, world!", voice="en-us", exact=True)
```

In `auto` mode, `prefer_exact_clauses=True` chooses an exact-capable native
library when possible and otherwise falls back to CLI best-effort clauses.
Calling `clauses(..., exact=True)` on a non-exact backend raises
`CapabilityError` rather than silently degrading.

Inspect capabilities without initializing eSpeak:

```python
from espeakng_runtime import inspect_espeak

inspection = inspect_espeak(require_exact_clauses=True)
print(inspection.native_available, inspection.cli_available)
for probe in inspection.candidates:
    print(probe.library, probe.loadable, probe.missing_symbols)
```

Inspection is non-initializing and does not alter process-global native state. In auto mode, a native initialization failure falls back to the CLI and is reported by `RuntimeInfo.fallback_code` and `RuntimeInfo.fallback_reason`.

## Configuration

Explicit constructor arguments take precedence over environment variables:

- `ESPEAKNG_RUNTIME_EXECUTABLE`
- `ESPEAKNG_RUNTIME_LIBRARY`
- `ESPEAKNG_RUNTIME_DATA`

The library intentionally does not read KokoroG2P/PiperG2P-specific variables;
those projects can map their legacy configuration into constructor arguments
during migration.

## MVP scope

The package returns raw eSpeak output. Model-specific transforms stay in their
consumer projects. In particular this MVP does **not** contain Kokoro phoneme
mapping, Piper NFD/phone composition, vowel-cluster merging, lexicons, or G2P
routing.
