teensy-vad-v4 β the 100-hour family
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.
Quick Start
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.
Use as Part of an ASR Pipeline
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.
Why 100 hours
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.
Models in this repository (named variants)
| 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 |
Training
- Speech: all 28,539 utterances of LibriSpeech train-clean-100
(~100 h of mixtures; 37,936,872 frames β every window verified from
the memmap at load:
train 37,936,863 windows) - Noise: ESC-50 + synthetic 7-talker babble + real AMI room ambience (calibration meetings only), SNR β5 β¦ 20 dB, G.711 Β΅-law augmentation
- Labels: Silero teacher (hard), memmap/float16 training plumbing (the design matrix would be 60 GB if materialised)
- Architecture identical to teensy-vad-1 β see its card for the exact reimplementable feature spec.
Comparison vs Silero / WebRTC / Energy β and prior families
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).
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-v4 1
Evaluation results
- frame F1 on teensyvad synthetic val (Silero-teacher labels)self-reported0.920
- frame AUC on teensyvad synthetic val (Silero-teacher labels)self-reported0.942
- frame ROC-AUC on TEN VAD public set (30 real recordings)self-reported0.880
- frame F1 on AMI SDM meetings (manual labels)self-reported0.880
- frame ROC-AUC on AMI SDM meetings (manual labels)self-reported0.862
