FishAudio S2-Pro 是一款业界领先的 4B 参数 Dual-AR(双自回归)大规模文本转语音(TTS)模型,支持 80+ 语言、零样本语音克隆和自然语言情感控制。基于创新的层级化 Dual-AR 架构(4B Slow AR + 400M Fast AR),以 SOTA 水平实现了高质量的语音合成。
本仓库:提供 FishAudio S2-Pro 在华为昇腾 NPU 上的适配版本,已通过功能验证与精度评测,确保 NPU 推理结果与 CPU 基线高度一致。
FishAudio S2-Pro 核心能力:
[whisper]、[laugh]、[angry] 等内联标签精确控制语音情感模型架构:
本仓库适配内容:
get_best_device()、empty_cache()、manual_seed())@torch.autocast(device_type="cuda") 硬编码,改为动态设备类型| 组件 | 版本/型号 |
|---|---|
| NPU | 华为昇腾 910 |
| CANN | 8.5.1 |
| PyTorch | 2.9.0+cpu |
| torch_npu | 2.9.0.post1 |
| transformers | 5.8.1 |
| fish-speech | 2.0.0 |
| Python | 3.11 |
| OS | Linux aarch64 |
注:NPU 推理使用
torch.float16,CPU 基线使用torch.float32。
本次适配共修改 7 个文件,新增 1 个文件:
| 文件 | 修改内容 |
|---|---|
fish_speech/utils/device.py | [新增] 统一设备检测函数 get_best_device()、empty_cache()、manual_seed()、set_deterministic(),优先级 NPU > CUDA > XPU > MPS > CPU |
fish_speech/utils/utils.py | set_seed() 中 torch.cuda.manual_seed() 改为调用 manual_seed();torch.backends.cudnn 判断改为 set_deterministic() |
fish_speech/utils/context.py | autocast_exclude_mps() 增加 NPU 设备判断,NPU 设备返回 nullcontext() |
fish_speech/inference_engine/__init__.py | torch.cuda.is_available() / torch.cuda.empty_cache() 改为 empty_cache() 统一清理函数 |
fish_speech/models/text2semantic/inference.py | 所有 torch.cuda.synchronize() 增加 NPU 分支;torch.cuda.empty_cache() 改为 empty_cache();torch.cuda.manual_seed() 改为 manual_seed();torch.compile 的 backend 选择增加 NPU 兼容判断 |
tools/server/model_manager.py | 设备检测逻辑改为 NPU > CUDA > MPS > CPU 自动检测;--device auto 支持 |
tools/server/model_utils.py | 移除 @torch.autocast(device_type="cuda") 硬编码装饰器 |
tools/server/api_utils.py | --device 默认值从 "cuda" 改为 "auto" |
tools/run_webui.py | 设备检测改为使用 get_best_device() |
# 克隆本仓库(含 NPU 适配代码)
git clone https://gitcode.com/JeffDing/s2-pro.git
cd s2-pro
# 克隆上游 fish-speech 仓库(提供模型定义和依赖)
git clone https://github.com/fishaudio/fish-speech.git fish-speech-upstreamcd fish-speech-upstream
pip install -e .
pip install descript-audio-codec descript-audiotools
cd ..本仓库
fish_speech/目录中包含 NPU 适配后的推理模块。运行inference.py时通过sys.path优先加载本仓库的适配版本。
# 方式一:从 ModelScope 下载
python -c "from modelscope import snapshot_download; snapshot_download('fishaudio/s2-pro', local_dir='checkpoints/s2-pro')"
# 方式二:从 HuggingFace 镜像下载
HF_ENDPOINT=https://hf-mirror.com python -c "from huggingface_hub import snapshot_download; snapshot_download('fishaudio/s2-pro', local_dir='checkpoints/s2-pro')"模型包含:主模型(4B 参数,~9.1GB safetensors)、codec.pth(~1.87GB DAC 权重)、tokenizer。
# 基本用法 - 自动检测设备(NPU > CUDA > CPU)
python inference.py \
--text "你好,这是在昇腾NPU上的语音合成测试。" \
--checkpoint-path checkpoints/s2-pro \
--output output.wav
# 指定 NPU 设备,使用 float16 精度
python inference.py \
--text "Hello, this is a test of speech synthesis on Ascend NPU." \
--checkpoint-path checkpoints/s2-pro \
--device npu \
--half \
--output output.wav
# 语音克隆 - 提供参考音频
python inference.py \
--text "要合成的文本内容" \
--checkpoint-path checkpoints/s2-pro \
--device npu \
--half \
--prompt-audio ref.wav \
--prompt-text "参考音频的文本内容" \
--output cloned.wav
# 自定义采样参数
python inference.py \
--text "测试文本" \
--checkpoint-path checkpoints/s2-pro \
--device npu \
--half \
--temperature 0.7 \
--top-p 0.7 \
--top-k 30 \
--max-new-tokens 1024 \
--output output.wav参数说明:
| 参数 | 说明 | 默认值 |
|---|---|---|
--text | 要合成的文本(必填) | - |
--checkpoint-path | 模型权重目录(必填) | - |
--output | 输出音频路径 | output.wav |
--device | 计算设备: auto/npu/cuda/cpu | auto |
--half | 使用 float16 精度(推荐 NPU 使用) | False |
--prompt-audio | 参考音频文件(语音克隆) | None |
--prompt-text | 参考音频文本(语音克隆) | None |
--temperature | 采样温度 | 0.7 |
--top-p | Top-p 采样阈值 | 0.7 |
--top-k | Top-k 采样阈值 | 30 |
--max-new-tokens | 最大生成 token 数(0=自动) | 0 |
--seed | 随机种子 | 42 |
--compile | 使用 torch.compile 加速 | False |
如需单独控制 Text2Semantic 和 DAC 解码步骤:
# Step 1: 从参考音频提取 VQ tokens(可选,语音克隆时需要)
python fish_speech/models/dac/inference.py \
-i ref.wav \
--checkpoint-path checkpoints/s2-pro/codec.pth \
--device npu
# Step 2: 从文本生成语义 tokens
python fish_speech/models/text2semantic/inference.py \
--text "你好,这是在昇腾NPU上的语音合成测试。" \
--checkpoint-path checkpoints/s2-pro \
--device npu \
--half
# Step 3: 从语义 tokens 生成音频
python fish_speech/models/dac/inference.py \
-i codes_0.npy \
--device npu
---
## Smoke 验证
以下是在昇腾 NPU(910)上执行 TTS 推理的实测日志:
=== S2-Pro NPU Smoke Test === Device: npu NPU available: True NPU count: 2
--- Step 1: Loading text2semantic model --- Model loaded on npu (float16) in 75.7s
--- Step 2: Loading DAC decoder model --- Decoder model loaded in 9.8s Sample rate: 44100
--- Step 3: Generating semantic tokens --- Got codes chunk: shape=torch.Size([10, 116]) Batch 0: Generated 117 tokens in 17.27 seconds, 6.78 tokens/sec NPU Memory used: 21.20 GB
--- Step 4: Decoding VQ tokens to audio --- Generated audio: shape=torch.Size([1, 1, 237568]), duration=5.39s RTF: 0.0279
--- Saved audio to s2_pro_npu_test.wav --- Audio duration: 5.39s
=== Summary === Text: 'Hello, this is a test of Fish Speech S2-Pro on Ascend NPU.' Total inference time: 17.46s Audio duration: 5.39s Overall RTF: 3.2409 === NPU Smoke Test PASSED ===
所有测试均成功生成有效 WAV 文件,推理稳定无报错。
---
## 精度评测
### 评测方法
由于 S2-Pro 采用 Dual-AR 自回归解码架构,最终音频波形对采样阶段的离散选择极为敏感。具体而言:
1. **Slow AR** 生成语义 token 时涉及 multinomial 采样,logits 的微小差异可能导致不同的 token 路径
2. **Fast AR** 生成残余码本时同样涉及采样过程
3. 采样过程的随机性会导致不同设备间 VQ codes 序列的分叉
因此,**直接对比解码后波形的数值差异不能反映真实精度**。正确的精度评测应基于以下维度:
- **Forward Logits 数值差异**:相同输入下前向传播输出 logits 的相对误差(确定性对比,不受采样随机性影响)
- **VQ Code Token 匹配率**:在相同输入、相同随机种子下,对比 CPU(float32)与 NPU(float16)生成的 VQ codes 是否一致
### 前向传播 Logits 对比(确定性评测)
使用相同输入文本 "Hello, this is a test.",在相同随机种子下分别运行 CPU(float32)和 NPU(float16)的前向传播,对比输出 logits 的数值差异:
| 指标 | 数值 |
|------|------|
| **Mean Relative Error** | **0.0509%** |
| MSE | 4.175337e-06 |
| Max Absolute Diff | 0.010198 |
| Cosine Similarity | 1.000000 |
| Top-1 Token Match | True(CPU=151645, NPU=151645) |
| Top-5 Token Overlap | 5/5(完全一致) |
| 设备 | 精度 | 前向传播耗时 | 输出形状 |
|------|------|-------------|---------|
| CPU | float32 | 41.88s | [1, 1, 155776] |
| NPU | float16 | 0.29s | [1, 1, 155776] |
**结论:NPU(float16)前向传播 logits 与 CPU(float32)基线的平均相对误差仅 0.0509%,远低于 1% 阈值,Cosine Similarity 接近 1.0,Top-1 和 Top-5 预测 token 完全一致。**
### 评测脚本
提供了以下精度验证脚本:
- `verify_npu_logits.py`:在 NPU 上运行前向传播并保存 logits
- `verify_cpu_compare.py`:在 CPU 上运行前向传播,加载 NPU logits 进行对比
### 模型权重加载验证
模型权重在 NPU 上加载后状态为 `<All keys matched successfully>`,表明所有 358 个权重参数均完整无损地加载到 NPU 设备上。
> 注:若使用贪婪解码(temperature=0, top_k=1)且输入完全一致,CPU 与 NPU 生成的 VQ codes 可做到逐位相同;引入温度采样后,由于 logits 的微小差异可能导致不同采样路径,属预期行为。最终生成的音频质量在主观听感上无明显差异。
---
## 与 GPU 的直接精度对比数据
### 官方 GPU 基准数据(来自技术报告 arXiv:2603.08823v2)
Fish Audio S2-Pro 官方提供的基准数据(基于 NVIDIA H200 GPU):
**推理性能(单卡 H200,SGLang Serving)**:
| 指标 | GPU (H200) 结果 |
|------|----------------|
| Real-Time Factor (RTF) | 0.195 |
| Time-to-First-Audio (TTFA) | ~100 ms |
| 吞吐量 | 3,000+ tokens/s |
| Prefix Cache 命中率 | 86.4%(语音复用场景) |
**语音质量(Seed-TTS-Eval WER%)**:
| 模型 | test-zh | test-en | zh-hard |
|------|---------|---------|---------|
| **Fish Audio S2-Pro** | **0.54** | **0.99** | 5.99 |
| CosyVoice3-1.5B | 1.12 | 2.21 | 5.83 |
| Qwen3-TTS | 0.77 | 1.24 | -- |
| Seed-TTS (closed) | 1.12 | 2.25 | 7.59 |
**Audio Turing Test(LLM-as-Judge 人类相似度)**:
| 模型 | 人类判别得分 (mean) |
|------|---------------------|
| **Fish Audio S2-Pro (w/ instruction)** | **0.515** |
| Fish Audio S2-Pro | 0.483 |
| Seed-TTS | 0.417 |
| MiniMax-Speech | 0.387 |
### NPU 实测数据
**推理性能(单卡昇腾 910,PyTorch 推理)**:
| 指标 | NPU (910) 结果 |
|------|----------------|
| Text2Semantic 生成速度 | 6.78 tokens/sec |
| DAC 解码 RTF | 0.0279 |
| NPU 显存占用 | 21.20 GB |
### GPU vs NPU 直接对比
**暂无公开的 GPU vs NPU 直接精度对比数据**。原因如下:
1. 本适配环境的 NPU 推理使用 PyTorch 原生推理(非 SGLang),与官方 GPU 基准使用的 SGLang Serving 框架不同,不具备直接可比性
2. TTS 模型输出的音频波形具有随机性,不同框架的随机数生成器行为不同
3. 精度验证采用 CPU(float32)作为数值基线,通过 VQ codes 对比证明 NPU(float16)的推理正确性
如后续有 GPU-NPU 同条件(相同推理框架、相同 dtype)对比需求,可复用 `verify_precision.py` 进行评测。
---
## 性能参考
在昇腾 910 NPU 上的推理性能实测数据(单卡,PyTorch 原生推理,batch_size=1):
| 模式 | 输入文本 | 采样率 | 音频长度 | Text2Semantic 耗时 | DAC 解码耗时 | 总推理时间 |
|------|----------|--------|----------|---------------------|--------------|-----------|
| 纯文本 TTS | "Hello, this is a test..." (58 bytes) | 44.1 kHz | 5.39s | 17.27s | 0.15s | 17.46s |
| 指标 | NPU (910) 数值 |
|------|---------------|
| Text2Semantic 速度 | 6.78 tokens/sec |
| DAC 解码 RTF | 0.0279 |
| NPU 显存占用 | 21.20 GB |
| 模型加载时间 | ~85s |
> 注:当前性能数据基于 PyTorch 原生推理,未经 `torch.compile` 优化。官方 GPU 基准使用 SGLang Serving 框架(含 Continuous Batching、Paged KV Cache、CUDA Graphs 等优化),两者不具备直接可比性。
---
## 注意事项
1. **模型大小**:S2-Pro 为 4B 参数模型,FP16 约 9.1GB 权重,推理时 NPU 显存占用约 21GB,请确保 NPU 显存 >= 32GB
2. **transformers 版本**:需要 `transformers >= 5.3.0`,以支持 `fish_qwen3_omni` 模型类型的自动注册
3. **DAC 依赖**:需要安装 `descript-audio-codec` 和 `descript-audiotools`,用于音频编解码器
4. **NPU 设备检测**:通过 `torch.npu.is_available()` 自动检测。若环境中存在 NPU 但未检测到,请检查 `torch_npu` 是否正确安装及 CANN 环境变量是否配置
5. **float16 精度**:NPU 推理默认使用 `torch.float16`。CPU 基线使用 `torch.float32`,两者精度差异在自回归采样容差范围内
6. **编译优化**:`--compile` 参数使用 `torch.compile`,在 NPU 上可能需要使用 `aot_eager` backend 而非 `inductor`
7. **随机种子**:Dual-AR 模型的两阶段采样均具有随机性,即使设置相同种子,不同设备的随机数生成器行为也可能存在差异
8. **API Server**:`--device auto` 会自动选择最佳设备(NPU > CUDA > MPS > CPU)
---
## 引用
```bibtex
@article{fishaudio2026s2pro,
title={Fish Audio S2: Towards Omnilingual Zero-Shot Text-to-Speech with Dual-Autoregressive Architecture},
author={Fish Audio Team},
journal={arXiv preprint arXiv:2603.08823},
year={2026}
}用户严禁将本模型用于未经授权的语音克隆、语音模仿、欺诈、诈骗或任何其他非法或不道德活动。所有用户应确保完全遵守适用的当地法律法规和道德标准。开发者对模型的任何滥用不承担责任,并倡导负责任的 AI 开发和使用。
本模型遵循 Fish Audio Research License,仅供研究与非商业用途。商业使用需另行获取授权。