Recursive AI

Diarization

All onespeech docs

Speech recognition for .NET. Speaker labels are document-local, not biometric identities. No audio or embedding is persisted by diarization helpers.

Word assignment

TranscriptDiarization.Merge is shared by diarizers. Input ActiveTurn values wrap original-clock turns and optional relative activity in [0,1] (default 1, not a probability). Turns require a named, assigned speaker, nonnegative start and positive duration. Null times are never filled in.

Intervals are half-open. A sweep partitions the turns at every endpoint. Where speakers are concurrent, the highest-activity turn wins; equal activity breaks by ordinal speaker ID. Covered duration in these partitions is summed per speaker for each word. The speaker covering the greatest duration wins; equal durations again break by ordinal ID. Uncovered portions do not vote. A positive-duration word can therefore be assigned even if most of its interval is silence. No coverage, null endpoints, reversed endpoints, and zero-duration words yield SpeakerLabel.Unassigned.

Word.Overlap is true only when a positive-duration part of the word intersects simultaneous turns from different speakers. Duplicate or overlapping turns from the same speaker do not count as overlap. Touching endpoints do not overlap. This flag is independent of which speaker wins. Merging replaces prior speaker/overlap assignments; it preserves word text, timing, confidence and timing method, document text, language and model provenance. Segment words are assigned by the same rule. The input document remains unchanged.

Original turns are ordered by start and ordinal speaker ID. Each assigned root word is attached once to the turn of its chosen speaker having greatest temporal intersection, breaking ties by earliest start. Turn text is the exact concatenation of attached word text, without inserted spacing. Segment-only words are assigned in their segments but are not added to the root word list or turn text.

TranscriptDiarization.Exclusive provides a separate, exclusive caption timeline: the highest-activity speaker at each instant, with the same tie rule, coalescing adjacent intervals for the same speaker. It leaves gaps uncovered and produces empty turn text/words; a caller must place captions explicitly rather than infer word timing from this view.

Separated-party stereo

ChannelDiarizer uses channel labels channel-1 and channel-2; it does not infer identities or distinguish multiple people on one channel. Auto-detection is deliberately conservative:

  • exactly two channels;
  • at least three 20 ms frames dominated by the left channel and at least three dominated by the right;
  • dominated means energy at least 100 times the other channel (20 dB), above mean-square energy 1e-8;
  • absolute normalized waveform dot product over the whole recording at most 0.3.

The final short frame is included. These are initial heuristic values, not thresholds fitted or validated on a speech development set. Silence, mono, dual-mono and one-sided conversations are inconclusive, not evidence of separation. Auto-detection returns false for them. This rule cannot prove separation: uncorrelated stereo music or alternating noises may pass. Known separated calls can set forceSeparated: true; known mixed audio should use a voice-clustering diarizer instead. Failure is a CapabilityNotSupportedException, never a silent downmix fallback.

For each channel, VAD runs on bounded, independently analyzed blocks of at most 30 seconds, retaining original-clock times. VAD state resets at block boundaries; this is not continuous-state VAD equivalence. Simultaneous channel speech is retained. Channel output metadata grows with turns, but temporary PCM does not grow with duration. The caller's in-memory input remains borrowed.

Pipeline

The five-argument VadTranscriptionPipeline constructor accepts a borrowed Diarizer after the existing chunk-duration and progress arguments. The four-argument constructor is unchanged. In-memory transcription runs recognition on the usual downmix and diarization on the original channels, then merges words. Segment enumeration computes whole-recording diarization before emitting any final segments, so assignments are never revised after emission.

ClusteringDiarizer and ChannelDiarizer implement BlockDiarizer: consecutive PCM blocks share one recording clock, and returned IDs are global to that recording. File inputs make two bounded decoding passes: diarization first, recognition second. Encoded streams use the existing temporary seekable spool and rewind it between passes; the spool is deleted when processing ends. No recording waveform is retained. Progress remains recognition audio-time progress, not wall time or a sum over both passes. Callers must not change a file while it is being processed.

