Sprachaktivitätserkennung — Silero VAD

Zwei VAD-Modelle sind verfügbar: Pyannote-Segmentierung für Offline-Batch-Verarbeitung mit hoher Genauigkeit und Silero VAD für Streaming mit niedriger Latenz. Beide laufen vollständig auf dem Gerät.

Pyannote (Offline)

Pyannote segmentation-3.0 bietet hochgenaue VAD über eine PyanNet-Architektur. Sie verarbeitet Audio in 10-Sekunden-Gleitfenstern mit einem Schritt von 1 Sekunde, aggregiert dann überlappende Vorhersagen und wendet Hysterese-Glättung an.

Architektur

StufeDetails
SincNet40 gelernte Bandpass-Filter (insgesamt 80: 40 cos + 40 sin)
BiLSTM4 Schichten, hidden=128, bidirektional (256-dim-Ausgabe)
Linear2 lineare Schichten mit LeakyReLU (negative_slope=0,01)
Ausgabe7-Klassen-Softmax mit Hysterese-Nachbearbeitung

Modellgröße: ~1,49M Parameter, ~5,7 MB auf Disk.

Standard-Schwellenwerte

CLI-Verwendung

# Offline VAD
.build/release/speech vad recording.wav

# JSON output
.build/release/speech vad recording.wav --json

# Custom thresholds
.build/release/speech vad recording.wav --onset 0.6 --offset 0.3

Silero VAD (Streaming)

Silero VAD ist ein leichtgewichtiges Streaming-Modell, das 512-Sample-Chunks (32 ms bei 16 kHz) verarbeitet. Es läuft im Release-Modus mit 23-facher Echtzeit und eignet sich damit für Live-Audio-Anwendungen.

Backend-Aufteilung: MLX und CoreML nutzen jetzt beide Silero-v6.2.1-Exporte als Standard: aufklarer/Silero-VAD-v6.2.1-MLX und aufklarer/Silero-VAD-v6.2.1-CoreML. Beide behalten dieselbe 32-ms-Streaming-API bei.

Architektur

StufeDetails
STFTConv1d (1 auf 258 Kanäle), Reflection-Pad nur rechts von 64
Encoder4x Conv1d + ReLU
LSTMHidden-Size 128, Zustand wird über Chunks hinweg fortgeführt
DecoderConv1d (128 auf 1) auf LSTM-Hidden-State, Sigmoid-Ausgabe

Modellgröße: ~309K Parameter, ~1,2 MB auf Disk.

Streaming-Zustandsmaschine

Der Streaming-VAD-Prozessor verwendet eine 4-Zustands-Maschine, um saubere Sprachsegmente zu erzeugen:

  1. silence — keine Sprache erkannt
  2. pendingSpeech — Onset-Schwellenwert überschritten, warten auf minimale Sprachdauer
  3. speech — bestätigtes Sprachsegment läuft
  4. pendingSilence — Offset-Schwellenwert unterschritten, warten auf minimale Stillezeit

Standard-Schwellenwerte

CLI-Verwendung

# Streaming VAD
.build/release/speech vad-stream recording.wav

# Custom thresholds
.build/release/speech vad-stream recording.wav --onset 0.6 --offset 0.3

# Minimum durations
.build/release/speech vad-stream recording.wav --min-speech 0.5 --min-silence 0.2

# Choose engine
.build/release/speech vad-stream recording.wav --engine coreml

Optionen

OptionGilt fürBeschreibung
--onsetBeideWahrscheinlichkeitsschwelle für Sprachbeginn
--offsetBeideWahrscheinlichkeitsschwelle für Sprachende
--min-speechStreamingMinimale Sprachsegmentdauer (Sekunden)
--min-silenceStreamingMinimale Stillezeit zum Beenden des Segments (Sekunden)
--engineStreamingInferenz-Engine: mlx oder coreml
--jsonBeideJSON-Ausgabeformat
Wichtig

Für Echtzeit-Anwendungen verwende speech vad-stream mit Silero VAD. Das Pyannote-Modell benötigt die vollständige Audiodatei und eignet sich besser für Offline-Batch-Verarbeitung, bei der Genauigkeit Vorrang hat.

Pausen mit Smart Turn bestätigen

Ein VAD hört nur Stille und kann einen beendeten Satz nicht von einer Pause mitten im Satz unterscheiden. Schließe Smart Turn v3.2 an StreamingVADProcessor an — oder führe speech vad-stream --smart-turn aus —, um jede Pause zu bestätigen, bevor das Segment endet: Ein beendeter Satz schließt den Turn sofort ab, eine Pause mitten im Satz hört weiter zu.

Modell-Downloads

ModellBackendGrößeHuggingFace
Silero-VAD-v6.2.1MLX~1,2 MBaufklarer/Silero-VAD-v6.2.1-MLX
Silero-VAD-v6.2.1CoreML~1,2 MBaufklarer/Silero-VAD-v6.2.1-CoreML
Pyannote-Segmentation-3.0MLX~5,7 MBaufklarer/Pyannote-Segmentation-MLX

Swift-API

import SpeechVAD

// Offline VAD (Pyannote)
let pyannote = try await PyannoteVADModel.fromPretrained()
let segments = pyannote.detectSpeech(audio: samples, sampleRate: 16000)
for segment in segments {
    print("\(segment.startTime)s - \(segment.endTime)s")
}

// Streaming VAD (Silero)
let silero = try await SileroVADModel.fromPretrained()
let processor = StreamingVADProcessor(model: silero, config: .sileroDefault)
for event in processor.process(samples: audioBuffer) {
    switch event {
    case .speechStarted(let time):
        print("Speech started at \(time)s")
    case .speechEnded(let segment):
        print("Speech: \(segment.startTime)s - \(segment.endTime)s")
    }
}

Auch auf Android sowie auf Linux und Windows über Speech Core (ONNX Runtime) verfügbar.