Skip to main content

index-tts-2.5-mnn

IndexTTS-2.5 voice cloning on MNN — fast CPU inference (x86 / ARM, Linux / Windows / macOS), torch-free, and ships as a one-click uvx package that auto-downloads the weights from Hugging Face.

  • Voice cloning from a short reference clip (≤15 s) — Chinese / English / Japanese / Cantonese, including mixed-language text with numbers and abbreviations.
  • Reference-exact decoding: both shipped quant sets reproduce the PyTorch CPU reference greedy acoustic tokens exactly (73/73 and 83/83 on the verification fixtures); fp32 is additionally bit-exact at every stage.
  • Torch-free: numpy + pymnn only. No PyTorch, no ONNX Runtime, no MLX.
  • Quantized by default: every module ships as fp16 weights (fp32 compute) — half the download of fp32, gate-verified to reproduce the reference greedy acoustic tokens 100% on both zh/en fixtures.

Platform: any OS with Python 3.10+. The pip MNN wheel is CPU-only; on Apple Silicon the MLX build (GPU) is ~7× faster than real-time, and on NVIDIA GPUs the ONNX build with CUDA is the fast path. This package is the fast CPU option — its BigVGAN vocoder runs ~4× faster than ONNX Runtime CPU.


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-switchingzh, 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. 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:

uvx index-tts-2.5-mnn synth \
    --ref /path/to/voice.wav \
    --text "大家好, this is IndexTTS running on MNN." \
    --out out.wav

The first run downloads the fp16 weights (~3.6 GB) from Hugging Face into the standard HF cache; later runs reuse it. Use --quant fp32 for the bit-exact reference set (~7 GB).

Or install into an environment:

pip install index-tts-2.5-mnn

Pre-download the weights ahead of time:

uvx index-tts-2.5-mnn download            # fp16 (default)
uvx index-tts-2.5-mnn download --quant fp32

CLI usage

index-tts-2.5-mnn 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.
--quant fp16 fp16 (all modules, ~3.6 GB) or fp32 (bit-exact, ~7 GB).
--threads 4 CPU 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

from index_tts_2_5_mnn import IndexTTS

tts = IndexTTS(quant="fp16")           # 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

End-to-end synthesis, warm, 4 threads (Apple M5 Pro, ~3 s of audio). RTF = synthesis time ÷ audio duration (lower is better).

Backend synth RTF gpt cfm bigvgan
MNN fp32 9.20 s 3.16 3.61 s 4.42 s 1.12 s
MNN fp16 (default) 9.48 s 3.25 3.84 s 4.42 s 1.12 s
ONNX Runtime fp32 (CPU) 9.53 s 3.27 1.20 s 3.51 s 4.81 s

fp16 is weight-only quantization: MNN dequantizes to fp32 at load and computes in fp32, so speed is the same — the win is half the download.

MNN's vocoder is ~4× faster than ONNX Runtime CPU (1.1 s vs 4.8 s); ORT wins the GPT decode. End-to-end they land at the same place on this machine — pick MNN for the smaller quantized download and the self-contained CPU wheel.

Quality / effect

Numeric fidelity — fp32 and fp16 both reproduce the PyTorch CPU reference greedy acoustic tokens exactly (fx0 73/73, fx1 83/83). fp32 is bit-exact at every stage (cosine = 1.0000, vocoder mel-SNR ≈ 70 dB). fp16 keeps stage cosine ≥ 0.99998 and vocoder mel-SNR 26–29 dB (gate: 25 dB — inaudible); only the GPT stays bit-exact under fp16, because greedy argmax absorbs the sub-1e-5 logit error.

Quantization: what ships and why. fp16 weights pass every gate on every module — that's the default set. Everything deeper was measured and rejected:

  • int8/int4 BigVGAN destroys the vocoder (SNR ≤ 15 dB vs 64.5 dB fp32; int4 is pure noise at −1.4 dB).
  • int8 CFM mel outliers (maxdiff 0.6–1.2) collapse even an fp32 vocoder.
  • int8 CAMPPlus / semantic encoder shifts the GPT conditioning just enough (cos 0.992–0.999) to flip greedy argmax — the EN fixture keeps only 17% of reference tokens.
  • int8 GPT (any block config) flips a close argmax (35% match); fp16 GPT compute (MNN precision="low") also flips it (≤7%) — fp16 is only safe as a weight format, never as a compute precision.

So: fp16 weights everywhere, fp32 compute. No int8/int4 set is shipped because none preserved quality.

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 MNN graphs converted from the ONNX export and verified stage-by-stage against the PyTorch reference.

Model weights: yunfengwang/IndexTTS-2.5-mnn.

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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

index_tts_2_5_mnn-0.1.1.tar.gz (22.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

index_tts_2_5_mnn-0.1.1-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

File details

Details for the file index_tts_2_5_mnn-0.1.1.tar.gz.

File metadata

  • Download URL: index_tts_2_5_mnn-0.1.1.tar.gz
  • Upload date:
  • Size: 22.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for index_tts_2_5_mnn-0.1.1.tar.gz
Algorithm Hash digest
SHA256 d8ad1fcec564fe88b607f247513cbd990cb84736e71b11e250bded3588bb6606
MD5 a045247377d2c4bfbbdd5da90b574a22
BLAKE2b-256 489e4d7c566309db8da14f7665131c558fdd1f9637d076f79d1369c522cc1c87

See more details on using hashes here.

File details

Details for the file index_tts_2_5_mnn-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: index_tts_2_5_mnn-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 27.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for index_tts_2_5_mnn-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1287ec5e0e61329b6a96a82f9b0d5c423fabfa1fbdd0b21c50d2a8f88278171e
MD5 ecd389455522deecb6c3fecfe945802b
BLAKE2b-256 317e6ed6df43134813514014d695cda3214d07785aa63a1925a51ba0e5749dfd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page