Metadata-Version: 2.4
Name: pipersynth
Version: 0.1.1
Summary: Independent Python synthesis runtime for Piper-compatible ONNX TTS models
Author: PiperSynth contributors
License: Apache-2.0
Keywords: tts,text-to-speech,piper,onnx,speech,onnxruntime
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
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: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.23
Requires-Dist: utterplan<0.2,>=0.1
Requires-Dist: piperg2p
Requires-Dist: onnxvoice<0.2,>=0.1
Requires-Dist: audiocompose<0.2,>=0.1
Provides-Extra: cpu
Requires-Dist: onnxvoice[cpu]<0.2,>=0.1; extra == "cpu"
Provides-Extra: gpu
Requires-Dist: onnxvoice[gpu]<0.2,>=0.1; extra == "gpu"
Provides-Extra: catalog
Requires-Dist: onnxvoice<0.2,>=0.1; extra == "catalog"
Provides-Extra: playback
Requires-Dist: sounddevice<0.6,>=0.5; extra == "playback"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-cov>=5; extra == "dev"
Requires-Dist: ruff<0.17,>=0.16; extra == "dev"
Requires-Dist: mypy>=1.11; extra == "dev"
Requires-Dist: build>=1; extra == "dev"
Dynamic: license-file

# PiperSynth

PiperSynth is an independent Apache-2.0 application-facing Piper engine. It uses `piperg2p` for voice configuration and phonemization, `OnnxVoice` for model assets and ONNX execution, and `AudioCompose` for generic audio composition and AudioJob persistence. It does not depend on the upstream Piper runtime or `piper-tts`.

## Quick start

Install the CPU runtime and catalog support:

```bash
pip install "pipersynth[cpu]"
```

Generate a WAV from a catalog voice:

```python
from pipersynth import synthesize_to_wav

synthesize_to_wav(
    "Hello, this sentence was generated with PiperSynth.",
    "hello.wav",
    voice="en_US-lessac-medium",
)
```

On first use OnnxVoice fetches the Piper catalog and installs the selected model, matching config, and any model card into its shared local store. Later calls reuse that installation. The convenience call creates a fresh pipeline and closes it before returning.
For repeated synthesis, reuse one pipeline and one ONNX session:

```python
from pipersynth import PiperPipeline

with PiperPipeline.from_pretrained("en_US-lessac-medium") as pipe:
    pipe("One.").save_wav("one.wav")
    pipe("Two.").save_wav("two.wav")
```

Use cached assets only with `offline=True`:

```python
with PiperPipeline.from_pretrained("en_US-lessac-medium", offline=True) as pipe:
    pipe("This uses cached assets only.").save_wav("offline.wav")
```

## Planning and rendering

`PiperPipeline.plan()` compiles text into an immutable `UtterancePlan`. The UtterPlan planner owns document parsing, Spokenform, SSMD, language runs, semantic units, markers, and resolved pauses. Rendering an existing plan never replans it, so the same plan can be rendered repeatedly with different acoustic overrides:

```python
with PiperPipeline.from_pretrained("en_US-lessac-medium") as pipe:
    plan = pipe.plan("One. Two.", unit="sentence")
    plan.save("speech.utterplan.json")
    normal = pipe.render_plan(plan, length_scale=1.0)
    fast = pipe.render_plan(plan, length_scale=0.9)
```

## AudioJob production and replay

An existing plan can be converted to a generic, persisted AudioJob without composing it in PiperSynth:

```python
job = pipe.to_audio_job(plan)
manifest = job.save("speech.audiojob")
```

`AudioClip` IDs preserve UtterPlan segment IDs. Resolved semantic pauses are explicit `Silence` items, and the job includes an explicit compatibility output policy. Replay is producer-neutral:

```python
from audiocompose import AudioJob, Composer

job = AudioJob.load("speech.audiojob/audiojob.json")
composition = Composer().compose(job)
```

The normal `render_plan()` API builds and composes this job exactly once, then adapts the composed waveform back to `AudioResult`. Streaming APIs remain a separate batch-independent path.

## Runnable examples

The maintained examples use catalog voices and require no manual model download.
They explicitly create and persist an `UtterancePlan` before rendering it. Generated plans
and WAV files are written below `example-artefacts/`. See [`examples/README.md`](examples/README.md).

```bash
python examples/basic.py
python examples/run_all.py
```

Use `is_phonemes=True` only for direct Piper phoneme input. It bypasses UtterPlan and does not attach a semantic plan to the result.

## Local models

Existing explicit local model usage remains network-free:

```python
from pipersynth import PiperPipeline, PipelineConfig

with PiperPipeline(PipelineConfig(model_path="voice.onnx")) as pipe:
    pipe("No network is used here.").save_wav("local.wav")
```

`PiperVoice.load()` and `PiperPipeline(PipelineConfig(...))` never resolve the catalog or download assets. Use `PiperVoice.from_pretrained()` or `PiperPipeline.from_pretrained()` when managed catalog resources are desired.

## Voice discovery and cache

```python
from pipersynth import VoiceAssetManager, list_voices

for voice in list_voices(language="en", quality="medium"):
    print(voice.id, voice.name)

manager = VoiceAssetManager()
metadata = manager.get_voice_metadata("en_US-lessac-medium")
bundle = manager.resolve_voice("en_US-lessac-medium")
print(bundle.model_card_text)
```

Set `ONNXVOICE_CACHE_DIR` or pass `cache_dir=` explicitly to control the OnnxVoice store. `PIPERSYNTH_CACHE_DIR` remains accepted as a PiperSynth compatibility alias. Set `PIPERSYNTH_OFFLINE=1` for process-wide offline operation. Explicit `offline=` arguments take precedence.

OnnxVoice owns installed artifacts, manifests, checksums, and locks. PiperSynth's `VoiceAssetManager` and `VoiceBundle` are compatibility views over that store. Voice licenses apply to the downloaded model and are not part of the PiperSynth Apache-2.0 license.

The CLI provides catalog and cache operations:

```bash
pipersynth voices list --language en --quality medium
pipersynth voices show en_US-lessac-medium
pipersynth voices download en_US-lessac-medium
pipersynth voices license en_US-lessac-medium
pipersynth voices path en_US-lessac-medium
pipersynth speak --voice en_US-lessac-medium "Hello from PiperSynth." -o hello.wav
pipersynth cache info
```

The original local-model command remains supported:

```bash
pipersynth voice.onnx "Hello world." -o hello.wav
```

## Optional features

The UtterPlan dependency provides Spokenform and SSMD planning. Install `pipersynth[playback]` for `AudioResult.play()` and streaming playback, or `pipersynth[gpu]` for the OnnxVoice GPU provider. Catalog support is provided by OnnxVoice and is also available as `pipersynth[catalog]`.

The core API supports sentence and paragraph units through UtterPlan, resolved semantic pauses, plan save/load, and PCM iteration through `iter_pcm()`. It does not claim generic voice blending, approximate word timings, hidden language detection, model conversion, training, quantization, or HTTP serving.

See [`docs/architecture.md`](docs/architecture.md), [`docs/providers.md`](docs/providers.md), [`docs/troubleshooting.md`](docs/troubleshooting.md), and [`examples/download_and_synthesize.py`](examples/download_and_synthesize.py).
