Nodes/ComfyUI_Speaker_Diarization/Speaker Diarizer (Up to 5 Speakers)
ComfyUI Node

Speaker Diarizer (Up to 5 Speakers)

Who's Talking When? Split a Conversation Into Up to 5 Voice Tracks in ComfyUI

By ldfla·Created 5 months ago·Updated 5 months ago· 0
Speaker Diarizer (Up to 5 Speakers)
  • audio
  • speaker_1_audio
  • speaker_2_audio
  • speaker_3_audio
  • speaker_4_audio
  • speaker_5_audio
  • summary
  • segments_json
hf_token
deviceauto
min_speakers1
max_speakers5
merge_gap_ms200
keep_only_detected_speakerstrue
pyannote_python
worker_script
timeout_seconds600

Feed it a recording and it tells you who spoke when - then hands you back separate audio tracks for up to five distinct voices. That's speaker diarization, the "who said this" half of the transcription problem, and this node is one of the few ways to get it inside a ComfyUI graph. Think call-center recordings, conference calls, interview audio destined for a TTS pipeline, or a podcast where each host gets their own dubbing track. If you've ever had to hand-slice a two-hour interview in an editor because two people kept talking over each other, you know why this exists.

The part that makes this one interesting isn't just that it diarizes - pyannote has done that for years - it's when it diarizes. Most diarization tools label speakers with anonymous IDs (SPEAKER_00, SPEAKER_01) that don't mean anything until you map them yourself. This node reorders everything chronologically: speaker_1_audio is the first person to open their mouth, speaker_2_audio the second, and so on. For a call-center setup where "the caller" and "the agent" are whoever talks first and second, that mapping is the whole job.

How it actually works

Here's the architectural twist: this node does none of the pyannote work in the ComfyUI process. It writes your audio to a temp WAV, then launches a separate Python interpreter (pyannote_python) running a worker script (worker_script) as a subprocess, waits for it to write a JSON of per-speaker segments, then builds each output track by copying the original waveform and zeroing out every sample outside that speaker's segments.

Why bother with all that ceremony? Because pyannote.audio and ComfyUI share the same torch/torchaudio pile and they don't always get along. ComfyUI's custom-node dependency hell is legendary - every node installs into one shared Python environment, and one bad pip install can silently break a node that was working yesterday. The author's answer is to quarantine pyannote in its own venv and talk to it over a file. It's a genuinely smart design, and it means this node won't trash your image-generation setup just by existing.

The inputs and outputs that matter

You set a handful of things, and that's about it:

  • audio - an AUDIO input, straight from ComfyUI's audio loader nodes.
  • hf_token - a Hugging Face token whose account has accepted the conditions on the pyannote/speaker-diarization model. Non-negotiable; pyannote's model is gated.
  • min_speakers / max_speakers - your expected headcount, 1–5. Telling pyannote "there are 2 to 3 voices here" instead of "0 to 5" makes it noticeably more accurate.
  • merge_gap_ms - gaps up to this many milliseconds between the same speaker's segments get glued together. Default 200 is fine.
  • pyannote_python / worker_script - absolute paths to the external environment's Python and to pyannote_worker.py. This is where setup lives or dies.

Outputs: five AUDIO tracks plus a human-readable summary string and a segments_json with exact start/end/duration per segment - the thing you'd wire into a subtitle or SRT generator. If fewer than five voices are detected, the unused outputs are silent audio of the same length, so downstream nodes don't break.

Installing it

The README's version is short and, frankly, incomplete:

cd ComfyUI/custom_nodes
git clone https://github.com/ldfla/ComfyUI-Speaker-Diarization
cd ComfyUI-Speaker-Diarization
pip install -r requirements.txt

You can also just search "Speaker Diarization" in ComfyUI Manager and hit install. But here's the catch: the repo doesn't ship pyannote_worker.py. The node requires a path to it, and no such file exists in the repository, so you need to set up a separate Python venv, pip install pyannote.audio in it, and obtain or write that worker script yourself - the node's source shows the exact arguments it expects (--input-wav, --output-json, --hf-token, --device, --min-speakers, --max-speakers). The README also says pyannote 3.1 while the code's docstring targets pyannote.audio 4.x, and requirements.txt pins >=3.1,<4. Pick one and make the worker match it. It's a fresh, low-adoption pack - expect rough edges like this.

Where people get burned

The number-one failure mode: the node silently returns silent audio. On any error - bad token, missing worker, wrong device - it doesn't crash your graph, it returns five silent tracks plus an error message inside segments_json (some error strings are in Portuguese, the author's native language). If you're staring at silence, check that JSON output, not the waveforms. Then check the token: it must come from an HF account that clicked "agree" on the pyannote model's license gate. Finally, remember ComfyUI-ecosystem lesson number one: don't try to shortcut by installing pyannote into your main ComfyUI environment - that's exactly how you break every other node you own.

CategoryAudio/Isolation

Inputs (10)

NameTypeDefaultDescription
audioAUDIO
hf_tokenSTRINGHugging Face token for pyannote community-1
deviceCOMBOautoDevice used by the external pyannote worker
min_speakersINT11–5Minimum expected speakers
max_speakersINT51–5Maximum expected speakers
merge_gap_msINT2000–5000Merge adjacent same-speaker segments up to this gap
keep_only_detected_speakersBOOLEANtrueKept for compatibility. Output is timeline-preserving.
pyannote_pythonSTRINGAbsolute path to Python executable of the external pyannote environment
worker_scriptSTRINGAbsolute path to pyannote_worker.py
timeout_secondsINT60030–7200Timeout for the external worker

Outputs (7)

NameTypeDescription
speaker_1_audioAUDIO
speaker_2_audioAUDIO
speaker_3_audioAUDIO
speaker_4_audioAUDIO
speaker_5_audioAUDIO
summarySTRING
segments_jsonSTRING