A custom plain Diarizer still works in memory, but file inputs require BlockDiarizer; otherwise they throw CapabilityNotSupportedException naming that requirement. BlockDiarizer declares contributing Models, which the pipeline adds to document provenance, deduplicated by ID and revision. Both channel and clustering implementations declare their VAD/embedding models. Omitting the diarizer preserves existing bounded file transcription.

Voice clustering and overlap limitation

ClusteringDiarizer is the tier-1 voice-clustering implementation, using caller-supplied VAD and speaker-embedding roles. It does not detect overlapped speech: each speech interval gets only one speaker at a time. The overlap-aware Nemotron 3 Diarization upgrade is an explicit tier-2 option, never selected by these helpers; the pyannote segmentation slot remains separate. Channel diarization is a distinct exception because separated channels supply activity independently. The component itself always uses the caller's embedder. The Speech.Transcribe helpers select CAM++ Chinese for a requested or detected Chinese language (zh, zh-*); otherwise they select CAM++ English. An explicit language takes precedence over detection. Recognition runs before the whole-recording diarization pass so this policy also applies without a language hint. Encoded streams are spooled once, with bounded PCM on both passes. This is a language-based starting choice, not a quality-validated default for every language.

For an overlap-aware file transcript, keep your recognizer and VAD and replace only the diarizer:

C#
using var overlap = await OneSpeech.Diarization.NemotronDiarizer.LoadAsync();
var transcript = new OneSpeech.Pipeline.VadTranscriptionPipeline(recognizer, vad, null, null, overlap).Transcribe(path, language: null, CancellationToken.None);

The pipeline retains the higher-activity speaker in simultaneous intervals, flags overlapping words, and leaves gaps Unassigned. This does not separate simultaneous voices or recover words the recognizer missed. The named load fetches the publisher's pinned checkpoint, keeps OpenMDW agreement/origin notices in ModelInfo, and converts only into the local cache.

Windows and clock

Input is consecutive 16 kHz PCM with one consistent channel count (1–32). Channels are averaged for voice clustering. VAD runs in fixed 30-second horizons, independent of caller block boundaries; state resets at each horizon. VAD regions are sorted and overlapping/touching regions unioned. Segments shorter than 100 ms are discarded. Following Landini et al., arXiv:2012.14952, §3.2, defaults are 1.5-second embedding windows and a 0.25-second stride; partial trailing windows of at least 100 ms are included. Models are borrowed, and each finite, nonzero embedding is length-normalized in double-precision accumulation before clustering. Embedding failures propagate; they are not replaced by arbitrary labels.

The boundary between neighboring window assignments is the midpoint between their centers. First/last assignments extend to the VAD region endpoints. Silence gaps remain gaps. Adjacent same-speaker assignments are coalesced. Labels speaker-1, speaker-2, ... follow first occurrence, are document-local, and are not enrolled identities. These are window-level speaker boundaries, not refined word or phonetic timing. Whole-file Speech.Transcribe helpers additionally compare normalized cluster means to compatible process-wide enrollments, setting SpeakerLabel.Name on accepted matches while preserving these document-local IDs. Unknown clusters remain anonymous; see speaker recognition.

Spectral clustering and AHC

For recordings whose retained embedding span exceeds 60 seconds, the default ClusteringMethod.Spectral follows Park et al., Auto-Tuning Spectral Clustering for Speaker Diarization Using Normalized Maximum Eigengap, arXiv:2003.02405v1, §III, Eq.4–15:

  1. Raw cosine affinities; row-wise top-p binarization (stable index ties), including the diagonal when ranked there.
  2. Symmetrization (A + Aᵀ)/2, then unnormalized Laplacian D − A.
  3. Symmetric eigendecomposition and ascending eigenvalues. The largest allowed eigengap estimates the speaker count. Select p minimizing p × (largestEigenvalue + 1e-10) / max(gap,1e-10).
  4. Cluster rows of the smallest-k eigenvector matrix by Euclidean Lloyd k-means, with deterministic farthest-first seeds (first seed index 0), stable ties and empty-cluster repair. At most 100 iterations.

