Skip to content

Repository files navigation

kokoro-ggml

多语言 G2P(Grapheme-to-Phoneme)库 + Kokoro-82M 加速 TTS 引擎(ggml encoder + ncnn Vulkan 四段 decoder,无 ONNX Runtime 依赖),C++ 从零复刻 misaki(hexgrad/misaki)的 en/zh 前端,支持中英文混读。英文 OOD 词由运行时 espeak-ng 兜底。

整个引擎可编译为链接库 kokoro_ncnn.dll / kokoro_ncnn.lib,对外提供纯 C API:文本输入直接产出音频,decoder 走 ncnn Vulkan 四段加速管线(decoder 稳态 RTF ≈ 0.53,13 s 音频约 6.9 s;ggml encoder 经 AVX2 / 图缓存 / F0-N 并行优化后单句约 0.25 s,短句全链路 RTF ≈ 0.670.70;均受核显限频与后台 GPU 负载影响,实测 0.50.8 波动)。接口说明见 docs/kokoro_api.md

加速推理管线(ggml encoder + ncnn Vulkan 四段 decoder)

原版 kokoro-decoder.onnx(约 213 MB,CPU 实时性差)被拆成四段混合管线,GPU 承担重活;原 kokoro-encoder.onnx(107 MB,ORT)已移植为 ggml 图(models/encoder-ggml.bin,约 106 MB):

flowchart LR
    T["文本"] --> G["G2P 音素"] --> E["ggml · encoder<br/>encoder-ggml.bin"]
    E --> F["asr / F0 / N / style_dec"]
    F --> S1["Seg1 · C++ 内联<br/>lsin 正弦源+噪声"]
    S1 --> S2["Seg2 · ncnn Vulkan net-A<br/>STFT 激发"]
    S2 --> S3["Seg3 · C++ 内联<br/>where 相位回绕"]
    S3 --> S4["Seg4 · ncnn Vulkan net-B<br/>backbone + iSTFT"]
    S4 --> A["24 kHz 音频"]
Loading
执行器 模型 说明
Seg1 C++(lsin_runtime) —(lsin_graph 生成) F0 → 正弦源 / 噪声 / 清浊掩码
Seg2 ncnn Vulkan dec_A2.param/.bin 源 → STFT 实部/虚部
Seg3 C++(lsin_runtime) —(RunWhereCpu 相位 ±π 回绕
Seg4 ncnn Vulkan dec_B4.param/.bin backbone + iSTFT → 音频

关键点:两网全 fp32(fp16 舍入会使 Seg3 的 atan2 在 ±π 边界翻转 → Seg4 NaN);Vulkan shader 首次编译 7~10 s,已在 create 内置 warmup;稳态推理以 net-B(Seg4)为绝对大头(L=1040 约 6.2 s)。

G2P 运行流程图

flowchart TD
    IN["文本输入"] --> ROUTE["MixedG2P::convert 统一后端路由"]
    ROUTE --> D{"含中文?"}

    D -- "否:纯英文" --> EN["EnglishG2P · 纯英文路径"]
    D -- "是:含中文" --> ZH["ZHG2P · 含中文路径"]

    subgraph EN_LANE["EnglishG2P"]
        T1["Tokenize:标点/缩写/数字切分"]
        T2["Word() 特殊词→词典→NNP→词干<br/>Number() 数字→英文"]
        T3["subtokenize 窗口搜索<br/>失败 → espeak-ng 运行时兜底"]
        EN --> T1 --> T2 --> T3
    end

    subgraph ZH_LANE["ZHG2P"]
        Z1["预处理:数字/标点映射"]
        Z2["v1.0 → legacy_call(IPA 路径)<br/>v1.1 → ZHFrontend(注音符号)"]
        Z3["中文段:jieba+拼音+声调/儿化<br/>英文段 → EnglishG2P"]
        ZH --> Z1 --> Z2 --> Z3
    end

    T3 --> OUT["音素串"]
    Z3 --> OUT
Loading

构建与使用

依赖(submodule)

第三方源码依赖通过 git submodule 管理:

git submodule update --init   # 拉取 ncnn / cppjieba / ggml
路径 来源 说明
third_party/ncnn/ Tencent/ncnn @ 20250503 推理库源码;本地 Vulkan 编译产物在 build-vk-mt/(不入库,需自行编译)
third_party/ggml/ ggml-org/ggml(v0.9.9 附近) encoder 推理库源码;本地 CPU 编译产物在 build-cpu/(不入库,需自行编译)
third_party/cppjieba/ yanyiwu/cppjieba @ v5.6.7 中文分词头文件库(limonp 依赖头在 cppjieba/deps/limonp,随 --recursive 拉取)
third_party/espeak-ng/ 预编译运行时(DLL + 数据) 随仓库提交;缺失时 G2P 自动降级为纯词典兜底

ncnn 的 build-vk-mt/ 与 ggml 的 build-cpu/ 编译产物由本地编译生成(ggml 需 GGML_CPU_ALL_VARIANTS=OFF 或默认配置),构建脚本引用 third_party\ggml\build-cpu\src\Release\*.libthird_party\ncnn\build-vk-mt\src\Release\ncnn.lib

动态库(对外 API)

.\compile_kokoro_dll.bat     # 产物:kokoro_ncnn.dll / kokoro_ncnn.lib
# Python (ctypes) 直接合成:文本 → 24 kHz float32 音频
python scripts\test_dll.py

C / C++ 调用方链接 kokoro_ncnn.lib(需 /MT),API 与示例见 docs/kokoro_api.md

命令行工具

.\compile_g2p.bat            # g2p_cli.exe —— 项目自带 G2P(zh/en)

# G2P:文本 → 音素
.\g2p_cli.exe dict\zh\dict.bin "Hello world"      # → həlˈO wˈɜɹld

# 动态库端到端(ggml encoder + ncnn 四段管线):文本 → 24 kHz 音频
python scripts\test_dll.py

特征生成与验证(测试工作流)

# 1) 端到端回归:G2P + ggml encoder + ncnn 四段 decoder,与 ORT 参考对比(corr ≈ 0.98)
python scripts\test_dll.py

# 2) decoder-only RTF 基准(预热后稳态,L=128/256/512/1040)
python scripts\bench_decode.py

espeak-ng 依赖 third_party/espeak-ng/(DLL + 数据),缺失时自动降级为纯词典兜底。

验证

结果
拆分管线 vs ORT 原版(同特征) corr ≈ 0.98,无 NaN
稳态 RTF(Vulkan,fp32,L=1040) ≈ 0.51(13 s 音频约 6.6 s 推理);GPU 频率受核显电源/温度节流影响,波动 0.50~0.57
英文 G2P(vs misaki,200 句) words 99.2%(无空输出词)
中文 G2P(v1.0/v1.1,各 3 测试集) 100% 逐 token 一致
espeak-ng 兜底 与 misaki EspeakFallback 逐字节一致

About

inference kokoro TTS with ncnn Vulkan acceleration.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages