Diarizacao de falantes
Identifique quem falou quando em uma gravacao multi-locutor. Dois engines de diarizacao estao disponiveis: um pipeline de duas etapas Pyannote (segmentacao + encadeamento de locutores baseado em atividade, depois embedding post-hoc) e um modelo ponta-a-ponta Sortformer (CoreML, Neural Engine).
Engines
Selecione o engine com --engine pyannote (padrao) ou --engine sortformer.
Pyannote (padrao)
Pipeline de duas etapas: a segmentacao Pyannote processa janelas sobrepostas com encadeamento de locutores baseado em atividade (correlacao de Pearson nas zonas de sobreposicao) para atribuir rotulos globais de locutor. A extracao post-hoc de embedding WeSpeaker permite identificacao de locutor alvo via audio de enrolamento.
Sortformer (CoreML)
Modelo neural ponta-a-ponta de diarizacao da NVIDIA. Preve diretamente a atividade por frame de ate 4 falantes sem estagios separados de embedding ou clustering. Roda no Neural Engine via CoreML com buffers de estado de streaming (FIFO + speaker cache).
Sortformer nao produz embeddings de falante. As flags --target-speaker e --embedding-engine estao disponiveis apenas com o engine Pyannote.
Pipeline Pyannote
O pipeline padrao roda em duas etapas:
Etapa 1: Segmentacao + Encadeamento de falantes
Pyannote segmentation-3.0 processa janelas deslizantes de 10 segundos com sobreposicao de 50%. Um powerset decoder converte a saida de 7 classes em probabilidades por falante (ate 3 falantes locais por janela). Janelas adjacentes compartilham uma sobreposicao de 5 segundos — a identidade do falante e propagada entre janelas computando correlacao de Pearson entre as trilhas de probabilidade na zona de sobreposicao, com matching exclusivo greedy para IDs de falante globais consistentes.
Etapa 2: Embedding post-hoc
Apos a diarizacao, o WeSpeaker ResNet34-LM extrai um embedding centroide de 256 dimensoes por falante. Esses embeddings permitem extracao de falante alvo (--target-speaker) mas nao guiam a atribuicao de falante em si.
Uso do CLI
# Basic diarization (pyannote, default)
.build/release/audio diarize meeting.wav
# End-to-end Sortformer (CoreML)
.build/release/audio diarize meeting.wav --engine sortformer
# RTTM output format (for evaluation)
.build/release/audio diarize meeting.wav --rttm
# JSON output
.build/release/audio diarize meeting.wav --json
Extracao de falante alvo
Forneca audio de enrolamento de um locutor conhecido para extrair apenas seus segmentos de uma gravacao. O pipeline computa o embedding de falante do audio de enrolamento e encontra o cluster com a maior similaridade de cosseno.
# Extract segments for a specific speaker
.build/release/audio diarize meeting.wav --target-speaker enrollment.wav
Pontuacao DER
Avalie a qualidade da diarizacao pontuando contra um arquivo RTTM de referencia. O pipeline calcula a Diarization Error Rate (DER), que mede a proporcao de tempo atribuido incorretamente.
# Score against reference RTTM
.build/release/audio diarize meeting.wav --score-against reference.rttm
Saida RTTM
A flag --rttm produz saida Rich Transcription Time Marked, um formato padrao usado para avaliacao de diarizacao. Cada linha segue o formato:
SPEAKER filename 1 start_time duration <NA> <NA> speaker_id <NA> <NA>
Opcoes
| Opcao | Descricao |
|---|---|
--target-speaker | Audio de enrolamento para extracao de falante alvo (somente pyannote) |
--embedding-engine | Engine de embedding de falante: mlx ou coreml (somente pyannote) |
--vad-filter | Pre-filtrar com Silero VAD (somente pyannote) |
--rttm | Saida no formato RTTM |
--json | Formato de saida JSON |
--score-against | Arquivo RTTM de referencia para avaliacao DER |
A diarizacao funciona melhor com gravacoes que tem turnos claros de falante. Fala altamente sobreposta pode reduzir a precisao. O numero de falantes e determinado automaticamente.
Downloads de modelos
Os modelos sao baixados automaticamente no primeiro uso:
| Componente | Modelo | Tamanho | HuggingFace |
|---|---|---|---|
| Segmentacao | Pyannote-Segmentation-3.0 | ~5.7 MB | aufklarer/Pyannote-Segmentation-MLX |
| Embedding de falante | WeSpeaker-ResNet34-LM (MLX) | ~25 MB | aufklarer/WeSpeaker-ResNet34-LM-MLX |
| Embedding de falante | WeSpeaker-ResNet34-LM (CoreML) | ~25 MB | aufklarer/WeSpeaker-ResNet34-LM-CoreML |
| Sortformer | Sortformer Diarization (CoreML) | ~240 MB | aufklarer/Sortformer-Diarization-CoreML |
API Swift
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
)