Loading...

文章背景图

Silero VAD 保姆级部署教程:2MB 企业级语音活动检测器,从 Python 到 ONNX 全平台落地

2026-10-30
0
- 字
- 分钟
|

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

一、项目介绍与适用场景

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/帧 的速度对绝大多数场景也够用了)。

二、核心功能逐条拆解

  1. 极致轻量:JIT 模型约 2MB,不依赖 GPU,纯 CPU 推理。
  2. 极快速度:单 CPU 线程处理 30ms 音频块 < 1ms;ONNX 在某些条件下能快 4-5 倍。
  3. 高精度:官方在 Quality Metrics Wiki 上给出了与 WebRTC VAD、Coqui 等方案的对比,准确率领先。
  4. 双采样率支持:8000Hz(电话音质)与 16000Hz(宽带音质)都支持。
  5. 多语言鲁棒:训练语料覆盖 6000+ 语言,对各种背景噪音、各种音质都能适应。
  6. 多运行时:PyTorch JIT、ONNX Runtime、ONNX、ExecuTorch、OpenVINO、tinygrad 全支持。
  7. 多语言绑定:官方 examples 提供 C++、Rust、Go、Java、C#、Python 等语言示例。
  8. 浏览器端可用:通过 ONNX Runtime Web 在浏览器里跑(社区项目 ricky0123/vad)。
  9. 无条款束缚: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 开始转写。

九、全套报错故障排查

  1. 报错:OSError: FFmpeg not found。 原因分析:torchaudio/torchcodec 需要 FFmpeg 后端。 分步解决方案:conda install -c conda-forge 'ffmpeg<7',或 apt-get install ffmpeg。

  2. 报错:AssertionError: You must install torch 或 No module named torch。 原因分析:未装 PyTorch。 分步解决方案:pip install torch torchaudio,或直接 pip install silero-vad[audio] 让它自动装。

  3. 报错:模型文件下载失败。 原因分析:首次调用 load_silero_vad() 要从 GitHub 下载约 2MB JIT 模型,网络不通。 分步解决方案:手动从 GitHub 仓库 src/silero_vad/data/ 下载 silero_vad.jit 放到对应目录;或用 torch.hub.load 方式并设置 trust_repo=True。

  4. 报错:检测结果全是"有语音"或全是"静音"。 原因分析:音频采样率不对(不是 8000/16000Hz),或音量极小。 分步解决方案:先用 ffmpeg 重采样到 16000Hz 单声道:ffmpeg -i input.wav -ar 16000 -ac 1 output.wav;或把 threshold 调到 0.3-0.6 之间试试。

  5. 报错:read_audio 对 mp3 文件失败。 原因分析:torchaudio 后端不支持 mp3,需要 torchcodec。 分步解决方案:pip install silero-vad[audio] 确保 torchcodec 装好,或先用 ffmpeg 转 wav。

  6. 报错:ONNX 路线下 import onnxruntime 失败。 原因分析:装了 silero-vad 但没装 onnx-cpu extras。 分步解决方案:pip install silero-vad[onnx-cpu]。

  7. 报错:模型加载很慢,或第一次调用 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 环境变量指向缓存目录。

  8. 报错:检测结果时间戳错位,语音段比实际说话早/晚几百毫秒。 原因分析:音频采样率不是 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/
评论交流

文章目录