Speaker Diarization of Known Speakers #1667
Replies: 11 comments 19 replies
-
|
Hey @tobiasschmidt89 I'm just started working on this too (for podcasts). Digging into pyannote I see it uses speechbrain "speechbrain/spkrec-ecapa-voxceleb" embedding model. https://huggingface.co/speechbrain/spkrec-ecapa-voxceleb I can share the approach I have in mind:
I'll see how that goes. Let me know how you get on with it. Feel free to hmu if you wanna collaborate a bit on this. |
Beta Was this translation helpful? Give feedback.
-
|
Hi @desicochrane, @tobiasschmidt89 . I'm exploring ways to improve speaker diarization in recordings with multiple speakers, but my primary goal is to accurately detect a specific target speaker. I have additional enrollment samples for that speaker (which I suppose I can use to generate an embedding), and I'm wondering if anyone here has achieved high precision for this particular use case. |
Beta Was this translation helpful? Give feedback.
-
|
Hi, here is my gist that applies embedding on a wav of a known speaker, and compares it to the output of the diarisation. I am building an API that manages meetings and audio from meetings to transcribe it. |
Beta Was this translation helpful? Give feedback.
-
|
In case it's helpful, there's a dev who did this process for public meetings in NYC and developed a great prompt engineering methodology to have LLMs identify speakers and then map the speaker name across very lengthy sessions. If you're running something like a 5+ hour D&D session, you might have a lot of 'lost in the middle' problems where the LLM does a much better job IDing speakers at the beginning and end of the file. He has a lot of tricks to fix that. He does mention toward the end that you can include a list of the possible speaker names in the prompt as a way to eliminate small variations and spelling mistakes that occur if you just set the llm loose without that parameter. Link to his speaker id prompts: https://gist.github.com/voberoi/3d82f6b2a55e79b7cd014847853be8bf |
Beta Was this translation helpful? Give feedback.
-
|
@desicochrane Did you end up figuring this out for podcasts. Looking into the exact same thing rn. |
Beta Was this translation helpful? Give feedback.
-
|
@mroconnell Thanks, taking a look at this |
Beta Was this translation helpful? Give feedback.
-
|
Hi @tobiasschmidt89 Are you running your DND sessions on a meeting platform? If you are, it might be easier to get speaker labels by using an API that supports transcription and speaker diarization. |
Beta Was this translation helpful? Give feedback.
-
|
Hi, I am an absolute newbie to these matters, and I'd like to know how you solved the problem of assigning the transcriptions from whisper to the diarization results? From my testing the diarization model identifies things ok enough, but the timestamps don't align at all with the ones provided by the transcription model (Systran/faster-whisper-large-v3). I was wondering if there was a way of passing the timestamps of the start and end of a transcribed phrase and having the model identify the speaker in that period. |
Beta Was this translation helpful? Give feedback.
-
|
Thanks, that’s a fair correction.
You’re right — “hallucination” is not the right term for diarisation
errors. What I meant was diarisation error rate: incorrect speaker
attribution, segmentation mistakes, and degradation under overlapped
speech. I’ll update the wording to avoid mixing DER with Whisper-style
hallucination.
The distinction is important: diarisation fails as a speaker
segmentation/attribution problem, while Whisper may hallucinate transcript
content when the acoustic signal is weak and the language model prior
dominates.
Good point also on overlapped speech. I’ll frame the improvement path as
training/evaluating diarisation on annotated data with more overlapping
speakers, rather than treating known/unknown speakers as the core issue
after diarisation.
Thanks for the precise correction.
pon., 27 kwi 2026, 11:15 użytkownik Alun King ***@***.***>
napisał:
… I'm being pedantic here, but the diarisation (sic, I'm UK based) model
doesn't 'hallucinate'. What you are describing there is the DER -
diarisation error rate. It's one of the biggest problems for diarisation,
the best way to improve that is to train the diarisation model on annotated
data that has more overlapped speaking. Known or unknown shouldn't be
different, as the thread is discussing identifying the speaker after
diarisation has occurred anyway.
The Whisper model 'hallucinates' because it uses language model reasoning
if the audio is not generating a strong enough signal.
Good luck with your project!
—
Reply to this email directly, view it on GitHub
<#1667 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BUHB4E4O7KWVH2JVXUE74534X4QMVAVCNFSM6AAAAACX2YK6W2VHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTMNZSGY3DGMI>
.
You are receiving this because you are subscribed to this thread.Message
ID: <pyannote/pyannote-audio/repo-discussions/1667/comments/16726631@
github.com>
|
Beta Was this translation helpful? Give feedback.
-
|
ModuleNotFoundError: No module named 'omegaconf'
…On Mon, Apr 27, 2026 at 6:16 PM rmatinha-fctunl ***@***.***> wrote:
I do apologise if I seemed rude. English is not my native tongue. I've
tried giving it a couple tests, and changing it to work from CLI instead of
colab/jupyter and I seem to be getting an error when it calls the embeding
model
File "/diarization/repos/scripts/diaritranscribe3.py", line 356, in apply_reference_speaker_labels
embedding_model = Model.from_pretrained(
^^^^^^^^^^^^^^^^^^^^^^
File "/.cache/uv/environments-v2/diaritranscribe3-3f9949c47f20e532/lib/python3.12/site-packages/pyannote/audio/core/model.py", line 602, in from_pretrained
loaded_checkpoint = pl_load(
^^^^^^^^
File "/.cache/uv/environments-v2/diaritranscribe3-3f9949c47f20e532/lib/python3.12/site-packages/lightning/fabric/utilities/cloud_io.py", line 73, in _load
return torch.load(
^^^^^^^^^^^
File "/.cache/uv/environments-v2/diaritranscribe3-3f9949c47f20e532/lib/python3.12/site-packages/torch/serialization.py", line 1579, in load
return _load(
^^^^^^
File "/.cache/uv/environments-v2/diaritranscribe3-3f9949c47f20e532/lib/python3.12/site-packages/torch/serialization.py", line 2190, in _load
result = unpickler.load()
^^^^^^^^^^^^^^^^
File "/.cache/uv/environments-v2/diaritranscribe3-3f9949c47f20e532/lib/python3.12/site-packages/torch/serialization.py", line 2179, in find_class
return super().find_class(mod_name, name)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ModuleNotFoundError: No module named 'omegaconf'
Do you happen to know if there is something I could do to fix this? I did
not use the forked whisper version which is the largest deviation I think I
made.
—
Reply to this email directly, view it on GitHub
<#1667 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BUHB4E42SYCEXFONZEHLARL4X6BXHAVCNFSM6AAAAACX2YK6W2VHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTMNZTGE2DGNQ>
.
You are receiving this because you commented.Message ID:
***@***.***
com>
|
Beta Was this translation helpful? Give feedback.
-
|
Your plan is exactly right — enroll one embedding per known person, then match each diarized speaker to the closest enrollment. Concrete version: from pyannote.audio import Pipeline, Inference, Model
from scipy.spatial.distance import cosine
emb = Inference(Model.from_pretrained("pyannote/embedding", use_auth_token=TOKEN),
window="whole") # window="whole" -> one vector per input
dia = Pipeline.from_pretrained("pyannote/speaker-diarization-3.1", use_auth_token=TOKEN)
# 1. enroll: one averaged embedding per known person (isolated ~1 min clips)
references = {name: emb(path) for name, path in {
"Max": "max.wav", "Maria": "maria.wav", "Tobi": "tobi.wav"}.items()}
# 2. diarize the full session
diar = dia("session.wav")
# 3. assign each diarized speaker to the nearest known person (or "Unknown")
def match(vec, thr=0.5):
sims = {n: 1 - cosine(vec, r) for n, r in references.items()}
name, score = max(sims.items(), key=lambda kv: kv[1])
return name if score >= thr else "Unknown"
names = {}
for spk in diar.labels():
seg = max(diar.label_timeline(spk), key=lambda s: s.duration) # longest clean segment
names[spk] = match(emb.crop("session.wav", seg))
labeled = diar.rename_labels(names)Two things that matter in practice: use |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi,
I really enjoy using this Library for speaker diarization to create labeled transcripts in combination with Whisper: Speaker 1: ..., Speaker 2: ..., Speaker 1: ...
Currently I then search and replace the anonymous speaker labels with the real names.
I have some meetings that always have the same speakers (D&D game sessions). Therefore I am searching for a way to kind of create "voice embeddings" of each speaker by recording them in isolation for a minute or so. Then I want to do a speaker diarization using these embeddings to get labels like: Max: ..., Maria: ..., Tobi: ..., Max: ..., Unknown: ...
I would be interested if someone has some pointers on how I could achieve this with Pyannote. I expect I need to do the following:
Crossed items I know how to do.
I am very comfortable with text embeddings. Audio embedding is a new topic for me.
I would really appreciate any pointers or example scripts.
Thank you
T.
Beta Was this translation helpful? Give feedback.
All reactions