Metadata-Version: 2.4
Name: qwen3-tts-mnn
Version: 0.1.0
Summary: Qwen3-TTS (12Hz, voice clone) inference on pure CPU via MNN — no PyTorch required at runtime
Author: Qwen3-TTS MNN Community
License: Apache-2.0
Project-URL: Homepage, https://github.com/QwenLM/Qwen3-TTS
Project-URL: Model, https://modelscope.cn/models/Qwen/Qwen3-TTS-12Hz-0.6B-Base
Keywords: tts,qwen3,mnn,voice-clone,speech-synthesis,cpu-inference
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: numpy>=1.23
Requires-Dist: MNN>=3.0
Requires-Dist: regex>=2023.0.0
Provides-Extra: extract
Requires-Dist: torch; extra == "extract"
Requires-Dist: qwen-tts; extra == "extract"
Requires-Dist: soundfile; extra == "extract"
Provides-Extra: export
Requires-Dist: torch; extra == "export"
Requires-Dist: qwen-tts; extra == "export"
Requires-Dist: onnx; extra == "export"
Requires-Dist: onnxruntime; extra == "export"
Requires-Dist: soundfile; extra == "export"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: soundfile; extra == "dev"

# qwen3-tts-mnn

[Qwen3-TTS-12Hz-0.6B-Base](https://modelscope.cn/models/Qwen/Qwen3-TTS-12Hz-0.6B-Base) 的**纯 CPU** 推理包 — 基于 [MNN](https://github.com/alibaba/MNN),支持零样本声音克隆。

- 运行时只需 `numpy + MNN`(pymnn),**无需 PyTorch / CUDA**
- 内置纯 Python Qwen2 BPE 分词器(与 HuggingFace 输出逐 token 一致)
- 与原生 PyTorch 推理 codec 匹配率 ≥99%(fp16 权重,实测 g0 99.0% / 全 16 组 99.9%)
- 输出 24kHz 单声道波形

## 安装

```bash
pip install qwen3-tts-mnn
```

## 模型资产

PyPI 包不含模型权重(~1.9GB),需自行准备 MNN 资产目录:

```
model_dir/
  talker_step.mnn      # Talker LM 单步 (带 KV cache)
  cp_step.mnn          # CodePredictor 单步
  vocoder.mnn          # 12Hz codec -> 24kHz 波形
  weights/*.bin        # 嵌入表/头 fp16 + meta.json
  tokenizer/{vocab.json, merges.txt}
```

声线目录(克隆资产,纯 numpy,运行时无 torch 依赖):

```
voice_dir/
  ref_code.i32.bin     # [T,16] int32, 参考音频的 12Hz codec
  spk_emb.f32.bin      # [1024] float32, 说话人嵌入
  meta.json            # {ref_text, ref_ids, ref_frames}
```

## 快速开始

### Python API

```python
from qwen3_tts_mnn import Qwen3TtsMnn

tts = Qwen3TtsMnn('model_dir', num_threads=8)
tts.load_voice('voice_dir')

pcm = tts.synthesize('你好呀,我是小柒!')        # float32 [-1,1], 24kHz
tts.synthesize_to_file('你好呀', 'out.wav')      # 直接写 wav (标准库)
```

可调参数:`temperature / top_k / top_p / repetition_penalty / seed / max_steps / min_new_tokens`,
以及 `synthesize_codes()`(取 codec 帧)与 `codes_to_wav()`(离线解码)、`on_frame` 流式回调。

### 命令行

```bash
qwen3-tts-mnn --model-dir model_dir --voice voice_dir \
    --text '你好呀,我是小柒!' -o out.wav --threads 8 --seed 42
```

## 克隆新声音

用官方 PyTorch 模型**离线一次性**提取声线资产(之后推理不再需要 torch):

```bash
pip install qwen3-tts-mnn[extract]
qwen3-tts-mnn-extract --hf-model /path/to/Qwen3-TTS-12Hz-0.6B-Base \
    --ref-audio ref.wav --ref-text '参考音频的逐字文本' -o my_voice/
```

参考音频建议 3~15s 清晰人声,`--ref-text` 必须与音频内容逐字一致。

```python
from qwen3_tts_mnn.voice import extract_voice
profile = extract_voice(hf_model_path, 'ref.wav', '逐字文本', out_dir='my_voice/')
```

## 架构

```
文本 ──> Qwen2 BPE ──> text_proj ──┐
                                   ├─> Talker LM (28层, KV cache) ──> g0 logits ──> CP (15步) ──> codes [T,16]
ref_code+spk_emb ──> ICL 装配 ─────┘                                                   │
                                                              vocoder.mnn <──────────┘
                                                                   │
                                                              24kHz wav
```

- Talker/CodePredictor 以 `*_step.mnn`(prefill/decode 共用单步 + KV cache 输入输出)运行
- 嵌入表/头等小权重为 fp16 bin,由 numpy 查表/矩阵乘完成
- 采样对齐原生实现:temperature + top_k + top_p + repetition_penalty(unique 历史)

## 性能参考

Apple Silicon(8 线程, fp16):RTF ≈ 4~6(即 1s 音频需 4~6s 合成)。生产环境建议
预合成固定台词缓存,或流式分段合成。

## License

Apache-2.0(代码)。模型权重遵循 Qwen 模型许可证。
