Traduzione automatica · Originale inglese
Diarizzazione dei parlanti
Identificare chi ha parlato quando in una registrazione multi-altoparlante. Quattro motori sono disponibili: leggero Pyannote (il CLI predefinito), full-pipeline Community-1 (CoreML + nativo PLDA/VBx), streaming Sortformer (CoreML, Neural Engine), e Nemotron 3 (CoreML INT8 o MLX INT8).
Motori
Selezionare il motore con --engine pyannote (default), --engine community1, --engine sortformer, or --engine nemotron3
Pyannote (default)
Condotto a due stadi: Pyannote processi di segmentazione sovrapposizione di finestre con catena di altoparlanti basata su attività (raffronto tra le zone sovrapposte) per assegnare etichette di altoparlante globali. WeSpeaker l'estrazione di embedding consente l'identificazione dell'altoparlante di destinazione tramite l'audio di registrazione.
Community-1 ( CoreML + VBx nativo)
Il pieno Pyannote Community-1 fascio CoreML: 10-secondo PyanNet segmentazione finestre avanzare ogni secondo, mascherato WeSpeaker embeddings feed centroid AHC e un 256→128 Trasformazione PLDA, poi nativo Swift VBx e l'assegnazione limitata producono cluster globali. 256centroide dimensionale per diffusore rilevato e supporta i limiti esatti, minimi o massimi del conteggio dell'altoparlante.
Ordinatore ( CoreML)
NVIDIA modello di diarizzazione neurale end-to-end. Predice direttamente l'attività di diffusore per frame per un massimo di 4 altoparlanti senza fasi di inserimento o clustering separate. Corre su Neural Engine tramite CoreML con buffer di stato in streaming (FIFO + buffer di altoparlante).
Per audio dal vivo, SortformerStreamingSession corre .streaming Sortformer modello incrementale con 16 kHz mono PCM buffer di qualsiasi dimensione. Una volta il suo 560 ms lookahead è disponibile, avanza in 480 ms passi audio; una serie M di cinque file Neural Engine pilota misurato 12.4 latenza mediana per 500 Le etichette di altoparlante seguono la Cache di Speaker dell'Ordine di arrivo invece di ri-cluster ogni finestra, e ogni spinta restituisce un'istantanea a flusso intero. finish() Nella prova di equivalenza con il modello, i segmenti finali corrispondono a tutto il buffer .streaming diarizzazione all'interno di circa un telaio 80 ms.
Nemotron 3 ( CoreML o MLX)
NVIDIA Nemotron 3 predizioni 10 ms attività di oratore fino a otto altoparlanti anonimi. INT8 esportazione download automaticamente da CoreML o MLX. Il backend CLI predefinito è CoreML; scegliere MLX con --nemotron3-backend mlx. Entrambi supportano un fascio locale attraverso --nemotron3-directory.
Su un interno 132-registrare set diarizzazione (12.82 ore, 0.25 s collar), il spedito Nemotron 3 MLX e CoreML runtime segnati 10.98% e 11.20% in piscina DER, rispettivamente, senza guasti. Su 48 Incontri inglesi, hanno segnato 10.31% e 10.24%. Vedi il comparazione e limiti di valutazione per lingua.
Il --target-speaker e --embedding-engine le bandiere sono disponibili solo con il default Pyannote motore. Community-1 restituisce cluster centroids attraverso il suo Swift API; Sortformer e Nemotron 3 non producono embeddings di diffusori.
Per i risultati misurati attraverso i sistemi di diarizzazione e otto lingue, segnati con un righello, vedere i benchmark di diarization speaker
Pubblicato CALLHOME
Di seguito è la linea di base anonime grezzo pubblicata da NVIDIA per il diar_streaming_sortformer_4spk-v2Si tratta di un riferimento esterno, non di una misura locale della conversione speech-swift di CoreML e non di un risultato di attribuzione denominato-speaker.
| Dataset | Condizione | DER |
|---|---|---|
| CALLHOME Parte 2 | 2 relatori di riferimento | 6.57% |
| CALLHOME Parte 2 | 3 altoparlanti di riferimento | 10.05% |
| CALLHOME Parte 2 | 4 relatori di riferimento | 12.44% |
Tutte le righe utilizzano latenza input-buffer 1.04 s, sovrapposizione inclusa, un colletto di 0.25 s e post-elaborazione sintonizzata su disgiunta CALLHOME Parte 1. CALLHOM è concesso in licenza e non è in bundle. Local diarization-bench report comparabili risultati separatamente dal conteggio di riferimento nella console e in JSON sotto byReferenceSpeakerCount
Community-1 Pipeline
Community-1 corre entrambe le fasi neurali con CoreML e tutti i processi di elaborazione degli host Swift, così non si carica MLX o richiedere Metal libreria shader. I default pubblicati sono conservati: decodifica hard powerset, maschere a singolo diffusore pulite con il ritorno a monte a corto raggio, 0.6 soglia centroid-linkage, Fa=0.07, Fb=0.8, e alla maggior parte 20 VBx iterations.
Sul subset a cinque file fisso VoxConverse release (setti 1,057.49, colletto 0.25-secondo, sovrapposizione inclusa), uscita Swift riscossa con pyannote.metrics misurato 4.66% DER / 21.43% JER; il riferimento CoreML pubblicato misurato 4.65% / 21.42%. Questo è un piccolo controllo di parità, non una richiesta di qualità dataset-wide.
Con il segnapunti frame-grid di speech-swift sullo stesso sottoinsieme, Community-1 misurato 9.31% DER / 16.20% JER, 25.5× in tempo reale, e 1.54 GB picco RSS. Il motore predefinito Pyannote misurato 5.03% / 9.28%, 105.7× in tempo reale, e 393 MB. Community-1 è quindi un opzionale pipeline upstream-parity con i limiti del contatore e centroids restituiti, non un'accuratezza universale o un aggiornamento della velocità.
Pyannote Pipeline
La pipeline di default viene eseguita in due fasi:
Fase 1: Segmentazione + Catena di altoparlanti
Pyannote segmentation-3.0 elabora finestre scorrevoli 10-secondo con sovrapposizione 50%. A decoder powerset converte il 7-class output in probabilità di per-speaker (fino a 3 diffusori locali per finestra). 5-secondo sovrapposizione — l'identità dell'altoparlante viene propagata attraverso le finestre mediante l'elaborazione Correlazione di Pearson tra tracce di probabilità nella zona sovrapposta, con avidità esclusiva per gli ID di altoparlante globali coerenti.
Fase 2: Embedding post-hoc
Dopo la diarizzazione, WeSpeaker ResNet34-LM estrae un centroide dimensionale 256 incorporato per diffusore, che consente l'estrazione dell'altoparlante target (--target-speaker) ma non guidare l'assegnazione dell'altoparlante stesso.
Migrazione da pyannote.audio
Se vieni da Python pyannote.audio biblioteca — sostituzione di una Pipeline sottoclasse che imposta pipeline.segmentation = ..., o allontanarsi da un hosting server pyannote/speaker-diarization-3.1 — Soniqo avvolge lo stesso modello Pyannote-Segmentation-3.0 e lo esegue interamente on-device su Apple Silicon. No Python runtime, no CUDA, no Hugging Face token a inference time.
| pyannote.audio ( Python) | Soniqo (Swift) |
|---|---|
Pipeline.from_pretrained("pyannote/speaker-diarization-3.1") |
DiarizationPipeline.fromPretrained() |
pipeline(audio_file) |
pipeline.diarize(audio: samples, sampleRate: 16000) |
pipeline.segmentation = ... (sottoclasse doganale) |
Corretto: Pyannote-Segmentation-3.0 ( MLX o CoreML, auto-selezionato) |
diarization.itertracks(yield_label=True) |
for seg in result.segments { ... } |
diarization.write_rttm(file) |
CLI: --rttm |
pyannote.metrics.diarization.DiarizationErrorRate |
CLI: --score-against reference.rttm |
Il Pyannote-Segmentation-3.0 i pesi vengono convertiti dall'a monte HuggingFace checkpoint, quindi i logits di segmentazione sono numericamente equivalenti all'interno della tolleranza di precisione del galleggiante. La catena di post-segmentazione (la correlazione tra le finestre sovrapposte + l'avidità esclusiva corrispondenza) e post-hoc WeSpeaker Le fasi di embedding sono reimplementate Swift ma produrre un output RTTM comparabile al riferimento Python Conduttura.
Non c'è streaming OnlineSpeakerDiarization equivalente per il motore Pyannote. Per l'uso in tempo reale di diarizzazione --engine sortformer invece, che gestisce il modello Sortformer con buffer di stato FIFO e altoparlante-cache.
Uso CLI
# Basic diarization (pyannote, default)
.build/release/speech diarize meeting.wav
# Community-1 (CoreML + native PLDA/VBx)
.build/release/speech diarize meeting.wav --engine community1
.build/release/speech diarize meeting.wav --engine community1 --num-speakers 2
# End-to-end Sortformer (CoreML)
.build/release/speech diarize meeting.wav --engine sortformer
# Nemotron 3 (CoreML default; MLX optional)
.build/release/speech diarize meeting.wav --engine nemotron3
.build/release/speech diarize meeting.wav --engine nemotron3 --nemotron3-backend mlx
# RTTM output format (for evaluation)
.build/release/speech diarize meeting.wav --rttm
# JSON output
.build/release/speech diarize meeting.wav --json
Estrazione di altoparlante target
Fornisce audio di registrazione di un diffusore noto per estrarre solo i loro segmenti da una registrazione. Il gasdotto calcola l'integrazione dell'audio di registrazione e trova il cluster con la più alta somiglianza di cosene.
# Extract segments for a specific speaker
.build/release/speech diarize meeting.wav --target-speaker enrollment.wav
DER Scommesse
Valutare la qualità della diarizzazione segnando contro un file RTTM di riferimento. Il gasdotto calcola il tasso di errore di diarizzazione (DER), che misura la percentuale di tempo che viene attribuita in modo errato.
# Score against reference RTTM
.build/release/speech diarize meeting.wav --score-against reference.rttm
RT RT RT RT produzione di energia elettrica
La bandiera --rttm produce l'uscita Rich Transcription Time Marked, un formato standard utilizzato per la valutazione della diarizzazione.
SPEAKER filename 1 start_time duration <NA> <NA> speaker_id <NA> <NA>
Opzioni
| Opzione | Designazione |
|---|---|
--target-speaker | Iscrizioni audio per l'estrazione di altoparlante target (solo piannota) |
--embedding-engine | Motore di embedding del diffusore: mlx o coreml (solo in piannota) |
--vad-filter | Prefiltro con Silero VAD (solo per piannota) |
--community1-compute-units | ane (default) cpu, gpu, o all |
--num-speakers | Conto preciso dell'altoparlante ( Community-1) |
--min-speakers | Conto minimo dell'altoparlante ( Community-1, default 1) |
--max-speakers | Conto massimo del diffusore ( Community-1 |
--rttm | Uscita in formato RTTM |
--json | Formato di uscita JSON |
--score-against | Referenza RTTM file per la valutazione DER |
La diarizzazione funziona meglio con le registrazioni che hanno un chiaro girante di altoparlante. Il discorso altamente sovrapposto può ridurre l'accuratezza.
Download del modello
I modelli vengono scaricati automaticamente sul primo utilizzo:
| Componenti | Modello | Dimensione | HuggingFace |
|---|---|---|---|
| Segmentazione | Pyannote-Segmentation-3.0 | 5,7 MB | aufklarer/Pyannote-Segmentation-MLX |
| Altoparlante Embedding | WeSpeaker-ResNet34-LM (MLX) | ~ 25 MB | aufklarer/WeSpeaker-ResNet34-LM-MLX |
| Altoparlante Embedding | WeSpeaker-ResNet34-LM (CoreML) | ~ 25 MB | aufklarer/WeSpeaker-ResNet34-LM-CoreML |
| pipeline Community-1 | PyanNet + mascherato WeSpeaker + PLDA/VBx | ~ 32 MB | aufklarer/Pyannote-Community-1-CoreML |
| Sortformer | Diarizzazione di Sortformer ( CoreML) | ~240 MB | aufklarer/Sortformer-Diarization-CoreML |
| Nemotron 3 | Diarizzazione INT8 ( CoreML o MLX) | ~ 100 MB ciascuno | CoreML · MLX |
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]")
}
// Target speaker extraction
let targetEmb = pipeline.embeddingModel.embed(audio: enrollmentAudio, sampleRate: 16000)
let segments = pipeline.extractSpeaker(
audio: meetingAudio, sampleRate: 16000,
targetEmbedding: targetEmb
)
// Full Community-1 pipeline with bounded speaker counts
let community1 = try await Community1DiarizationPipeline.fromPretrained()
try community1.prewarm()
let attributed = try community1.diarize(
audio: meetingAudio,
sampleRate: 16000,
speakerBounds: Community1SpeakerBounds(minimum: 2, maximum: 6)
)