Metadata-Version: 2.5
Name: index-tts-2.5-onnx
Version: 0.1.0
Summary: IndexTTS-2.5 voice cloning on ONNX Runtime: fp32 bit-exact, torch-free, one-click uvx, CPU/CUDA
Project-URL: Homepage, https://huggingface.co/yunfengwang/IndexTTS-2.5-onnx
Project-URL: Source, https://huggingface.co/yunfengwang/IndexTTS-2.5-onnx
Author: yunfengwang
License: Bilibili-IndexTTS
Keywords: indextts,onnx,onnxruntime,tts,voice-cloning
Requires-Python: >=3.10
Requires-Dist: huggingface-hub>=0.24
Requires-Dist: kaldi-native-fbank>=1.18
Requires-Dist: librosa>=0.10
Requires-Dist: numpy>=1.24
Requires-Dist: onnxruntime>=1.17
Requires-Dist: pyyaml>=6.0
Requires-Dist: soundfile>=0.12
Requires-Dist: tiktoken>=0.7
Requires-Dist: transformers>=4.45
Requires-Dist: wetext
Description-Content-Type: text/markdown

# index-tts-2.5-onnx

[IndexTTS-2.5](https://modelscope.cn/models/IndexTeam/IndexTTS-2.5) voice cloning on **ONNX Runtime** — fp32, bit-exact against the PyTorch CPU reference, torch-free, and ships as a one-click `uvx` package that auto-downloads the weights from Hugging Face. Runs anywhere ONNX Runtime runs: Linux / Windows / macOS, x86 / ARM, CPU or NVIDIA GPU (CUDA).

- **Voice cloning** from a short reference clip (≤15 s) — Chinese / English / Japanese / Cantonese, including mixed-language text with numbers and abbreviations.
- **Bit-exact fp32**: greedy decoding reproduces the PyTorch CPU reference acoustic tokens exactly (73/73 and 83/83 on the verification fixtures); every stage matches at cosine ≥ 0.9999.
- **Torch-free**: numpy + onnxruntime only. No PyTorch, no MLX, no MNN.
- **CPU + CUDA**: `--device auto` picks CUDA when `onnxruntime-gpu` is installed, otherwise CPU.

> Platform: any OS with Python 3.10+. For NVIDIA GPUs install `onnxruntime-gpu` instead of `onnxruntime`.

---

## Features

- **Zero-shot voice cloning** — supply any ≤15 s clean reference; the timbre and speaking style are carried into the output. Build the speaker once and reuse it across unlimited lines.
- **Multilingual + code-switching** — `zh`, `en`, `ja`, `yue`, and mixed text in a single sentence (e.g. `Use the CPU or GPU, 都可以`).
- **Text normalization** — numbers, abbreviations and symbols are read out correctly via `wetext` (e.g. `2025 年` → “二零二五年”, `100 万` → “一百万”). Disable with `--no-normalization`.
- **Rich decoding controls** — greedy or sampling (`top_k` / `top_p` / `temperature` / `seed`), `repetition_penalty`, `duration_factor` (speech rate), and the flow-matching solver knobs (`n_timesteps`, `cfg_rate`).
- **Auto-download** — weights pull from Hugging Face on first run and are cached for reuse; CLI and Python API share the same cache.
- **Timing report** — every `synth` prints load / clone / synth time, RTF, and a per-stage breakdown.

## Install / one-click run

No install needed with [uv](https://docs.astral.sh/uv/):

```bash
uvx index-tts-2.5-onnx synth \
    --ref /path/to/voice.wav \
    --text "大家好, this is IndexTTS running on ONNX Runtime." \
    --out out.wav
```

The first run downloads the fp32 models (~7 GB) from Hugging Face into the standard HF cache (`~/.cache/huggingface`); later runs reuse it.

For an NVIDIA GPU, install the GPU build of ONNX Runtime and pass `--device cuda` (or leave `auto`, which detects it):

```bash
uv pip install onnxruntime-gpu   # replaces onnxruntime
uvx --from index-tts-2.5-onnx --with onnxruntime-gpu index-tts-2.5-onnx synth \
    --ref voice.wav --text "..." --device cuda
```

Or install into an environment:

```bash
pip install index-tts-2.5-onnx          # CPU
pip install index-tts-2.5-onnx onnxruntime-gpu   # + CUDA
```

Pre-download the weights ahead of time:

```bash
uvx index-tts-2.5-onnx download
```

## CLI usage

```
index-tts-2.5-onnx synth --ref REF.wav --text "..." --out out.wav [options]
```

| Option | Default | Description |
|---|---|---|
| `--ref` | (required) | Reference audio to clone (≤15 s, clear speech). |
| `--text` | (required) | Text to synthesize (zh/en/ja/yue, mixed OK). |
| `--out` | `output.wav` | Output WAV path (22050 Hz, int16). |
| `--lang` | `zh` | Language hint: `zh`, `en`, `ja`, `yue`. |
| `--device` | `auto` | `auto` / `cpu` / `cuda` / `coreml`. auto = CUDA if available, else CPU. |
| `--threads` | `4` | CPU intra-op threads. |
| `--greedy` | off | Greedy decoding (deterministic). |
| `--seed` | random | RNG seed for sampling. |
| `--top-k` / `--top-p` / `--temperature` | `30` / `0.8` / `0.8` | Sampling controls. |
| `--repetition-penalty` | `10.0` | Repetition penalty. |
| `--max-mel-tokens` | `1500` | Max acoustic tokens per segment. |
| `--duration-factor` | `1.0` | Speech-rate multiplier. |
| `--n-timesteps` / `--cfg-rate` | `25` / `0.7` | Flow-matching solver controls. |
| `--model-dir` | auto | Use a local weight dir instead of downloading. |
| `--no-normalization` | off | Disable text normalization. |

## Python API

```python
from index_tts_2_5_onnx import IndexTTS

tts = IndexTTS(device="auto")          # auto-downloads weights on first use
sr, pcm = tts.clone(
    "AI 模型在 2025 年处理了 100 万条数据。",
    ref_audio_path="voice.wav",
    out="clone.wav",                   # optional; also returns pcm
    lang="zh",
)

# Reuse one cloned voice across many lines (build the speaker once):
spk = tts.build_speaker("voice.wav")
for i, line in enumerate(["第一句。", "Second sentence.", "第三句。"]):
    sr, pcm = tts.clone(line, ref_audio_path=None, spk=spk, out=f"line{i}.wav")
```

`synthesize(...)` returns the raw int16 PCM array (`numpy`) at `tts.sample_rate` (22050 Hz); `clone(...)` additionally writes a WAV when `out` is given. Use your own reference audio only with permission — see **License**.

## Speed

CPU (Apple M5 Pro, 4 threads, fp32): GPT step ≈ 16 ms/token, CFM step ≈ 138 ms, BigVGAN ≈ 4.9 s for a ~3 s clip — end-to-end RTF ≈ 3.3. The BigVGAN vocoder dominates on ONNX Runtime CPU; if you need fast CPU inference, use the [MNN build](https://huggingface.co/yunfengwang/IndexTTS-2.5-mnn) (same pipeline, ~6× faster vocoder). On Apple Silicon, use [index-tts-2.5-mlx](https://pypi.org/project/index-tts-2.5-mlx/) (GPU, faster than real-time). CUDA EP is the fast path on NVIDIA GPUs.

## Quality / effect

**Numeric fidelity** — the fp32 ONNX graphs are bit-exact against the PyTorch CPU reference: every verification stage passes at cosine = 1.0000, greedy decoding reproduces the reference acoustic tokens exactly (fx0 73/73, fx1 83/83), and the vocoder output matches at mel-spectrogram SNR ≈ 85 dB (inaudible). Output audio is for practical purposes identical to running the official PyTorch model on CPU.

**Why no int8?** Every ONNX Runtime CPU quantization scheme was evaluated and rejected on measurement: dynamic QInt8 quantization flips GPT greedy argmax (only 26% of reference acoustic tokens survive — the decode drifts), and MatMulNBits weight-only int8 both degrades GPT logits (cos 0.985) and runs *slower* than fp32 on this pipeline. So this distribution ships fp32 only — quality is the feature here. For smaller/faster quantized builds see the MNN (ARM/CPU) and MLX (Apple Silicon) packages.

**A note on `coreml`**: the provider is selectable but not recommended — every stage benchmarked slower than CPU, and the CFM estimator graph does not run on it.

## How it works

Pipeline: text frontend (tiktoken + wetext normalization) → w2v-bert semantic features → semantic codec → **GPT** autoregressive acoustic tokens → length regulator → flow-matching **CFM** (DiT) → **BigVGAN** vocoder → 22050 Hz WAV. The orchestration (samplers, solvers, DSP) is numpy; the heavy networks are ONNX graphs exported from the PyTorch reference and verified stage-by-stage.

Model weights: [`yunfengwang/IndexTTS-2.5-onnx`](https://huggingface.co/yunfengwang/IndexTTS-2.5-onnx) (fp32).

## License

Code in this package is provided under the same terms as the upstream project. IndexTTS-2.5 model weights are subject to the original **Bilibili IndexTTS** license — see the upstream model card. Use voice cloning responsibly and only with consent from the voice owner.
