Silero VAD 保姆级部署教程:2MB 企业级语音活动检测器,从 Python 到 ONNX 全平台落地
Silero VAD 是一个预训练的企业级语音活动检测器(Voice Activity Detector),由 Silero Team 开源,MIT 协议发布。它的 JIT 模型文件只有约 2MB,单 CPU 线程处理一段 30ms 音频耗时不到 1ms,在 8000Hz/16000Hz 采样率下都能工作,训练语料覆盖 6000+ 语言。在语音处理流水线里,VAD 是最前置的一环:把"有人说话"和"静音/噪音"分开,后面才能接 ASR、TTS、声纹识别、录音断句。本文按官方 README,从 pip 安装、Python API、torch.hub、ONNX 部署一路讲到 C++/Rust/Go 多语言落地。

一、项目介绍与适用场景
Silero VAD 不是一个大模型,而是一个极小的、专用的神经网络分类器:输入一段 30ms 的音频帧,输出"这一段里有没有人说话"的概率。它的设计目标是"在资源受限的边缘设备上跑得动、跑得准",因此模型压缩到 2MB、纯 CPU 推理、无需 GPU、无需联网。
官方列举的典型场景:
- IoT / 边缘 / 移动端:智能音箱、录音笔、监控设备上的语音活动检测;
- 数据清洗与准备:批量处理语音数据集,自动切掉静音段,为 ASR 训练做预处理;
- 电话与呼叫中心自动化:识别客户什么时候开口,触发语音机器人;
- 语音接口:在实时对话系统里判断"用户说完了没",触发 ASR。
与站点此前写过的语音项目(Whisper、FunASR、SenseVoice 这些 ASR 模型)相比,Silero VAD 不做"说了什么"的识别,只做"有没有人说"的判断——它是 ASR 的前置组件,不是替代品。在真实部署里,你会用 Silero VAD 先把长录音切成一小段一小段的语音块,再喂给 Whisper 转写,这样既能省显存、又能提高准确率。
为什么需要 VAD?直接把整段录音塞给 Whisper 行不行?技术上可以,但有三个问题:第一,Whisper 一次处理的音频长度有限(30 秒窗口),长录音要手动分段;第二,静音段也会消耗算力,白白浪费;第三,ASR 模型对连续静音段会产生幻觉(把静音"脑补"成文字)。VAD 就是解决这三个问题的标准组件:它先扫一遍音频,标出所有"有人说话"的区间,然后 ASR 只处理这些区间。这个"VAD 前置 + ASR 后置"的流水线是工业级语音系统的标配,从呼叫中心到智能音箱都这么搭。
Silero VAD 相比传统 VAD(如 WebRTC VAD)的优势:WebRTC VAD 是基于信号处理的老算法,对音乐、多人说话、背景噪音敏感;Silero 是神经网络模型,训练数据覆盖 6000+ 语言,对各种口音、噪音、音质都更鲁棒。代价是比 WebRTC VAD 稍慢(但 2MB 模型 <1ms/帧 的速度对绝大多数场景也够用了)。
二、核心功能逐条拆解
- 极致轻量:JIT 模型约 2MB,不依赖 GPU,纯 CPU 推理。
- 极快速度:单 CPU 线程处理 30ms 音频块 < 1ms;ONNX 在某些条件下能快 4-5 倍。
- 高精度:官方在 Quality Metrics Wiki 上给出了与 WebRTC VAD、Coqui 等方案的对比,准确率领先。
- 双采样率支持:8000Hz(电话音质)与 16000Hz(宽带音质)都支持。
- 多语言鲁棒:训练语料覆盖 6000+ 语言,对各种背景噪音、各种音质都能适应。
- 多运行时:PyTorch JIT、ONNX Runtime、ONNX、ExecuTorch、OpenVINO、tinygrad 全支持。
- 多语言绑定:官方 examples 提供 C++、Rust、Go、Java、C#、Python 等语言示例。
- 浏览器端可用:通过 ONNX Runtime Web 在浏览器里跑(社区项目 ricky0123/vad)。
- 无条款束缚:MIT 协议,无遥测、无 Key、无注册、无内置过期、无厂商锁定。
三、全套官方链接
| 类型 | 链接 |
|---|---|
| GitHub 仓库 | https://github.com/snakers4/silero-vad |
| 官方文档 | https://github.com/snakers4/silero-vad/wiki |
| 官方 Demo | https://colab.research.google.com/github/snakers4/silero-vad/blob/master/silero-vad.ipynb |
| License | MIT |
四、硬件与环境前置要求
官方 README 的 Dependencies 小节明确:
- 系统:x86-64(ONNX Runtime 路线可跑其他架构);
- Python:3.8+;
- 内存:1GB+ RAM;
- CPU:现代 CPU,支持 AVX、AVX2、AVX-512 或 AMX 指令集;
- 必装依赖:
torch>=1.12.0; - 可选 extras:
silero-vad[audio]:装torchaudio>=0.12.0,<2.10+ Python 3.9+ 的torchcodec,用于read_audio/save_audio;silero-vad[codec]:只装torchcodec,完全不依赖 torchaudio;silero-vad[onnx-cpu]:装onnxruntime>=1.16.1+numpy,走 ONNX CPU 推理;silero-vad[onnx-gpu]:装onnxruntime-gpu>=1.16.1,走 ONNX GPU;silero-vad[all]:全部装上。
补充:如果自己用其他库(如 soundfile、librosa)读音频,直接传一个一维 float32 的 torch.Tensor 给 get_speech_timestamps 即可,不需要装任何 extras。torchcodec 需要系统装 FFmpeg 4-9;torchaudio 后端需要 FFmpeg(conda install -c conda-forge 'ffmpeg<7')或 sox(apt-get install sox)或 soundfile(pip install soundfile)。
五、多平台部署步骤
5.1 pip 安装(官方 Fast start)
第 1 步:安装(官方原文):
pip install silero-vad[audio]
如果你已经自己加载音频,不需要 read_audio 辅助函数,直接:
pip install silero-vad
第 2 步:最简 Python 用法(官方示例原文):
from silero_vad import load_silero_vad, read_audio, get_speech_timestamps
model = load_silero_vad()
wav = read_audio('path_to_audio_file')
speech_timestamps = get_speech_timestamps(
wav,
model,
return_seconds=True, # Return speech timestamps in seconds (default is samples)
)
逐段解释:load_silero_vad() 加载 JIT 模型(首次调用会自动下载约 2MB 模型文件);read_audio() 读音频文件(内部走 torchaudio 或 torchcodec,自动重采样到 16000Hz);get_speech_timestamps() 遍历整个音频,返回一段段语音的起止时间戳,return_seconds=True 表示用秒表示,默认用采样点数表示。
输出 speech_timestamps 是一个 list,每个元素形如 {'start': 0.0, 'end': 3.45},即这段语音从第 0 秒开始到第 3.45 秒结束。
5.2 torch.hub 方式(官方)
import torch
torch.set_num_threads(1)
model, utils = torch.hub.load(repo_or_dir='snakers4/silero-vad', model='silero_vad')
(get_speech_timestamps, _, read_audio, _, _) = utils
wav = read_audio('path_to_audio_file')
speech_timestamps = get_speech_timestamps(
wav,
model,
return_seconds=True,
)
逐段解释:torch.hub.load 直接从 GitHub 拉模型;utils 是一个包含多个工具函数的元组,第一个就是 get_speech_timestamps。torch.set_num_threads(1) 限制单线程,官方推荐的默认配置——VAD 模型太小,多线程反而 overhead。
5.3 ONNX Runtime 部署(官方 onnx-cpu extras)
pip install silero-vad[onnx-cpu]
ONNX 路线的好处是不依赖 PyTorch 运行时,包体积更小、启动更快,适合嵌入式、服务器上的轻量部署。官方 README 提示:纯 ONNX 路线下,你需要自己实现 I/O(即自己用 soundfile 读 wav),并把现有 wrapper / examples / 后处理改成你需要的形式。
具体做法:
import onnxruntime as ort
import numpy as np
# 加载 ONNX 模型
session = ort.InferenceSession("silero_vad.onnx", providers=["CPUExecutionProvider"])
# 推理单帧(30ms 音频,16kHz)
input_name = session.get_inputs()[0].name
outputs = session.run(None, {
input_name: audio_chunk_16k_numpy, # shape: (480,) float32
"state": np.zeros((2, 1, 128), dtype=np.float32),
"sr": np.array([16000], dtype=np.int64)
})
speech_prob = outputs[0][0][0]
ONNX 路线的典型用法是把 Silero VAD 嵌入到 C++/Rust/Go 服务里——这些语言没有 PyTorch 运行时,但都有 ONNX Runtime 绑定。官方 examples 目录里的 C++/Rust/Go 示例就是这么做的。
5.4 C++ / Rust / Go / Java 部署(官方 examples)
官方仓库 examples/ 目录下提供了多语言示例:
- C++:
examples/cpp - Rust:
examples/rust-example、examples/rust-wav-processing-with-wavekat-vad - Go:
examples/go - Java:
examples/java-example - C#:
examples/csharp
这些示例都基于 ONNX Runtime 加载模型,适合把 VAD 嵌入到非 Python 项目里。官方还提供 OpenVINO 转换指南(examples/openvino)和 ExecuTorch 的 C++ 示例(pytorch/executorch 官方仓库)。
六、配置文件全部参数解释
Silero VAD 无配置文件,参数全部体现在 get_speech_timestamps() 函数上。按官方 README 与 Wiki 整理:
| 参数 | 作用 | 可选值 | 默认值 | 配置示例 | 改错后果 |
|---|---|---|---|---|---|
return_seconds |
返回值用秒还是采样点 | True/False | False | return_seconds=True |
不设则返回采样点数,需自己除以采样率换算 |
threshold |
判定为"有语音"的概率阈值 | 0.0–1.0 | 0.5 | threshold=0.5 |
过高漏检、过低误报 |
min_speech_duration_ms |
最短语音段长度 | 整数 ms | 250 | min_speech_duration_ms=250 |
太短会切碎正常停顿 |
min_silence_duration_ms |
最短静音段长度 | 整数 ms | 100 | min_silence_duration_ms=100 |
影响合并相邻语音段 |
speech_pad_ms |
语音段前后补边 | 整数 ms | 30 | speech_pad_ms=30 |
防止把语音头尾切掉 |
(以上参数在官方 Wiki "Examples and Dependencies" 与源码 get_speech_timestamps 中定义,官方 README 未逐字列出全部,此处按官方默认行为如实标注。)
调优经验:threshold 是最敏感的参数。默认 0.5 适合大多数场景;如果你的音频背景噪音大,模型容易把噪音误判成语音,把 threshold 提到 0.6-0.7;如果你的音频很干净但有轻声说话被漏掉,把 threshold 降到 0.3-0.4。min_speech_duration_ms 默认 250ms,意味着短于 250ms 的语音段会被忽略——这对过滤咳嗽、咔哒声有用,但如果你要识别很短的词(比如"喂"),可以降到 100ms。min_silence_duration_ms 默认 100ms,决定两段语音之间隔多久才算"真的说完了",电话场景建议调到 300-500ms,避免一句话中间的停顿被切成两段。
七、启动、后台常驻与开机自启
Silero VAD 是库,不是服务,没有"启动"概念。把它嵌入到你自己的 Python 服务里:
# vad_server.py
from fastapi import FastAPI, UploadFile
from silero_vad import load_silero_vad, get_speech_timestamps
import soundfile as sf, io
app = FastAPI()
model = load_silero_vad()
@app.post("/detect")
async def detect(file: UploadFile):
wav, sr = sf.read(io.BytesIO(await file.read()), dtype='float32')
import torch
timestamps = get_speech_timestamps(torch.from_numpy(wav), model, return_seconds=True)
return {"speech_segments": timestamps}
启动:
pip install fastapi uvicorn python-multipart soundfile
uvicorn vad_server:app --host 0.0.0.0 --port 50022
systemd unit:
[Unit]
Description=Silero VAD HTTP Service
After=network.target
[Service]
User=your_user
WorkingDirectory=/your/path
ExecStart=/usr/bin/uvicorn vad_server:app --host 0.0.0.0 --port 50022
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now silero-vad-server
修改端口:改 --port 50022。
八、功能实操教程
第 1 步:装好 pip install silero-vad[audio],准备一个 16kHz 单声道 wav 文件 test.wav。
第 2 步:跑最简检测:
from silero_vad import load_silero_vad, read_audio, get_speech_timestamps
model = load_silero_vad()
wav = read_audio('test.wav')
speech_ts = get_speech_timestamps(wav, model, return_seconds=True)
print(speech_ts)
预期输出形如:
[{'start': 0.5, 'end': 3.2}, {'start': 4.0, 'end': 8.7}]
第 3 步:把语音段切出来。官方配合 save_audio:
from silero_vad import save_audio
for i, ts in enumerate(speech_ts):
save_audio(f'segment_{i}.wav', wav[ts['start']:ts['end']], 16000)
当前目录会出现 segment_0.wav、segment_1.wav,每段都是单独的语音块。
第 4 步:与 Whisper 对接(真实流水线):用 Silero VAD 把长录音切成段,再逐段喂给 faster-whisper,最后把时间戳拼起来。这是 ASR 工程里最常见的优化:既避免 Whisper 一次处理太长的音频,又能跳过静音段省算力。完整代码:
from silero_vad import load_silero_vad, read_audio, get_speech_timestamps
from faster_whisper import WhisperModel
import torch
# 加载 VAD
vad_model = load_silero_vad()
wav = read_audio('long_interview.wav')
speech_ts = get_speech_timestamps(wav, vad_model, return_seconds=True)
# 加载 Whisper(只处理语音段)
asr_model = WhisperModel("small", device="cuda", compute_type="float16")
results = []
for i, ts in enumerate(speech_ts):
start, end = ts['start'], ts['end']
segment = wav[int(start*16000):int(end*16000)]
segments, _ = asr_model.transcribe(segment, language="zh")
for seg in segments:
results.append({
"start": start + seg.start,
"end": start + seg.end,
"text": seg.text
})
for r in results:
print(f"[{r['start']:.2f}s - {r['end']:.2f}s] {r['text']}")
逐段解释:先用 VAD 标出所有语音区间;然后遍历每个区间,把对应波形切片喂给 faster-whisper;最后把 Whisper 返回的相对时间戳加上区间起始时间,拼成全局时间轴。这个流水线比直接给 Whisper 整段录音更快、更准、更省显存。
第 5 步:实时流式检测(在麦克风流里逐块喂):
import torch
model = load_silero_vad()
# 假设你从麦克风流里每次拿到 30ms 的 16kHz 单声道 PCM 数据
# chunk_16k 是一个一维 float32 tensor,长度 = 16000 * 0.03 = 480
speech_prob = model(torch.from_numpy(audio_chunk_16k), 16000).item()
if speech_prob > 0.5:
print("有人说话,probability =", speech_prob)
else:
print("静音/噪音")
(官方 examples 里有完整的流式处理示例。)实时场景下,这个判断结果可以直接触发:开始录音、停止录音、唤醒词检测、ASR 开始转写。
九、全套报错故障排查
-
报错:
OSError: FFmpeg not found。 原因分析:torchaudio/torchcodec 需要 FFmpeg 后端。 分步解决方案:conda install -c conda-forge 'ffmpeg<7',或apt-get install ffmpeg。 -
报错:
AssertionError: You must install torch或No module named torch。 原因分析:未装 PyTorch。 分步解决方案:pip install torch torchaudio,或直接pip install silero-vad[audio]让它自动装。 -
报错:模型文件下载失败。 原因分析:首次调用
load_silero_vad()要从 GitHub 下载约 2MB JIT 模型,网络不通。 分步解决方案:手动从 GitHub 仓库src/silero_vad/data/下载silero_vad.jit放到对应目录;或用torch.hub.load方式并设置trust_repo=True。 -
报错:检测结果全是"有语音"或全是"静音"。 原因分析:音频采样率不对(不是 8000/16000Hz),或音量极小。 分步解决方案:先用 ffmpeg 重采样到 16000Hz 单声道:
ffmpeg -i input.wav -ar 16000 -ac 1 output.wav;或把threshold调到 0.3-0.6 之间试试。 -
报错:
read_audio对 mp3 文件失败。 原因分析:torchaudio 后端不支持 mp3,需要 torchcodec。 分步解决方案:pip install silero-vad[audio]确保 torchcodec 装好,或先用 ffmpeg 转 wav。 -
报错:ONNX 路线下
import onnxruntime失败。 原因分析:装了silero-vad但没装onnx-cpuextras。 分步解决方案:pip install silero-vad[onnx-cpu]。 -
报错:模型加载很慢,或第一次调用
load_silero_vad()卡住。 原因分析:首次调用要从 GitHub 下载约 2MB 的 JIT 模型,国内网络可能慢。 分步解决方案:先手动wget https://github.com/snakers4/silero-vad/raw/master/src/silero_vad/data/silero_vad.jit下载模型文件,放到src/silero_vad/data/目录下;或设置TORCH_HOME环境变量指向缓存目录。 -
报错:检测结果时间戳错位,语音段比实际说话早/晚几百毫秒。 原因分析:音频采样率不是 16000Hz,read_audio 重采样出了误差。 分步解决方案:先用 ffmpeg 显式重采样到 16000Hz 单声道:
ffmpeg -i input.wav -ar 16000 -ac 1 output.wav,再用read_audio('output.wav')。
十、升级、回滚与卸载
升级:pip install -U silero-vad。官方 Wiki "Version history and Available Models" 记录了各版本模型差异,升级前可以看一眼是否需要换模型文件。Silero VAD 的模型迭代比较克制,JIT 模型文件从 v4 到 v5 大小变化不大,通常不需要重新下载。
备份建议:Silero VAD 无本地状态,备份自己写的处理脚本即可。如果你用的是 ONNX 路线,记得把 silero_vad.onnx 文件单独备份,下次部署不用重新下载。
回滚:pip install silero-vad==<旧版本号>。
卸载:pip uninstall silero-vad;systemd 方式 sudo systemctl disable --now silero-vad-server 并删 unit 文件;ONNX 路线记得删模型文件。
十一、商用许可与合规风险提示
MIT 协议,允许商用、修改、分发,只需保留版权声明。官方 README 明确强调 "No Strings Attached"——无遥测、无 Key、无注册、无内置过期、无厂商锁定。模型本身基于公开数据集训练,无单独的模型权重限制。这是语音类开源项目里少见的"完全无束缚"协议,可以放心用于商业产品。
参考链接
- GitHub 仓库:https://github.com/snakers4/silero-vad
- Wiki 文档:https://github.com/snakers4/silero-vad/wiki
- Colab Demo:https://colab.research.google.com/github/snakers4/silero-vad/blob/master/silero-vad.ipynb
- PyPI:https://pypi.org/project/silero-vad/