s2.cpp 项目背景与概述

1. 一个缺口:S2 Pro 语音质量很好,但只能在 Python 里跑

2025 年以来,基于”语义 token + 声学 codec”的文本转语音(TTS)模型迅速成熟。Fish Audio 推出的 S2 Pro 采用 Dual-AR(双自回归) 架构:一个大 Transformer 逐帧预测语义 token,一个小 Transformer 紧接着逐码本解码声学 token,再经神经音频 codec 还原成 44.1 kHz 波形。官方推理链路基于 PyTorch/HuggingFace,部署时要装 Python、torch、一堆 CUDA 库,体积大、启动慢,嵌入桌面应用和服务端都不方便。

社区开发者 rodrigomatta 发起的 s2.cpp 填的就是这个缺口:用纯 C++17、基于 ggml 张量库,把 S2 Pro 的完整推理链路——分词、Dual-AR 生成、codec 编解码、WAV 输出——全部重写一遍。构建完成后运行时完全不需要 Python,并支持 CPU、Vulkan、CUDA、Metal 四种后端。项目自我定位见 README.md:6:

Fish Audio’s S2 Pro Dual-AR text-to-speech model running locally via a pure C++/GGML inference engine with CPU, Vulkan, CUDA, and Metal GPU backends. No Python runtime required after build.

项目被明确标注为 ALPHA 实验性软件(README.md:3-4):接口可能变动、不承诺生产可用,但核心链路已经完整,且提供 CLI、HTTP 服务和 C ABI 三种使用方式。

2. 它在整个流水线中的位置

一次完整的 TTS 推理,s2.cpp 全部在进程内完成(README.md:22):

文本
 │  Qwen3 BPE 分词(tokenizer.json)
 ▼
 token 序列(含对话模板 / 参考音频占位)
 │  Slow-AR:36 层 Qwen3 风格 Transformer(4.13B 参数,持久 KV cache)
 ▼
 每帧 1 个语义 token + 隐状态向量
 │  Fast-AR:4 层小 Transformer(0.42B 参数,无 KV cache)
 ▼
 每帧 10 个码本 token(1 语义 + 9 残差 RVQ),码本大小 4096
 │  音频 codec:卷积编码器/解码器 + 残差向量量化
 ▼
 44.1 kHz 波形 → WAV / PCM(可流式分块输出)

三个核心组件各自独立、又共享同一个 GGUF 文件:

组件 角色 实现文件
Slow-AR 36 层大 Transformer,文本 → 语义 token,GQA + RoPE(1M) + QK norm s2_model.cpp
Fast-AR 4 层小 Transformer,每个语义步解码 10 个声学码本 s2_model.cpp
Audio Codec 卷积编解码器 + RVQ(10 × 4096),波形 ↔ 离散码 s2_codec.cpp

参数量合计约 4.56B(Slow-AR 4.13B + Fast-AR 0.42B),架构说明见 README.md:526-534。

3. 三种使用形态

s2.cpp 虽然是个推理引擎,但交付的形态不止一个命令行工具:

  1. CLI 可执行文件 s2:单次合成、声音克隆、流式写文件。参数解析见 main.cpp:158-226,例如:

    ./s2 --model s2-pro-q4_k_m.gguf --cuda 0 \
         --text "你好,世界" --output out.wav
    
  2. HTTP 服务:--server 启动,基于内嵌的 cpp-httplib,只暴露一个 POST /generate multipart 接口,支持一次性 WAV、流式 WAV、实时分块 PCM。服务实现见 s2_server.cpp;同时提供 OpenAPI 规范。

  3. 导出库(C ABI):s2_shared / s2_static 两个目标,通过 s2_export_api.h 暴露不抛异常的 C 接口(不透明指针 + Alloc/Release),仓库自带 Python(ctypes)、C#、Go 调用示例。

4. 模型文件与许可证

  • GGUF 权重不在仓库内,由社区从官方 checkpoint 转换,发布在 HuggingFace 的 rodrigomt/s2-pro-gguf,从 f16(9.9 GB)到 q2_k(2.6 GB)共 7 个量化档(README.md:32-40)。
  • 转换脚本 unified_export_gguf.py 是仓库里唯一与 Python 相关的部分,且只用于离线导出,运行时不参与。
  • 一个 GGUF 同时装下 Transformer 和 codec(README.md:42);量化时 codec 张量(c.*)保留 F16,只量化 AR 部分。
  • 许可证需要特别注意:权重遵循 Fish Audio Research License(Copyright © 39 AI, INC.),研究/非商业免费,商业使用需向 Fish Audio 另行授权;引擎源码作为衍生作品同样适用该许可证(README.md:571-584)。

5. 本分析的范围与组织

本分析基于 s2.cpp 仓库固定提交 2c33261(以 git submodule 形式钉在 s2cpp/ 目录),所有代码链接均指向该提交,发布时由 CI 重写为 GitHub 上的固定 blob URL。全文按”从整体到细节”的顺序组织:

章节 内容
02 整体架构与数据流 张量形状、双 AR 交接、码行偏移约定
03 代码结构与构建 目录布局、CMake、ggml 子模块与本地补丁
04 模型加载与 GGUF 元数据默认值、权重放置、多 buffer 切分
05 Slow-AR 计算图 eval_cached、GQA、KV cache、tied embedding
06 Fast-AR 与生成主循环 fast_decode、generate 主循环、RAS
07 采样器 top-k/top-p/温度的具体实现
08 音频编解码器 卷积 codec、RVQ、余弦 VQ、缓存图
09 语音克隆与声音档案 参考音频编码、.s2voice、对话模板
10 流水线与流式合成 stride/holdback/context、codec 自动选型
11 HTTP 服务 /generate、503 单并发、分块与分句
12 导出库 API C ABI、回调式流式、各语言示例

关键文件

文件 行数 职责
README.md 623 项目说明、模型选型、架构与限制
src/main.cpp 340 CLI 入口与参数解析
src/s2_model.cpp 1257 Slow-AR / Fast-AR 模型与计算图
src/s2_codec.cpp 1447 音频 codec 全部实现
src/s2_pipeline.cpp 1205 组装流水线、流式窗口解码
src/s2_generate.cpp 218 Dual-AR 生成主循环

This site uses Just the Docs, a documentation theme for Jekyll.