- teensy-vad-3 β scaled data, real-world hardened
teensy-vad-3 β scaled data, real-world hardened
The best model of the teensyvad family: the same 20,449-parameter architecture as v1 and v2, trained on 10Γ more and much harder data β and evaluated on human-labelled real recordings.
Headline: at its AMI-calibrated operating point this 87 KB student scores AMI F1 0.886 vs Silero's 0.714 (Silero's stock threshold misses 44 % of speech in real rooms), and beats WebRTC VAD on every metric β at 1/20th the size of the Silero model. On ranking quality (AUC, computed on raw probabilities for every system) Silero remains ahead (see the comparison below) β the honest split is: Silero ranks best; teensy-v3 operates best in rooms, per KB and per Β΅s.
| real-world benchmark | v1 | v2 | v3 | Silero (teacher) |
|---|---|---|---|---|
| TEN VAD public set β AUC | 0.848 | 0.868 | 0.873 | 0.952 |
| AMI SDM meetings β AUC | 0.835 | 0.848 | 0.861 | 0.894 |
| AMI SDM meetings β F1 (calibrated) | 0.887 | 0.880 | 0.886 | 0.714 |
(FlashVAD v0.1, for reference, publishes F1 0.889 / AUC 0.882 on the TEN set β threshold-tuned on that set, as is our 0.894 best-threshold number: parity within caveats, at 2.3Γ fewer parameters.)
Training (what changed vs v2)
- Speech: 8,000 utterances from LibriSpeech
train-clean-100(~30 h of mixtures, 10.7M teacher-labelled frames β 10Γ v2) - Noise, three families:
- ESC-50 environmental (as before, fold-disjoint)
- synthetic 7-talker babble β summed disjoint LibriSpeech speakers; the classic hard case for VAD (background conversations)
- real AMI room ambience β non-speech stretches of distant-mic meeting audio (chairs, keyboards, HVAC), taken only from the 3 meetings reserved for calibration (the 8 evaluation meetings were never seen)
- SNR β5 β¦ 20 dB (down from 0 dB floor)
- Labels: Silero teacher (as in v2), Β΅-law augmentation kept (G.711 round-trip shifts real-set numbers by < 0.5 %)
- Lazy context-window training (
LazyWindowsβ the full design matrix would be 17 GB; windows materialise per batch)
Quick Start
from teensyvad import OfflineVAD
# Standalone VAD β auto-downloads from the Hub (pip install huggingface_hub)
model = OfflineVAD("Teensy/teensy-vad-3")
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-3", model_file="teensy-v3-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.
Use as Part of an ASR Pipeline
from teensyvad import OfflineVAD
from teensyvad.audio import write_wav
vad = OfflineVAD("Teensy/teensy-vad-3")
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.
What's in this repo
| file | what |
|---|---|
teensy-v3.npz |
float32 model β default |
teensy-v3-qat.npz |
QAT int8 version (28 KB; int8 val F1 0.912) |
teensy-v3.onnx |
float32 ONNX export |
teensy-v3-int8.onnx |
dynamic int8 ONNX (22 KB) |
Architecture and the exact reimplementable feature spec are identical to v1's card: 8 kHz, 25/10 ms framing, 20 log-mel + Ξ with per-frame band-mean subtraction, 10-frame context, 400β48β24β1 MLP.
Domain threshold profiles (important)
Rankings transfer across domains; operating points do not. Best
threshold measured: ~0.45 close-mic/telephony, 0.10 distant-room,
0.85 synthetic-events. The .npz metadata therefore ships profiles:
{"profiles": {
"close_mic": {"thr_hi": 0.45, "thr_lo": 0.27}, // default (telephony)
"distant_room": {"thr_hi": 0.10, "thr_lo": 0.06}}} // AMI-calibrated
distant_room was calibrated on 3 held-out AMI meetings; the 8
evaluation meetings were never used for any tuning.
Limitations (honest)
- At distant-room operating points everyone's false-alarm rate is high on overlapped meeting speech (labels mark foreground speech only).
- English speech; no music in training (a known gap β music reads as "activity").
- 100 ms context is short: unvoiced fricatives in noise remain the hardest frames; a GRU/TCN would help (deliberately out of scope β this family stays a readable MLP).
- Β΅-law/PSTN robustness verified; packet-loss concealment not modelled.
Models in this repository (named variants)
All variants share the 10.7M-frame scaled training recipe of this card β float variants differ only in hidden-layer size (88/48, 164/88, 200/96); the QAT variant is the 20k net fine-tuned under int8 simulation:
| name | file | params | KB | role |
|---|---|---|---|---|
| teensy-v3 | teensy-v3.npz |
20,449 | 88 | the default β best AMI F1 of the family |
| teensy-v3-40k | teensy-v3-40k.npz |
39,609 | 162 | capacity step |
| teensy-v3-80k | teensy-v3-80k.npz |
80,373 | 321 | family accuracy champion (best TEN F1/AUC) |
| teensy-v3-100k | teensy-v3-100k.npz |
99,593 | 396 | capacity ceiling β saturating |
| teensy-v3-qat | teensy-v3-qat.npz |
20,449 | 29 | int8 QAT β smallest near-parity artifact |
ONNX exports (float32 + dynamic int8) are provided for the 20k model.
Accuracy & speed of every variant
Unlike the v1/v2 families (flat 20kβ100k on 1M frames), this family's
10.7M-frame training set lets capacity pay: TEN AUC rises 0.873 (20k)
β 0.877 (80k) before saturating at 100k. Full cross-family story
in BENCHMARKS.md (capacity.png).
Comparison vs Energy / WebRTC / Silero β and capacity scaling
Full protocol, charts and the complete 14-model table live in BENCHMARKS.md (same protocol for every system, human-labelled audio, AMI-dev-calibrated operating points, AUC on raw probabilities). Summary:
| teensy-v3 (20k) | teensy-v3-80k | Silero VAD | WebRTC VAD | Energy VAD | |
|---|---|---|---|---|---|
| params | 20,449 | 80,373 | 1,774,000 | ~6k (C) | β |
| TEN VAD set β F1 (best thr*) | 0.894 | 0.894 | 0.938 | n/a | β |
| TEN VAD set β AUC | 0.873 | 0.877 | 0.952 | n/a | 0.670 |
| AMI SDM β F1 (calibrated) | 0.886 | 0.882 | 0.714 | 0.842 | 0.592 |
| AMI SDM β AUC | 0.861 | 0.861 | 0.894 | 0.760 | 0.658 |
| Β΅s / 20 ms chunk | 63 | 64 | 89 | 2 | 7 |
* tuned on that set β like-for-like with FlashVAD's published F1 0.889 / AUC 0.882.
This family was trained at 20k/40k/80k/100k params on the same 10.7M
frames (teensy-v3-{40k,80k,100k}.npz): capacity pays here up to a
sweet spot at ~80k (TEN AUC 0.873 β 0.877) then saturates β while
the v1/v2 families (1M frames) are flat from 20k. Capacity scales only
with data. See capacity.png in BENCHMARKS.md.
License & data
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.
Space using Teensy/teensy-vad-3 1
Evaluation results
- frame F1 on teensyvad synthetic val (Silero-teacher labels)self-reported0.911
- frame AUC on teensyvad synthetic val (Silero-teacher labels)self-reported0.929
- frame ROC-AUC on TEN VAD public set (30 real recordings)self-reported0.873
- frame F1 on AMI SDM meetings (manual labels)self-reported0.886
- frame ROC-AUC on AMI SDM meetings (manual labels)self-reported0.861
