主角是 SenseVoice。阿里达摩院的多语言 ASR 模型。234MB INT8 量化版。中英日粤通吃,还能识别笑声、咳嗽、BGM。配上 PUNC 标点模型,输出带标点的中文。
1. 微信一样的demo
做了一个demo,支持浏览器/服务端调用模型。
输入支持麦克和声音文件。
2. 流程图
声音 > 提取特征 >ASR模型 > 文字 > PUNC模型 > 文字(带标点), 其实如果只是用识别语音做提示词, 可以省去PUNC模型
3. ONNX 格式
项目中所用模型均为ONNX格式, 这是通用格式, 在js下使用。
4. 核心代码 5 行
// demo/3/server.ts
import * as ort from "onnxruntime-node"
const session = await ort.InferenceSession.create("./sensevoice.onnx", {
executionProviders: ["dml", "wasm"]
})
const out = await session.run({ x: tensor, x_length: ..., language: ..., text_norm: ... })
console.log(decodeGreedy(out["output"])) // 打印识别结果
onnxruntime-node 是 ONNX 模型的"执行器", 微软出品可以放心使用。
dml 是 DirectML,Windows 显卡的调度员。wasm 是兜底,没显卡也能跑。
5. 原理:声音怎么变文字
6. GPU 加速
服务端用 dml(DirectML)——Windows 显卡的"调度员"。onnxruntime-node 自动调,不用自己写 CUDA。
浏览器用 WebGPU——Chrome 113+ 的"新接口",直接调显卡。
wasm 兜底——没显卡跑字节码,CPU 也能跑。三层降级:dml → wasm → cpu。不用改代码。
7. 读音频
wav 是录音的"包裹",里面是波形 + 采样率 + 声道数。16kHz 单声道是 ASR 的"标准口粮",模型只认这个。
const wav = new WaveFile(buf) // 解码
if (wav.fmt.sampleRate !== 16000) wav.toSampleRate(16000) // 重采样
if (wav.fmt.numChannels !== 1) wav.toMono() // 转单声道
const audio = new Float32Array(wav.getSamples(true, Int16Array).map(s => s / 32768)) // 归一化
重采样 + 转 mono + 归一化,三步搞定。
8. 模型从哪来
|
模型
|
干什么
|
大小
|
魔搭上搜索
|
| :-- | :-- | :-- | :-- |
|
SenseVoice
|
语音转文字
|
230MB INT8
| xiaowangge/sherpa-onnx-sense-voice-small
(ModelScope)
|
|
PUNC
|
加标点
|
281MB INT8
| damo/punc_ct-transformer_zh-cn-common-vad_realtime-vocab272727-onnx |
两个 ONNX都可以在魔搭网下载。
INT8 量化版:32 位浮点砍 8 位整数,体积 1/4,速度翻倍。
9. 计划
ASR => 大模型 => 克隆声音
机器人
做到这里, 我在想后面做一个声音克隆, 接上大模型, 就可以人机对话了, 你们觉得怎么样?