Segment boundaries are systematically late at speech_pad_ms=0 (onset P50 ≈ +40 ms with a heavy tail to +1.4 s, offset P50 ≈ +50 ms); the two ends need corrections in opposite directions, so speech_pad_ms cannot compensate

Author: LXP-NeverCreated Sep 18, 2026Updated Sep 18, 2026

Summary

When tagging keyword-spotting training data (multilingual headset recordings, 16 kHz), we measured get_speech_timestamps (non-streaming, ONNX) boundaries against an objective, annotation-free acoustic reference on 8,966 files. At the library-default-style setting speech_pad_ms=0:

boundary lag vs. objective acoustic boundary (P50) P90 max
onset +39 to +43 ms (98-99% of files positive) +130 to +140 ms +1036 to +1415 ms
offset +47 to +58 ms +79 to +94 ms

Both boundaries are late, but they need opposite corrections: recovering the onset requires extending the segment earlier (positive pad), while recovering the offset requires trimming the segment earlier (negative pad). speech_pad_ms moves both ends outwards symmetrically, so it can fix the onset only by making the offset error grow 1:1 (verified below: pad=50 ms reproduces a manual onset annotation within 4 samples while pushing the offset +49 ms further out).

Edit note (2026-09-18): the first version of this report defined the acoustic reference as the first/last envelope frame above floor+6 dB, which single-frame clicks contaminated (inflated onset P50 to ~+79 ms and produced a spurious heavy tail). All numbers above use the click-robust definition (first/last frame of a run of ≥3 consecutive frames, i.e. 15 ms, above floor+6 dB). Figures and the example audio are attached in a comment below.

Environment

  • silero-vad: torch.hub.load('snakers4/silero-vad', model='silero_vad', onnx=True), master branch cache (model file silero_vad.onnx)
  • Python 3.11, PyTorch 2.1.1+cu121 (CPU inference)
  • Params: threshold=0.5, window_size_samples=512, speech_pad_ms=0, other args at library defaults
  • Audio: 16 kHz mono (one channel extracted from multichannel headset recordings), preprocessed with a 100 Hz high-pass and peak normalization (standard VAD preprocessing; the bias persists without it)

Single-file evidence (manual ground truth available)

One zh command utterance ("上一曲", 1.85 s; mono extract attached in the comment below). Manual annotated onset = sample 7908; objective energy onset (click-robust) = 8160; energy offset = 21520.

threshold speech_pad_ms window detected onset onset vs. manual GT detected offset offset vs. energy offset
0.5 0 512 8704 +796 (+50 ms) 21504 −1 ms
0.5 30 512 8224 +316 (+20 ms) 21984 +29 ms
0.5 50 512 7904 −4 (≈ GT) 22304 +49 ms
0.3 0 512 8704 +796 (threshold does not move onset) 22016 +31 ms
0.2 0 512 8192 +284 22528 +63 ms
0.5 0 1024 8704 +796 (window size does not move onset) 21504 −1 ms
0.5 0 1536 8704 +796 21504 −1 ms

Observations:

  1. Lowering threshold or changing window_size_samples does not reliably recover the onset; only speech_pad_ms shifts it, and it shifts the offset outwards by the same amount (offset error grows from −1 ms to +49 ms as pad goes 0→50 ms).
  2. For reference, FireRedVAD (DFSMN, FireRedTeam/FireRedVAD) on the same file errs in the opposite direction at the onset (7040, −54 ms) while also over-extending the offset (24160, +164 ms), i.e. boundary placement is model-specific and worth improving on both sides.

Large-scale evidence (n = 8,966, annotation-free)

Methodology: per file we compute a 5 ms RMS envelope of the preprocessed signal and estimate the noise floor as the 30th percentile of frame dB levels. The acoustic onset/offset are the first/last frame of a run of ≥3 consecutive frames (15 ms) above floor+6 dB; the run-length requirement rejects single-frame clicks (without it, a −45 dB one-frame click at sample 3200 of the example file masquerades as the onset). This reference is conservative: on the manually annotated file above it yields 8160 vs. manual 7908, i.e. the proxy is itself ~16 ms later than a human annotator, so the reported onset lag is if anything underestimated.

Results (zh headset commands, two loudness classes):

class n onset lag P50 onset lag P90 onset lag max offset lag P50 offset lag P90
comfortable 300 +43 ms +140 ms +1036 ms +47 ms +79 ms
soft 8,666 +39 ms +130 ms +1415 ms +58 ms +94 ms

Onset lag is positive in 98-99% of files. The onset heavy tail (up to +1.4 s) corresponds to files where a weak initial syllable never raises the frame probability above threshold; examples available on request. (Detection recall itself is fine: only 5/8,671 soft files yielded no segment, so this report is not about misses.)

Minimal reproduction

python
import torch, soundfile as sf
model, utils = torch.hub.load('snakers4/silero-vad', model='silero_vad', onnx=True)
(get_speech_timestamps, _, _, _, _) = utils
wav, sr = sf.read("silero_issue_example_mono16k.wav", dtype="float32")  # attached in comment

for pad in (0, 30, 50):
    ts = get_speech_timestamps(wav, model, sampling_rate=sr,
                               threshold=0.5, window_size_samples=512,
                               speech_pad_ms=pad)
    print(pad, ts[0]["start"], ts[-1]["end"])
# 0  -> 8704 21504   (onset +50 ms vs manual GT 7908)
# 30 -> 8224 21984
# 50 -> 7904 22304   (onset ≈ GT, offset +49 ms late)

Questions for the maintainers

  1. Is the systematic lateness of both raw boundaries (onset P50 ~+40 ms, offset P50 ~+50 ms at pad=0) known and intended? The onset in particular appears to be emitted where frame probability crosses the threshold on soft consonant onsets, without back-tracing to the acoustic onset.
  2. Would you consider hysteresis-style back-tracing (extend segment start backwards while frame probability stays above a lower threshold, and trim the offset symmetrically), so that boundary placement no longer depends on speech_pad_ms, which can only move both ends outwards?
  3. For boundary-accurate tagging use cases (KWS/ASR data cutting, subtitle alignment), is there a recommended parameter set other than symmetric speech_pad_ms?

Why this matters

VAD timestamps are widely used to cut/label training data for KWS and ASR and for subtitle alignment. A systematic +40-50 ms shift trims initial consonants and appends decay tails to every cut segment, and because the two ends need opposite corrections, the documented compensation (speech_pad_ms) necessarily corrupts one end while fixing the other.