8000 GitHub - daleione/voicekit · GitHub
[go: up one dir, main page]

Skip to content
daleionePublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

voicekit

中文语音关键词检测(KWS)+ 一次性语音转写(ASR)+ 语音活动检测(VAD)引擎,打包成可独立发布的 Rust 库。 引擎只输出事件(识别到哪个关键词、转写出什么文本、什么时候在说话),"该做什么"由调用方决定 —— 可接入智能家居 API、游戏宏、IoT 网关、辅助功能工具等任意场景。

为什么选 voicekit

  • 中文优先,预训练模型开箱可用。 内置 WenetSpeech 10k 小时训练的 zipformer KWS 权重(~6 MB int8 量化版),clone 完立刻能识别任意中文关键词。拼音 token 表和 keywords_invoker.txt 开箱匹配,不用像通用 Whisper / Vosk 那样自行做汉化适配。

  • 三种能力自由拆装。 KWS(关键词触发)/ ASR(自由语音转写)/ VAD(语音活动检测)是三个独立 Cargo feature:智能家居只用 KWS,会议记录只用 ASR,"唤醒词 + 自由指令" 组合用 KWS+ASR+VAD。关掉的能力在编译期就消失,不留运行时开销。

  • 纯事件输出,永远不替你决定。 API 产出 KeywordEvent / SpeechSegment / RecognitionResult 就收工 —— 敲键盘、调 HTTP、发 MQTT、播 TTS 回复,全是你的业务代码。对比行业里常见的"语音库捆绑 enigo/autoit/PyAutoGUI",voicekit 只做识别,上层永远在你手里。

  • 跨平台 / 跨线程 / 跨语言的工程化封装。 cpal stream 关在专属 OS 线程,Send 安全,FFI 跨线程 free 不 UB(macOS CoreAudio 的历史坑已规避)。除 Rust crate 外同步产出 libvoicekit_ffi.{dylib,so,dll} + cbindgen 自动生成的 voicekit.h,Python / Node / Go / C++ 一致接入。

  • Rust 性能下限 + sherpa-onnx 工程上限。 无 Python runtime、无 GIL、无异步调度开销;音频回调立即入通道,模型推理在 worker 线程,回调路径从不阻塞 OS 音频线程。int8 量化权重 + cmake 原生编译的 sherpa-onnx,纯 CPU 环境持续监听不发热。

  • Clone 即跑,也已为独立发布做好准备。 必要资产(KWS 权重 + Silero VAD + tokens + 测试词条)全在 assets/ 下,cargo run --example recognize_loop 就能验证全链路。crates/voicekit/Cargo.toml 已通过 exclude 把大型 ONNX 从 crates.io 打包中剔除。

30 秒上手

KWS — 关键词 → 事件

use voicekit::KeywordDetector;

let mut det = KeywordDetector::from_model_dir("./assets/model/kws")?;
det.start(|ev| println!("matched: {} (score {:.2})", ev.keyword, ev.score))?;
std::thread::park();

ASR + VAD — 持续监听,每句话自动转写

use voicekit::{SpeechRecognizer, VoiceActivityDetector};

let asr = SpeechRecognizer::from_model_dir("./assets/model/asr")?;
let vad = VoiceActivityDetector::from_model_file("./assets/model/vad/silero_vad.onnx")?;

for utt in vad.utterances_from_mic()? {
    println!("{}", asr.transcribe(&utt.samples)?.text);
}

就这么多。utterances_from_mic 返回一个阻塞 Iterator,说话间隔 ≥0.5s 就切一句。Drop 掉或调 stopper().stop() 停止。

回调 vs channel

两种风格都行:

// 回调
det.start(|ev| handle(ev))?;

// channel(更适合 select! / recv_timeout / 主线程控制)
let rx = det.start_channel()?;
for ev in rx {
    handle(ev);
}

KWS + ASR 组合(唤醒词 + 自由指令)

use voicekit::{KeywordDetector, SpeechRecognizer, VoiceActivityDetector};

let mut kws = KeywordDetector::from_model_dir("./assets/model/kws")?;
let asr = SpeechRecognizer::from_model_dir("./assets/model/asr")?;
let vad = VoiceActivityDetector::from_model_file("./assets/model/vad/silero_vad.onnx")?;

// 示意:kws 命中后由你的业务逻辑把后续 VAD 段丢给 asr.transcribe(...)

完整方式由应用层协调(怎么共享一个麦克风流、怎么处理打断等都是产品决策);voicekit 只提供三个原语。

Cargo features

feature 默认 作用
kws ✅ 启用 KeywordDetector
asr ✅ 启用 SpeechRecognizer
vad ✅ 启用 VoiceActivityDetector
builtin-audio ✅ 启用 cpal 麦克风采集;关掉就只能用 push_samples
[dependencies]
# 全套(默认)
voicekit = "0.1"