Two bounded-work deviations from the paper are explicit: dense clustering uses up to MaxLandmarks uniformly spaced windows over the complete sequence (default 128, allowed 16–256); p is searched at 2,4,8,... plus max(2,floor(L/4)), rather than every integer up to L/4. All nonsampled windows are assigned to the maximum-cosine landmark-cluster centroid; landmark labels are retained, including explicit-count splits of indistinguishable vectors. Rare/short speakers absent from the sample can therefore be missed. This is not a reference-equivalence claim.

The symmetric eigensolver uses cyclic Jacobi rotations, at most 60 sweeps, stopping when maximum off-diagonal magnitude is ≤1e-10 times the largest diagonal magnitude (at least 1). Numerical nonconvergence uses AHC instead. When all landmark cosines are within 1e-6 of one, there is no geometric separation evidence; AHC avoids creating speakers from arbitrary graph tie-breaking.

ClusteringMethod.Agglomerative is the alternative and the spectral numerical fallback: average-link cosine similarities, stable pair-order ties, merging to the supplied exact count or stopping below the configurable cosine threshold while honoring min/max. This uses the cosine AHC initialization described in Landini §3.2, not PLDA. The generic threshold 0.65 is an exposed starting value, not a universal model calibration; use the model-specific measured profile below. No embedding-model weights are changed.

NumSpeakers is exact for nonempty speech; MinSpeakers/MaxSpeakers constrain estimates. Default range is 1–8, supported ceiling 32. Exact counts must lie within min/max. If speech produces fewer windows than the required count, the request is refused with CapabilityNotSupportedException; silence produces no turns, not fictitious speakers. Invalid parameter combinations are rejected. Cancellation is checked per PCM block, embedding window, eigen sweep, clustering iteration and output turn.

Short recordings

For a retained embedding span of at most 60 seconds, the default spectral policy uses average-link cosine AHC instead. A sparse top-p rank graph can partition even a compact single-speaker cloud into disconnected nearest-neighbor components; its eigengap then counts those components rather than speakers. Absolute similarity is needed in this regime. This is a short-recording policy, not a two-speaker cap: exact/min/max hints still apply, including counts above two.

Only full-duration embedding windows provide clustering landmarks when there are enough to satisfy the requested minimum/exact count. Truncated tails down to 100 ms remain in the output activity sequence but are assigned to the full-window centroids, rather than introducing clusters from poorly supported embeddings. If there are insufficient full windows, all windows remain eligible. The landmark bound is unchanged. This full-window rule applies to both clustering methods on short recordings; longer recordings keep the original windows and S128 behavior.

ShortRecordingThreshold defaults to 0.3, used only by the short-recording spectral policy. Explicit Agglomerative continues to use AgglomerativeThreshold. The choice was frozen on 24 fixed AMI development excerpts (ES2011a/b; 10, 20, 30 and 60 seconds at offsets 60 + 60i seconds, i=0..11), comparing cosine thresholds {0.15,0.3,0.45,0.65}. Threshold 0.3 with full-window landmarks had the lowest pooled DER (20.25% versus 27.12% for the previous file-helper defaults) and the best count accuracy (16/24 versus 7/24). No held-out speaker identities, counts or boundaries reach inference.

onespeech-eval short-diarization prepare-ls CORPUS OUTPUT creates the repeatable check set outside the repository: LibriSpeech test-clean files ordered by SHA-256 of 1729:<filename>, the first eligible 5–15 second file per distinct speaker, 24 speakers. Twelve single clips use the first twelve speakers; each is paired with the corresponding speaker in the second twelve. Odd-index pairs repeat the two utterances once, giving alternating-speaker files in the 10–60 second range. No silence is added. sources.tsv records source/derived hashes and CC-BY-4.0 attribution; manifest.tsv names WAV/RTTM pairs. Reference speaker identity covers each entire utterance, including its silence, so DER includes VAD misses at utterance edges. This is a constructed check, not a natural conversation accuracy claim. tools/scripts/check-short-diarization.sh prepares and scores it; the evaluator can also score saved CLI JSON (json:DIRECTORY) or Speech.Transcribe (transcribe, Whisper tiny, English).

