Downloads · 30 days
0
Teensy/teensy-vad-v4
teensy-vad-v4 is a voice activity detection model from Teensy. Use it for the voice activity detection task on the model card, and read the license before you ship it in a product. It is set up for teensyvad. The card lists the license as cc-by-nc-sa-4.0.
The fourth generation of the teensyvad family: the same readable 3-layer MLP, now trained on the full ~100 h of LibriSpeech train-clean-100 (all 28,539 utterances — 3.5× the v3 dataset, 37.9M teacher-labelled frames),…
Downloads · 30 days
0
Access
Public
Updated Aug 28, 2026
Repo size
3.9 MB
Likes
0
Public
Click a slice to open those files.
.onnx2.4 MB · 63%
From the Hugging Face model README
The fourth generation of the teensyvad family: the same readable 3-layer MLP, now trained on the full ~100 h of LibriSpeech train-clean-100 (all 28,539 utterances — 3.5× the v3 dataset, 37.9M teacher-labelled frames), with the complete 20k/40k/80k/100k capacity sweep.
This card is the home of the family; every named size variant lives in this repository.
from teensyvad import OfflineVAD
# Standalone VAD — auto-downloads from the Hub (pip install huggingface_hub)
model = OfflineVAD("Teensy/teensy-vad-v4")
result = model.segments("long_audio.wav")
# Returns speech segments: [[start_ms, end_ms], [start_ms, end_ms], ...]
print(result) # e.g. [[90, 5150]] — the fsmn-vad convention
Variant selection: OfflineVAD("Teensy/teensy-vad-v4", model_file="teensy-v4-80k.npz")
(see the variant table below). Local use without the hub: pass a
.npz path. teensyvad is pure numpy (single package dir in the
project repo) — the only dependency.
from teensyvad import OfflineVAD
from teensyvad.audio import write_wav
vad = OfflineVAD("Teensy/teensy-vad-v4")
segments = vad.segments("meeting_2hours.wav") # [[start_ms, end_ms], ...]
for i, (start_ms, end_ms) in enumerate(segments):
seg = vad.slice("meeting_2hours.wav", start_ms, end_ms) # float32 @ 8 kHz
write_wav(f"speech_{i}.wav", seg, 8000)
# text = my_asr.transcribe(f"speech_{i}.wav") # <- your ASR here
Streaming / telephony (Asterisk AudioSocket): from teensyvad import StreamingVAD — feed 20 ms PCM16LE frames, get speech_start /
speech_end events, vad.speech_seconds for talk time; a working
server ships as scripts/audiosocket_server.py in the project repo.
The v3 experiment showed capacity only pays when data scales with it: on 1M frames, 20k→100k params was flat; on 10.7M frames the sweet spot moved to ~80k. v4 completes the curve at 37.9M frames — and this time capacity keeps paying to the largest size tested:
| size | val F1 | val AUC | training frames |
|---|---|---|---|
| teensy-v4 (20k) | 0.9137 | 0.9338 | 37.9M |
| teensy-v4-40k | 0.9179 | 0.9398 | 37.9M |
| teensy-v4-80k | 0.9199 | 0.9417 | 37.9M |
| teensy-v4-100k | 0.9205 | 0.9420 | 37.9M |
| (reference: v3-80k) | (0.9165) | (0.9373) | (10.7M) |
Real-world results (TEN VAD public set + AMI SDM, human labels) are in the comparison section below; the shared protocol lives in BENCHMARKS.md.
| name | file | params | KB | role |
|---|---|---|---|---|
| teensy-v4 | teensy-v4.npz | 20,449 | 87 | the default |
| teensy-v4-qat | teensy-v4-qat.npz | 20,449 | 28 | int8 QAT — beats float v4 on TEN AUC |
| teensy-v4-40k | teensy-v4-40k.npz | 39,609 | 161 | capacity step |
| teensy-v4-40k-qat | teensy-v4-40k-qat.npz | 39,609 | 47 | int8 QAT |
| teensy-v4-80k | teensy-v4-80k.npz | 80,373 | 321 | real-world champion (TEN AUC 0.880) |
| teensy-v4-80k-qat | teensy-v4-80k-qat.npz | 80,373 | 88 | int8 QAT — best AMI AUC of the family (0.863) |
| teensy-v4-100k | teensy-v4-100k.npz | 99,593 | 396 | capacity ceiling |
| teensy-v4-100k-qat | teensy-v4-100k-qat.npz | 99,593 | 107 | int8 QAT |
train 37,936,863 windows)Shared protocol (human-labelled audio, AMI-dev-calibrated operating points, AUC on raw probabilities — full appendix: BENCHMARKS.md):
| v4 (20k) | v4-40k | v4-80k | v4-100k | v4-qat (int8) | v3-80k | Silero | WebRTC | Energy | |
|---|---|---|---|---|---|---|---|---|---|
| params | 20,449 | 39,609 | 80,373 | 99,593 | 20,449 | 80,373 | 1,774,000 | ~6k | — |
| TEN VAD set — F1 (best thr*) | 0.892 | 0.892 | 0.896 | 0.892 | 0.894 | 0.894 | 0.938 | n/a | — |
| TEN VAD set — AUC | 0.871 | 0.875 | 0.880 | 0.875 | 0.876 | 0.877 | 0.952 | n/a | 0.670 |
| AMI SDM — F1 (calibrated) | 0.884 | 0.883 | 0.880 | 0.882 | 0.884 | 0.882 | 0.714 | 0.842 | 0.592 |
| AMI SDM — AUC | 0.861 | 0.862 | 0.862 | 0.861 | 0.862 | 0.861 | 0.894 | 0.760 | 0.658 |
| µs / 20 ms chunk | 63 | 65 | 66 | 64 | 92 | 66 | 89 | 2 | 7 |
* tuned on that set — like-for-like with FlashVAD's published F1 0.889 / AUC 0.882: v4-80k essentially matches FlashVAD's AUC (0.880 vs 0.882) at 2.3× fewer parameters, and leads every prior teensy family on TEN AUC. The int8 QAT variant holds TEN AUC 0.876 in a 28 KB file — within 0.005 of the 80k champion at 1/11th the size (val F1 0.9145, matching float v4).

Code: MIT. Weights: CC BY-NC-SA 4.0 (ESC-50 CC BY-NC-SA 3.0 noise in training; LibriSpeech CC BY 4.0; AMI CC BY 4.0; Silero teacher MIT). Not for commercial deployment without replacing non-commercial training data.