# 只要 KWS + 麦克风
voicekit = { version = "0.1", default-features = false, features = ["kws", "builtin-audio"] }

# 只要 VAD 做分段,音频自己管
voicekit = { version = "0.1", default-features = false, features = ["vad"] }

目录结构

voicekit/
├── Cargo.toml / DESIGN.md / README.md / LICENSE
├── .cargo/config.toml                 # sherpa-onnx dylib 的 rpath
├── assets/
│   ├── model/
│   │   ├── kws/                       # 已 bundle,17 MB,KWS 开箱即用
│   │   │   ├── encoder/decoder/joiner-epoch-12-*.onnx (+ int8)
│   │   │   ├── tokens.txt
│   │   │   ├── keywords_invoker.txt / keywords_test.txt
│   │   │   └── README.md
│   │   ├── asr/                       # 空槽位,放你下载的 offline zipformer
│   │   │   └── README.md              # 下载指引(一条 curl 命令)
│   │   └── vad/                       # Silero VAD(2.2 MB,已 bundle)
│   │       └── silero_vad.onnx
│   └── skills_example.json            # game_macro 示例数据
└── crates/
    ├── voicekit/                      # 核心库
    │   └── examples/
    │       ├── smart_home.rs          # KWS → HTTP
    │       ├── game_macro.rs          # KWS → 键盘动作
    │       ├── recognize_once.rs      # ASR 3 秒单次录音
    │       └── recognize_loop.rs      # ASR + VAD 持续监听(<50 行)
    ├── voicekit-ffi/                  # C ABI(KWS only)
    │   ├── cbindgen.toml
    │   └── include/voicekit.h
    └── voicekit-cli/                  # KWS 调试 CLI

快速跑通

# 首次编译:sherpa-onnx 原生库经 cmake 拉起,约 3–5 分钟
cargo build --workspace --all-targets

# KWS CLI:对麦克风说 测试 / 小爱同学 / 开灯 / 关灯 / 打开空调 / 打开电视
./target/debug/voicekit ./assets/model/kws ./assets/model/kws/keywords_test.txt

# ASR 持续监听(需要先按 assets/model/asr/README.md 下载 offline 模型)
cargo run --example recognize_loop -p voicekit -- \
    ./assets/model/asr ./assets/model/vad/silero_vad.onnx

调参

  • KWS 误触 → KwsModelConfig.keywords_threshold 调高(默认 0.25,可到 0.35)
  • KWS 漏识别 → 调低到 0.15,或确认关键词 ≥ 4 音节且含特色音素(zh / sh / q / x 等)
  • KWS 双触发 → BehaviorConfig.min_trigger_interval_ms 调大(默认 200,智能家居建议 1000)
  • VAD 句子被切碎 → VadConfig.min_silence_duration 调大(默认 0.5s → 0.8s)
  • VAD 太晚出结果 → 调小到 0.3s
  • 采样率不是 16kHz → voicekit::Resampler 自己做(VAD 内部已自动处理)

C FFI(非 Rust 集成)

cargo build --release -p voicekit-ffi
# 产物:target/release/libvoicekit_ffi.{dylib,so,dll} + .a

头文件:crates/voicekit-ffi/include/voicekit.h

当前 FFI 仅暴露 KWS;ASR 的 C 接口因为底层 sherpa-onnx 可能抛 C++ 异常不易安全包装,需要时再加。

Python ctypes 例子

from ctypes import CDLL, CFUNCTYPE, Structure, c_char_p, c_uint64, c_float, c_void_p, POINTER

lib = CDLL("./target/release/libvoicekit_ffi.dylib")

class VkEvent(Structure):
    _fields_ = [("keyword", c_char_p), ("timestamp_ms", c_uint64), ("score", c_float)]
CB = CFUNCTYPE(None, POINTER(VkEvent), c_void_p)

def on_kw(ev, _): print("got:", ev.contents.keyword.decode("utf-8"))

lib.vk_detector_new.restype = c_void_p
det = lib.vk_detector_new(b"./assets/model/kws")
lib.vk_detector_start(c_void_p(det), CB(on_kw), None)
input("press enter to stop")
lib.vk_detector_stop(c_void_p(det)); lib.vk_detector_free(c_void_p(det))

新增 / 改关键词

编辑 assets/model/kws/keywords_test.txt(或 keywords_invoker.txt),每行:

<拼音 tokens 空格分隔> @<显示名>

拼音 token 必须来自 assets/model/kws/tokens.txt(227 个,带声调)。运行中改完 reload_keywords 即可热加载,不用重启。

许可证

  • voicekit 源代码:MIT,见 LICENSE
  • 打包的 KWS 模型:Apache 2.0,见 assets/model/kws/README.md
  • 打包的 Silero VAD:MIT(snakers4/silero-vad)
  • 你自己下载的 ASR 模型:license 自查

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0