The fixed 24-recording check produced the following speaker-count matches and pooled DER (no collar, overlap scored; reference includes utterance silence):

PathSingle count matchesSingle DERTwo-speaker count matchesTwo-speaker DER
Previous low-level/CLI defaults0/1276.12%9/1219.59%
Previous file-helper profile0/1274.04%9/1214.81%
Shared short-recording policy12/125.15%11/126.08%

onespeech diarize and Speech.Transcribe (Whisper tiny, English) both reproduced the final counts and DER. One two-speaker pair is merged; the threshold is not retuned on these checks. These are constructed-data correctness checks, not bootstrap population estimates or comparisons against a reference diarizer. Re-scoring the four full meeting holdouts preserved the previously measured DER at the shown precision: ES2004a 28.21%, ES2004b 20.92%, R8001 41.57%, R8003 26.79%.

Memory and resegmentation

Only the embedding sequence and interval metadata grow with file duration. Temporary PCM is bounded by 30-second buffers (plus the decoder's bounded state); dense clustering is O(L²), capped at L=256. Retained sequence storage is O(ND+N), with float embeddings requiring 4ND bytes plus window/interval/collection overhead, labels and O(KD) centroids. This is not constant total memory independent of duration. Default MaxWindows=100000 (configurable up to 1000000) refuses further windows explicitly instead of growing without a limit. At the default stride, continuous speech produces approximately 14400 windows/hour; dimension 192 needs approximately 11 MB/hour of vector payload, dimension 256 approximately 15 MB/hour, before metadata. Caller-owned in-memory PCM is outside this bound.

An optional EmbeddingResegmenter receives borrowed windows/initial labels synchronously and returns a label per window before turn construction. The output must use only initial labels and respect count hints. The low-level constructor installs none by default; file helpers use the cosine-centroid profile below. In particular VBx is deferred. Landini §§2.1–2.3 requires a compatible pretrained PLDA mean, whitening/LDA transform and between-speaker variances. None is fitted or substituted here. Embeddings are never written to disk or retained by the diarizer after the call.

Development parameters and evaluation

CAM++ English (512 dimensions, float32) was fitted on AMI Full-corpus-ASR dev ES2011a/ES2011b only, with the original Mix-Headset signal and word-derived references described in the fetch scripts. Window defaults remain the paper-based 1.5 s / 0.25 s; count range is 1–8, with no oracle speaker count. The grid uses 64/128/256 landmarks and AHC thresholds −0.2, −0.1, 0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.50, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85. The initial high-threshold grid was extended using development results only. Selection minimizes pooled speaker-time DER, ties by reference-speaker-macro JER then ordinal profile ID. Embeddings and VAD outputs are replayed from RAM after input SHA checks while varying clustering parameters; no embeddings are saved or model weights altered.

CAM++ en profileMethodLandmarksAHC thresholdPooled dev DER / JER
S128, selected primarySpectral/NME1280.65 numerical fallback only33.3520% / 42.6786%
A64-0.15, fitted alternativeAverage-link AHC640.1557.0071% / 72.1743%

These are model-specific recipes, not a claim that the generic options are optimal for every embedder. S128 coincides with the existing spectral defaults. To use the fitted AHC alternative, explicitly set Method=Agglomerative, MaxLandmarks=64, AgglomerativeThreshold=0.15; retain 1.5 s / 0.25 s windows and min/max 1/8. All selections were frozen before reading holdout scores.

Channel-layout calibration used AMI dev ES2011a/ES2011b Headset-0/1 only. Ten correlated proxies total (five per meeting) cover separated microphones, 1% statistical leakage, 25%/50% leakage negatives, and dual mono. Leakage is computed on frame energy/cross-energy statistics; no new speech waveform is rendered. Searching 10/15/20/25/30 dB and normalized-dot limits 0.2/0.3/0.4/0.5/0.6 retained 20 dB / 0.3, with 4 true positives, 6 true negatives and no errors. Ties prefer the smallest change from the initial constants. The fixed three-frame and energy-floor rules are unchanged. This is not independent telephony accuracy or evidence that the heuristic proves separation.

Initial holdout floors

The embedder is ModelScope iic/speech_campplus_sv_en_voxceleb_16k revision 032b8131a7ad812f87061955ca974c99060c5a03; converted graph SHA-256 f333a00d5d66b9bf3d7e7abf35f36ff4a01e6e8a0df235b89a125e9fbe3cc15c. Linux x64, AMD Ryzen 9 7950X3D (32 logical CPUs, AVX2/FMA/AVX-512 available), .NET SDK 10.0.403/runtime 10.0.14, CPU/float32, eight inference threads, OneModel 1.0.0 and OneAudio 1.7.2; no GPU or speed measurement. Silero v6.2.3 uses threshold 0.5, negative 0.35, minimum speech 250 ms, minimum silence 100 ms, pad 30 ms, with the documented independent 30 s horizons. No collar; all overlap scored; no UEM exclusions. Figures are first-measurement floors, not reference parity or an absolute quality pass.

Held-out meetingS128 DER / JERA64-0.15 DER / JER
AMI test ES2004a, Mix-Headset33.9706% / 38.1994%36.2530% / 39.3777%
AMI test ES2004b, Mix-Headset27.0682% / 29.1370%28.8334% / 29.0338%
AliMeeting Eval R8001_M8004_MS801, far channel 166.1638% / 64.4226%67.9955% / 65.5995%
AliMeeting Eval R8003_M8001_MS801, far channel 145.3672% / 51.7859%47.6219% / 53.7021%

Pooled S128: AMI DER 29.0875%, JER 33.6682%; AliMeeting DER 55.2437%, JER 58.1043%. Descriptive 95% bootstrap intervals over the two meetings (1,000 resamples, seed 1729) are respectively DER [27.0682,33.9706]%, JER [29.1370,38.1994]%, and DER [45.3672,66.1638]%, JER [51.7859,64.4226]%. They do not establish generalization to a new speaker/meeting population. Individual-meeting intervals are unavailable. Missed speaker-time dominates these rows; this measurement does not separate VAD misses from the known inability to represent concurrent speakers.

Language-appropriate evaluation and published bundle comparison

CAM++ Chinese (iic/speech_campplus_sv_zh-cn_16k-common, revision 013c18884dffb82846cf472dd06dd4a08d97e2cd, converted SHA-256 4b2f0fef5ec8cb855b53c6b5abae5dd4cd72c215137c52d32f5c477e4a792f49) improves the Mandarin rows with the same frozen settings, without fitting on AliMeeting Eval:

AliMeeting Eval meetingChinese S128 DER / JERChinese A64-0.15 DER / JER
R8001_M8004_MS80162.3775% / 59.4958%72.9761% / 82.1277%
R8003_M8001_MS80139.6415% / 42.5590%48.2732% / 59.3365%

A released ModelScope 1.40.2 public speaker-diarization pipeline was run black-box with its published bundle iic/speech_campplus_speaker-diarization_common at 0b056318fde24067871436d60d020fa01f3096b4. Unlike passing a speaker-verification model directly to a diarization task, this is the documented bundle. It uses its own FSMN VAD, Chinese CAM++ and speaker-change locator, with default settings and no speaker-count oracle. Only auxiliary configuration paths were changed to verified local copies; network access was disabled. Pins are in tools/oracles/diarization-modelscope/diarization-bundle.tsv; its driver is bundle.py and dependency lock is under tools/oracles/diarization-modelscope. CPU float32, four threads/affinity to four logical CPUs, Python 3.13.17 / Torch 2.11.0 CPU, same host and scoring conventions as above. These are different systems, not logit-parity measurements.

MeetingOur S128 DER / JER (English for AMI, Chinese for AliMeeting)ModelScope bundle DER / JER
ES2004a33.9706% / 38.1994%26.5359% / 29.6337%
ES2004b27.0682% / 29.1370%18.1017% / 19.2563%
R8001_M8004_MS80162.3775% / 59.4958%34.5196% / 34.0168%
R8003_M8001_MS80139.6415% / 42.5590%26.8887% / 28.5758%

Every row misses a 0.5-point difference bound. A single meeting cannot supply an utterance/file bootstrap interval; these fixed slices do not prove population quality. Missed speech is the largest component in all our S128 rows. Replacing the embedder alone does not address the VAD/overlap weakness; no cause beyond this loss breakdown is established here.

A real 300-second AMI ES2004a excerpt through Speech.Transcribe with Whisper small and the original 0.5-threshold / 30-ms-padding activity settings produced 344 words, WER 16.0584% against chronological timed AMI words (en/1, 411 reference words), 28 Unassigned, zero Overlap and zero untimed words. Under an optimal one-to-one speaker mapping, 290/344 (84.3023%) predicted words had the correct reference speaker; 290/335 (86.5672%) among words with reference-time coverage. Each predicted word's reference speaker is the one covering most of its interval, with ordinal ties. This is temporal speaker assignment, not lexical correctness; Unassigned, untimed and no-reference words count against the all-word fraction. These are informational excerpt results, not a long-form quality bar. onespeech-eval diarize speech-excerpt DATA_ROOT ES2004a OUTPUT openai/whisper-small writes the transcript JSON and scoring summary. Holdout references were never used to choose settings.

See evaluation for no-collar, overlap-inclusive DER/JER and RTTM input.

Diarization-specific speech activity

The file transcription helpers use separate Silero instances for ASR chunking and diarization. ASR and live chunking retain the published defaults (activation 0.5, deactivation 0.35, minimum speech 250 ms, minimum silence 100 ms, padding 30 ms). The diarization instance uses activation 0.2, deactivation 0.2−0.15 (float32, approximately 0.05), minimum speech 250 ms, minimum silence 250 ms, padding 150 ms. Independent 30-second horizons and the 100-ms minimum embedding segment remain unchanged. Low-level ClusteringDiarizer continues to use the caller-supplied detector; it does not override its options. No ASR VAD behavior or model weights change.

These activity settings were selected only on AMI development ES2011a/ES2011b. AliMeeting Train/dev was not present and AliMeeting Eval was not used for fitting. The activity grid contains activation {0.2,0.35,0.5}, deactivation activation−0.15, minimum speech {0,250} ms, minimum silence {100,250} ms, padding {30,150} ms (24 settings). Frame probabilities are computed once per independent horizon, then replayed through the production segmenter. The best three pooled development union-activity miss+false-alarm settings were shortlisted; full S128 clustering evaluated those, the original baseline, and a shorter-window diagnostic. The final choice minimizes pooled speaker-time DER, then speaker-macro JER, then ordinal profile ID. This is a bounded shortlist search, not a claim of global optimality.

Oracle activity uses the union of the development RTTM intervals, without reference speaker labels or counts, as the clustering input. It is diagnostic only and never used on holdouts. Clustering windows, S128 settings, embedders and the absence of overlap detection are held fixed. Short-segment diagnostics lower the internal embedding cutoff from 100 to 45 ms; the production cutoff stays at 100 ms.

Development meetingOriginal DER / JERSelected activity DER / JEROracle activity DER / JER
ES2011a37.7930% / 53.8078%33.1123% / 48.2213%18.2216% / 41.1434%
ES2011b30.4951% / 31.5493%23.5827% / 25.3175%15.4738% / 17.9560%

Neither baseline development meeting lost an entire region to the 100-ms embedding cutoff: zero regions, zero seconds. Ownership spans the whole retained region even when a trailing embedding window is too short. With oracle activity only one 50-ms region (ES2011a) was omitted. Lowering the cutoff recovered that 50 ms but changed the sampled embedding sequence and increased confusion: oracle DER became 21.1118% / 15.5025%, and baseline DER 40.1308% / 30.8970%. Short-window dropping is not the main missed-speech cause on these development meetings, and the shorter cutoff was not adopted.

Reproduce the bounded development search with onespeech-eval diarize activity grid, shortlist, cluster, and freeze; the command rejects nondevelopment IDs for fitting. activity holdout requires the frozen setting file and writes its SHA-256 into every row. No evaluation speaker labels enter selection.

Pooled development DER/JER changes from 33.3520% / 42.6786% to 27.3133% / 36.7694%. Baseline miss/false-alarm/confusion totals are 660.880 / 20.873 / 117.625 seconds; selected totals are 427.738 / 96.369 / 130.535 seconds. Oracle-activity totals are 306.990 / approximately 0 / 89.667 seconds (16.5495% DER). Of oracle misses, 306.940 seconds are the unavoidable extra speaker-time during reference overlap for an exclusive single-speaker output; only 0.050 seconds come from the short-region cutoff. The original avoidable activity miss is about 353.940 seconds, larger than oracle-activity confusion. Oracle activity changes embedding segmentation as well as coverage, so this is a diagnostic breakdown rather than an additive guarantee for a replacement VAD.

The selected setting T20-M250-S250-P150-C100 was frozen before held-out scoring (selection SHA-256 c4d50356d42f1c4b0bd82a953ab94c9a1cae60f9b2e841e5a11b3b01bb49fed0). Each of the four held-out meetings was then run once, without an oracle activity pass or further tuning. All speech-activity, model, clustering, precision and scoring details remain as above except the selected activity profile. Values below supersede the earlier activity floors for the helpers:

MeetingSelected DER / JERSelected miss / FA / confusion (s)Published bundle DER / JERBundle miss / FA / confusion (s)
ES2004a28.8213% / 31.0004%180.754 / 42.453 / 42.93826.5359% / 29.6337%176.510 / 49.150 / 19.380
ES2004b21.1057% / 19.9543%298.314 / 90.640 / 82.34618.1017% / 19.2563%282.540 / 84.210 / 37.470
R8001_M8004_MS80142.4480% / 42.3801%771.504 / 19.706 / 78.65234.5196% / 34.0168%616.960 / 46.150 / 44.280
R8003_M8001_MS80127.2741% / 29.8615%418.452 / 117.852 / 81.65826.8887% / 28.5758%414.640 / 127.700 / 66.890

All four DER/JER pairs improve versus their earlier same-embedder floors. R8003 DER is within 0.5 points of the bundle; its JER and both metrics on the other meetings remain outside that bound. Single-file intervals remain unavailable. On AMI, the remaining bundle gap is primarily confusion (excess 23.558 / 44.876 seconds), not activity misses alone. R8001 still has a substantial missed-speech gap. No new segmentation/speaker-change model or overlap detector is added, and these different-system comparisons do not establish numerical parity.

Cosine-centroid resegmentation

CosineResegmenter is an optional embedding-only algorithm, not a learned speaker-change model or VBx replacement. It uses the existing 1.5-second windows at 0.25-second hop; it does not extract finer audio windows or claim sub-hop precision. VAD coverage and the midpoint ownership rule stay unchanged. No extra waveform pass, model, biometric persistence or overlap detection is introduced.

For each initial cluster, average the unit embeddings of stable windows, then normalize the sum. A window is stable when its initial label and the labels of StableRadius neighbors on either side agree, with no activity gap in that support. If a cluster has no stable windows, use all its windows. A near-zero centroid norm (less than 1e-12) leaves the whole initial labeling unchanged. Cosine distance to these fixed centroids is the per-window assignment cost. An exact minimum-cost path minimizes the sum of assignment costs plus SwitchPenalty for each label change. Costs are per window, not per second; the penalty is soft smoothing, not a hard minimum-turn duration. The path is reset at a positive gap between embedding windows. Ties prefer staying, then the lowest original label. Speaker IDs are canonicalized by the enclosing diarizer after refinement. No speaker outside the initial labels is created; a speaker can disappear, and the enclosing diarizer still enforces explicit count/min/max constraints. It refuses a violating result rather than ignoring a count request.

This is our own deterministic centroid/path design. It does not implement the publisher's acoustic transformer locator: its public API returned rounded change-point text, while its published card and paper do not specify a complete inference graph. That learned locator is not loaded by these helpers.

Public algorithm defaults are penalty 0.1 and radius 2; these are starting values, not a universal calibration. Limits: up to 1,000,000 windows, 32 distinct speakers and dimensions 1–4096, matching the clustering bounds. Path storage uses NK bytes for byte predecessors plus 4N bytes for output labels; centroid accumulators require at most 16KD bytes, plus small DP buffers and collection overhead. There is no additional PCM storage. Existing embedding-sequence storage remains O(ND), explicitly capped by MaxWindows, not constant total memory for arbitrarily long input. At the default N cap of 100,000, additional path payload is at most 3.6 MB. Cancellation is checked per window and during traceback.

Selected file-helper profile

The file helpers, CLI and low-level ClusteringDiarizer use CosineResegmenter(switchPenalty: 0.4, stableRadius: 2) by default. Set ClusteringOptions.Resegment = false to retain raw labels, or pass a custom resegmenter (which takes precedence). The default smoother is also omitted when an exact count or minimum above one is requested, because unconstrained smoothing can remove a required label; custom backends still must honor hints. The CLI and file helpers both use SileroVadOptions.Diarization. The low-level API deliberately borrows its caller-supplied detector unchanged; use that same profile when constructing Silero for equivalent activity behavior. The development-only search compared no resegmentation with all 15 combinations of radius {0,2,4} and penalty {0,0.05,0.1,0.2,0.4}, using the already selected activity profile and S128 clustering unchanged. All windows were the original 1.5 s / 0.25 s windows. Selection minimizes pooled development speaker-time DER, then macro JER and ordinal setting ID; no resegmentation wins a tie against the baseline. No AliMeeting Eval or AMI test labels were used.

AMI developmentNo resegmentation DER / JERSelected DER / JER
ES2011a33.1123% / 48.2213%31.5613% / 47.1127%
ES2011b23.5827% / 25.3175%22.1844% / 23.0626%
Pooled27.3133% / 36.7694%25.8552% / 35.0877%

Pooled development confusion falls from 130.535 to 95.589 seconds. Miss 427.738 seconds and false alarm 96.369 seconds are unchanged: this algorithm cannot recover activity or represent overlap. Profile R2-P400 was frozen before holdout inference, SHA-256 1d57269880fdccc38b635a53cf19776041c178a06e3419c5bcfd42bda7d53f13. onespeech-eval diarize activity refine-dev, refine-freeze and refine-holdout reproduce the search and fixed holdouts; the holdout command checks the freeze digest and refuses to overwrite scores. Development embeddings are cached only in RAM and cleared after each meeting.

The four complete holdouts were each run once with that frozen profile. Precision, machine, model pins, activity settings and no-collar/overlap-inclusive scoring are the same as the preceding activity rows. CPU float32, eight graph threads; OneModel 1.0.0, OneAudio 1.7.2, SDK 10.0.403/runtime 10.0.14. The reference remains the pinned ModelScope 1.40.2 published bundle, not this centroid algorithm. No new reference inference was needed.

MeetingBefore DER / JERRefined DER / JERRefined miss / FA / confusion (s)Published bundle DER / JER
ES2004a28.8213% / 31.0004%28.2116% / 29.6213%180.754 / 42.453 / 37.30826.5359% / 29.6337%
ES2004b21.1057% / 19.9543%20.9156% / 19.7743%298.314 / 90.640 / 78.10218.1017% / 19.2563%
R8001_M8004_MS80142.4480% / 42.3801%41.5741% / 41.1256%771.504 / 19.706 / 60.74334.5196% / 34.0168%
R8003_M8001_MS80127.2741% / 29.8615%26.7902% / 28.9546%418.452 / 117.852 / 70.69426.8887% / 28.5758%

All four improve over the preceding same-activity results, but the confusion gap is not closed. Using a 0.5-point single-file difference bound, only ES2004a JER and both R8003 metrics agree with the reference; ES2004b JER differs by 0.518 points and also misses. Single-file confidence intervals are unavailable. These fixed meetings do not establish population quality. This is not parity with the learned locator or the reference's full system.