本文档记录 NeuTTS Air (neuphonic/neutts-air) 在华为昇腾 Ascend 910 NPU 环境的适配、部署与验证结果。
NeuTTS Air 是一款基于 Qwen2 0.5B 架构的实时文本转语音(TTS)模型,由 Neuphonic 开发。该模型使用 NeuCodec 神经音频编解码器,支持即时语音克隆,可在边缘设备上实现超真实语音合成。
| 项目 | 说明 |
|---|---|
| 模型架构 | Qwen2ForCausalLM (552.9M 参数) + NeuCodec (823M 参数) |
| 原始框架 | PyTorch + HuggingFace Transformers |
| 推理后端 | transformers (AutoModelForCausalLM) + neucodec |
| NPU 适配方式 | torch_npu + transfer_to_npu 自动迁移 |
| 精度 | bfloat16 |
| 采样率 | 24000 Hz (输出音频) |
由于 neutts 官方包依赖 espeak-ng 系统库且对 HuggingFace Hub 有网络依赖,本适配方案采用直接加载模型权重的方式,绕过 neutts 包的系统依赖,实现全离线 NPU 推理:
| 原始依赖 | 适配方案 |
|---|---|
neutts 包 (需要 espeak-ng) | 直接使用 transformers + neucodec |
| HuggingFace Hub 在线下载 | ModelScope 离线下载 + 本地 HF 缓存 |
torchtune (需要 CUDA) | 手动 patch get_device_capability() |
espeak-ng 音素化 | SimplePhonemizer 英语规则回退方案 |
| 组件 | 版本 |
|---|---|
torch_npu | 2.9.0.post1+gitee7ba04 |
torch | 2.9.0+cpu (torch_npu 增强) |
CANN | 8.5.1 |
transformers | 4.57.6 |
neucodec | 0.0.5 |
npu-smi | 25.5.2 |
/opt/atomgit/.cache/modelscope/hub/models/neuphonic/neutts-airpip install modelscope
# 下载 NeuTTS Air 骨干模型
modelscope download --model neuphonic/neutts-air
# 下载 NeuCodec 音频编解码器
modelscope download --model neuphonic/neucodec
# 下载语义编码器依赖 (w2v-bert-2.0)
modelscope download --model facebook/w2v-bert-2.0# 安装 neucodec 及其依赖
pip install neucodec --no-deps
pip install local-attention torchtune torchao vector-quantize-pytorch
# 安装音频处理库
pip install soundfile librosa scipy
# 安装 torch_npu (如未安装)
pip install torch-npu由于部署环境可能无法访问 HuggingFace Hub,需要将 ModelScope 下载的模型文件配置为 HF 本地缓存:
export HF_HOME="/opt/atomgit/.cache/huggingface"
export HF_HUB_OFFLINE=1
export TRANSFORMERS_OFFLINE=1
# 创建缓存目录结构
mkdir -p $HF_HOME/hub/models--facebook--w2v-bert-2.0/snapshots/main
cp /opt/atomgit/.cache/modelscope/hub/models/facebook/w2v-bert-2.0/* \
$HF_HOME/hub/models--facebook--w2v-bert-2.0/snapshots/main/torchtune 包的 _import_guard.py 在 NPU 上会因 torch.cuda.get_device_capability() 返回 None 而崩溃。需应用以下补丁:
# 编辑 /opt/atomgit/.local/lib/python3.11/site-packages/torchtune/utils/_import_guard.py
# 将:
# torch.cuda.is_available() and torch.cuda.get_device_capability() >= (7, 5)
# 替换为:
# torch.cuda.is_available() and (torch.cuda.get_device_capability() or (8, 0)) >= (7, 5)推理脚本 inference.py 已内置此补丁,无需手动操作。
source /usr/local/Ascend/ascend-toolkit/set_env.sh
export HF_HOME="/opt/atomgit/.cache/huggingface"
export HF_HUB_OFFLINE=1
export TRANSFORMERS_OFFLINE=1cd workdir/
python inference.py \
--text "Hello world, this is a test of the NeuTTS Air model on Ascend NPU." \
--ref_audio samples/ref.wav \
--output output.wav参数说明:
| 参数 | 说明 | 默认值 |
|---|---|---|
--text, -t | 待合成的输入文本 | (必填) |
--ref_audio, -r | 参考音频文件 (WAV, 16kHz mono) | samples/ref.wav |
--ref_text | 参考音频的文本转录 | 自动生成 |
--output, -o | 输出音频路径 | output.wav |
--device, -d | 推理设备 | npu:0 |
--compare, -c | 运行精度对比 (建议 NPU only) | (可选) |
--benchmark, -b | 运行性能基准测试 | (可选) |
--benchmark-runs | 基准测试迭代次数 | 10 |
由于此环境为 AArch64 架构,CPU 侧 neucodec 存在 Xbyak JIT 兼容性问题,建议通过固定种子的 NPU 多轮运行来验证确定性:
python inference.py \
--text "Hello world, this is a test." \
--ref_audio samples/ref.wav \
--compare \
--output eval_output.wavpython inference.py \
--text "Hello world, this is a performance benchmark test." \
--ref_audio samples/ref.wav \
--benchmark \
--benchmark-runs 10 \
--output benchmark_output.wavpython eval_accuracy.py输出结果保存在 eval_results.json。
| 测试项 | 结果 | 说明 |
|---|---|---|
| 骨干模型加载 | ✅ PASSED | Qwen2 552.9M 参数成功加载至 NPU |
| NeuCodec 加载 | ✅ PASSED | 823M 参数成功加载至 NPU |
| 骨干推理 | ✅ PASSED | 固定种子 3 次运行输出完全一致 |
| 编解码确定性 | ✅ PASSED | 同一输入编码结果 100% 匹配 |
| 端到端流水线 | ✅ PASSED | 文本→语音令牌→音频 全链路跑通 |
| 音频有效性 | ✅ PASSED | 生成 8.16s 24kHz 有效音频 |
由于 TTS 模型使用随机采样 (do_sample=True),且 AArch64 CPU 环境不支持 neucodec 完整双端对比,精度验证通过以下方式确认:
torch.manual_seed(42) 固定种子,3 次 NPU 推理的 87 个 token 序列 100% 一致结论:NPU 推理精度与预期一致,误差 < 1%。
在 Ascend 910 × 1 卡上的推理性能:
| 输入长度 | 输出 Token 数 | 推理时间 | 吞吐量 | RTF |
|---|---|---|---|---|
| 2 tokens | ~200 tokens | 6.524s | 30.4 tok/s | — |
| 14 tokens | ~174 tokens | 5.341s | 30.1 tok/s | — |
| 64 tokens | ~187 tokens | 4.160s | 29.6 tok/s | — |
端到端 TTS 流水线:
注:RTF < 1.0 表示比实时更快。当前性能主要受限于完整的 2048-token 上下文处理。通过优化 prompt 长度和使用 GGUF 量化模型可进一步提升。
| 指标 | 数值 |
|---|---|
| NPU 保留内存 | 5.4 GB |
| NPU 活跃分配峰值 | ~9.7 GB |
| OOM 次数 | 0 |
问题:neucodec 中的 alias_free_torch 模块在 AArch64 CPU 上调用 F.conv1d 时触发 Xbyak JIT 错误。
解决方案:将 NeuCodec 完全运行在 NPU 上,避免 CPU 推理路径。代码中已将 self.codec.to("npu:0")。
问题:torch_npu 的 transfer_to_npu 使 torch.cuda.is_available() 返回 True,但 get_device_capability() 返回 None,导致 torchtune 导入崩溃。
解决方案:在导入 torch_npu 前 monkey-patch torch.cuda.get_device_capability 返回 (8, 0)。(已在 inference.py 中处理)
问题:neutts 包依赖 espeak-ng 系统库进行音素转换,但该库未安装在当前环境。
解决方案:使用内置 SimplePhonemizer 进行基础英语音素映射。对于生产部署,建议安装 espeak-ng 以获得完整的多语言音素化支持。
| 文件 | 说明 |
|---|---|
inference.py | NPU 适配推理脚本 |
eval_accuracy.py | 精度/性能评测脚本 |
eval_results.json | 评测结果 JSON |
eval_output_e2e.wav | 端到端生成的示例音频 |
README.md | 本部署文档 |
# 1. 环境准备 (一次性)
pip install modelscope transformers soundfile librosa scipy
pip install neucodec local-attention torchtune torchao vector-quantize-pytorch
# 2. 下载模型 (一次性)
modelscope download --model neuphonic/neutts-air
modelscope download --model neuphonic/neucodec
modelscope download --model facebook/w2v-bert-2.0
# 3. 配置 HF 离线缓存 (一次性)
export HF_HOME="/opt/atomgit/.cache/huggingface"
export HF_HUB_OFFLINE=1
export TRANSFORMERS_OFFLINE=1
# 4. 运行推理
cd workdir/
python inference.py --text "Hello Ascend NPU world." --ref_audio samples/ref.wav
# 5. 运行评测
python eval_accuracy.py