Sprecherdiarisierung
Identifiziere, wer wann in einer Mehrsprecheraufnahme gesprochen hat. Zwei Diarisierungs-Engines sind verfügbar: eine zweistufige Pyannote-Pipeline (Segmentierung + aktivitätsbasierte Sprecherverkettung, dann Post-hoc-Embedding) und ein durchgängiges Sortformer-Modell (CoreML, Neural Engine).
Engines
Wähle die Engine mit --engine pyannote (Standard) oder --engine sortformer.
Pyannote (Standard)
Zweistufige Pipeline: Pyannote-Segmentierung verarbeitet überlappende Fenster mit aktivitätsbasierter Sprecherverkettung (Pearson-Korrelation in Überlappungsbereichen), um globale Sprecherlabels zu vergeben. Die Post-hoc-WeSpeaker-Embedding-Extraktion ermöglicht die Identifikation von Zielsprechern per Enrollment-Audio.
Sortformer (CoreML)
NVIDIAs durchgängiges neuronales Diarisierungsmodell. Sagt direkt Per-Frame-Sprecheraktivität für bis zu 4 Sprecher voraus, ohne separate Embedding- oder Clustering-Stufen. Läuft auf der Neural Engine über CoreML mit Streaming-Zustandspuffern (FIFO + Sprecher-Cache).
Sortformer erzeugt keine Sprechereinbettungen. Die Flags --target-speaker und --embedding-engine sind nur mit der Pyannote-Engine verfügbar.
Pyannote-Pipeline
Die Standard-Pipeline läuft in zwei Stufen:
Stufe 1: Segmentierung + Sprecherverkettung
Pyannote-segmentation-3.0 verarbeitet 10-Sekunden-Gleitfenster mit 50 % Überlappung. Ein Powerset-Decoder wandelt die 7-Klassen-Ausgabe in Per-Sprecher-Wahrscheinlichkeiten um (bis zu 3 lokale Sprecher pro Fenster). Benachbarte Fenster teilen sich eine 5-Sekunden-Überlappung — die Sprecheridentität wird über Fenster hinweg propagiert, indem die Pearson-Korrelation zwischen Wahrscheinlichkeitsspuren im Überlappungsbereich berechnet wird, mit gieriger exklusiver Zuordnung für konsistente globale Sprecher-IDs.
Stufe 2: Post-hoc-Embedding
Nach der Diarisierung extrahiert WeSpeaker ResNet34-LM ein 256-dimensionales Zentroid-Embedding pro Sprecher. Diese Embeddings ermöglichen die Zielsprecher-Extraktion (--target-speaker), steuern aber nicht die Sprecherzuordnung selbst.
CLI-Verwendung
# Einfache Diarisierung (pyannote, Standard)
.build/release/audio diarize meeting.wav
# Durchgängiger Sortformer (CoreML)
.build/release/audio diarize meeting.wav --engine sortformer
# RTTM-Ausgabeformat (für Auswertung)
.build/release/audio diarize meeting.wav --rttm
# JSON-Ausgabe
.build/release/audio diarize meeting.wav --json
Zielsprecher-Extraktion
Gib Enrollment-Audio eines bekannten Sprechers an, um nur dessen Segmente aus einer Aufnahme zu extrahieren. Die Pipeline berechnet das Sprecher-Embedding des Enrollment-Audios und findet das Cluster mit der höchsten Kosinusähnlichkeit.
# Segmente für einen bestimmten Sprecher extrahieren
.build/release/audio diarize meeting.wav --target-speaker enrollment.wav
DER-Scoring
Bewerte die Diarisierungsqualität durch Vergleich mit einer Referenz-RTTM-Datei. Die Pipeline berechnet die Diarization Error Rate (DER), die den Anteil der falsch zugeordneten Zeit misst.
# Gegen Referenz-RTTM scoren
.build/release/audio diarize meeting.wav --score-against reference.rttm
RTTM-Ausgabe
Das Flag --rttm erzeugt eine Rich-Transcription-Time-Marked-Ausgabe, ein Standardformat zur Diarisierungsauswertung. Jede Zeile folgt dem Format:
SPEAKER filename 1 start_time duration <NA> <NA> speaker_id <NA> <NA>
Optionen
| Option | Beschreibung |
|---|---|
--target-speaker | Enrollment-Audio für die Zielsprecher-Extraktion (nur pyannote) |
--embedding-engine | Sprecher-Embedding-Engine: mlx oder coreml (nur pyannote) |
--vad-filter | Vorfilterung mit Silero VAD (nur pyannote) |
--rttm | Ausgabe im RTTM-Format |
--json | JSON-Ausgabeformat |
--score-against | Referenz-RTTM-Datei für DER-Auswertung |
Diarisierung funktioniert am besten mit Aufnahmen, die klare Sprecherwechsel aufweisen. Stark überlappende Sprache kann die Genauigkeit verringern. Die Sprecherzahl wird automatisch bestimmt.
Modell-Downloads
Modelle werden beim ersten Gebrauch automatisch heruntergeladen:
| Komponente | Modell | Größe | HuggingFace |
|---|---|---|---|
| Segmentierung | Pyannote-Segmentation-3.0 | ~5,7 MB | aufklarer/Pyannote-Segmentation-MLX |
| Sprecher-Embedding | WeSpeaker-ResNet34-LM (MLX) | ~25 MB | aufklarer/WeSpeaker-ResNet34-LM-MLX |
| Sprecher-Embedding | WeSpeaker-ResNet34-LM (CoreML) | ~25 MB | aufklarer/WeSpeaker-ResNet34-LM-CoreML |
| Sortformer | Sortformer Diarization (CoreML) | ~240 MB | aufklarer/Sortformer-Diarization-CoreML |
Swift-API
import SpeechVAD
let pipeline = try await DiarizationPipeline.fromPretrained()
let result = pipeline.diarize(audio: samples, sampleRate: 16000)
for seg in result.segments {
print("Speaker \(seg.speakerId): [\(seg.startTime)s - \(seg.endTime)s]")
}
// Zielsprecher-Extraktion
let targetEmb = pipeline.embeddingModel.embed(audio: enrollmentAudio, sampleRate: 16000)
let segments = pipeline.extractSpeaker(
audio: meetingAudio, sampleRate: 16000,
targetEmbedding: targetEmb
)