Skip to content

Expose the pyannote window shift ratio in the C API and language bindings - #3870

Merged
csukuangfj merged 2 commits into
k2-fsa:masterfrom
JulianPscheid:expose-pyannote-window-shift-ratio
Aug 13, 2026
Merged

csukuangfj merged 2 commits into
k2-fsa:masterfrom
JulianPscheid:expose-pyannote-window-shift-ratio

Conversation

@JulianPscheid

@JulianPscheid JulianPscheid commented Aug 11, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to #3769, which added window_shift_ratio to the C++ core and the CLI but deliberately left the bindings alone to stay reviewable. This exposes OfflineSpeakerSegmentationPyannoteModelConfig::window_shift_ratio through the C and CXX APIs and the language bindings that already surface that config, so the knob is reachable outside the CLI.

The C struct treats 0 and negative values as unset and maps them to 0.1. C API callers and raw bindings commonly zero-initialize config structs, and passing a zero straight through would fail the native (0, 1] validation and break every existing caller. The sentinel lives in one place, the config conversion in c-api.cc, and c-api.h documents it. NaN is not treated as unset; it still reaches native validation and is rejected. Typed binding defaults are 0.1.

For the standard window_size=160000 model the default path still computes a 16000-sample shift. A C API probe returned 16000 samples from a zero-initialized field and 32000 samples at 0.2. A build of untouched upstream/master and a build of this branch produced byte-identical segment output with the ratio unset (same ten segments, same SHA-256).

Two things worth calling out beyond the mechanical binding work. There is a new debug-only log line in offline-speaker-segmentation-pyannote-model.cc that reports the computed shift in samples, which is what makes propagation observable from a binding; it is inside the existing config_.debug guard and does not change normal output. And the WASM binding's struct packing moves from 4 to 8 bytes with its compile-time layout assertion updated to match. I could not compile that one locally, so it is worth a look in CI.

The benchmark that motivated the core option, for context: a 644 s two-speaker English WAV on macOS arm64, 0.10 at 40 s, 0.15 at 27 s (1.48x), 0.20 at 20 s (2.00x), with 99.89% and 99.93% frame-level label agreement against 0.10.

Check Result
Release C++ core, CLI, C API, CXX API, C/CXX examples Passed
Default output vs untouched upstream/master Identical (same 10 segments and SHA-256)
C API zero / negative / 0.2 native shift 16000 / 16000 / 32000 samples
JNI shared library Passed
Python build and import Passed
Java compile Passed (existing deprecation warnings only)
Flutter library analyze Passed
Dart example analyze Passed with existing warnings and info
Go wrapper tests and example build Passed
Node typecheck, native addon build, JS syntax Passed
Swift typecheck Passed
Kotlin and Android app Not compiled locally; Kotlin compiler and API artifact unavailable
.NET Not compiled locally; dotnet unavailable
Rust Not compiled locally; Cargo unavailable
Pascal Not compiled locally; FPC unavailable
WASM C++ Not compiled locally; Emscripten unavailable; JS syntax passed
HarmonyOS ETS Not compiled locally; Harmony toolchain unavailable; shared native bridge compiled through Node

git diff --check passes and no generated artifacts are included.

Summary by CodeRabbit

  • New Features

    • Added configurable Pyannote segmentation window-shift ratio for offline speaker diarization.
    • The setting is available across supported APIs and platforms, with a default value of 0.1.
    • Values can be adjusted to control segmentation window overlap.
  • Documentation

    • Updated speaker diarization guidance and examples to demonstrate the new configuration option.
  • Bug Fixes

    • Improved consistency by ensuring the configured window-shift ratio is applied throughout speaker diarization workflows.

Expose the pyannote segmentation window shift ratio through the C API, CXX wrapper, and supported language bindings.

Treat non-positive C values as the native 0.1 default so callers that zero-initialize config structs keep their existing behavior.
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Aug 11, 2026
@coderabbitai

coderabbitai Bot commented Aug 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds a Pyannote segmentation window shift ratio with a default of 0.1. It updates the native C/C++ APIs, language bindings, platform integrations, WebAssembly handling, and speaker diarization examples.

Changes

Pyannote window shift ratio

Layer / File(s) Summary
Native configuration and runtime handling
sherpa-onnx/c-api/*, sherpa-onnx/csrc/*, sherpa-onnx/c-api/docs/*
Defines window_shift_ratio, applies the 0.1 fallback for non-positive values, forwards it during creation, and logs the finalized value.
Language binding propagation
sherpa-onnx/java-api/..., sherpa-onnx/kotlin-api/*, sherpa-onnx/python/*, sherpa-onnx/rust/*, swift-api-examples/SherpaOnnx.swift, sherpa-onnx/pascal-api/*, scripts/go/*, scripts/dotnet/*, sherpa-onnx/jni/*, android/*
Adds the configuration field, builder or constructor support, default values, and native mapping across supported language APIs.
Platform and runtime integrations
flutter/sherpa_onnx/lib/src/*, harmony-os/*, scripts/node-addon-api/*, wasm/speaker-diarization/*
Adds configuration properties, serialization, native mapping, WebAssembly layout updates, defaults, and diagnostics.
Diarization example updates
c-api-examples/*, cxx-api-examples/*, dart-api-examples/*, dotnet-examples/*, go-api-examples/*, java-api-examples/*, kotlin-api-examples/*, nodejs*-examples/*, pascal-api-examples/*, python-api-examples/*, rust-api-examples/*, swift-api-examples/speaker-diarization.swift
Sets the Pyannote window shift ratio to 0.1 in speaker diarization examples. SpeakerDiarizationWorker.ets also reformats an error-handler brace.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: csukuangfj

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: exposing the Pyannote window shift ratio through the C API and language bindings.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sherpa-onnx/c-api/docs/speaker-diarization.dox`:
- Around line 17-19: Update the comment above
config.segmentation.pyannote.window_shift_ratio to state that non-positive
values use the default shift ratio of 0.1, and describe the setting as
controlling the sliding-window shift rather than overlap. Keep the example value
and valid range unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b7afe5ce-fb83-44f4-ab90-dda71f82f8d8

📥 Commits

Reviewing files that changed from the base of the PR and between c3625d2 and c81234e.

📒 Files selected for processing (39)
  • android/SherpaOnnxSpeakerDiarization/app/src/main/java/com/k2fsa/sherpa/onnx/speaker/diarization/SpeakerDiarizationObject.kt
  • c-api-examples/offline-speaker-diarization-c-api.c
  • cxx-api-examples/offline-speaker-diarization-cxx-api.cc
  • dart-api-examples/speaker-diarization/bin/speaker-diarization.dart
  • dotnet-examples/offline-speaker-diarization/Program.cs
  • flutter/sherpa_onnx/lib/src/offline_speaker_diarization.dart
  • flutter/sherpa_onnx/lib/src/offline_speaker_diarization_config.dart
  • flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart
  • go-api-examples/non-streaming-speaker-diarization/main.go
  • harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/non-streaming-speaker-diarization.cc
  • harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/ets/components/NonStreamingSpeakerDiarization.ets
  • harmony-os/SherpaOnnxSpeakerDiarization/entry/src/main/ets/workers/SpeakerDiarizationWorker.ets
  • java-api-examples/OfflineSpeakerDiarizationDemo.java
  • kotlin-api-examples/test_offline_speaker_diarization.kt
  • nodejs-addon-examples/test_offline_speaker_diarization.js
  • nodejs-examples/test-offline-speaker-diarization.js
  • pascal-api-examples/speaker-diarization/main.pas
  • python-api-examples/offline-speaker-diarization.py
  • rust-api-examples/examples/offline_speaker_diarization.rs
  • scripts/dotnet/OfflineSpeakerSegmentationPyannoteModelConfig.cs
  • scripts/go/sherpa_onnx.go
  • scripts/node-addon-api/lib/types.js
  • sherpa-onnx/c-api/c-api.cc
  • sherpa-onnx/c-api/c-api.h
  • sherpa-onnx/c-api/cxx-api.cc
  • sherpa-onnx/c-api/cxx-api.h
  • sherpa-onnx/c-api/docs/speaker-diarization.dox
  • sherpa-onnx/csrc/offline-speaker-segmentation-pyannote-model.cc
  • sherpa-onnx/java-api/src/main/java/com/k2fsa/sherpa/onnx/OfflineSpeakerSegmentationPyannoteModelConfig.java
  • sherpa-onnx/jni/offline-speaker-diarization.cc
  • sherpa-onnx/kotlin-api/OfflineSpeakerDiarization.kt
  • sherpa-onnx/pascal-api/sherpa_onnx.pas
  • sherpa-onnx/python/csrc/offline-speaker-diarization.cc
  • sherpa-onnx/rust/sherpa-onnx-sys/src/offline_speaker_diarization.rs
  • sherpa-onnx/rust/sherpa-onnx/src/offline_speaker_diarization.rs
  • swift-api-examples/SherpaOnnx.swift
  • swift-api-examples/speaker-diarization.swift
  • wasm/speaker-diarization/sherpa-onnx-speaker-diarization.js
  • wasm/speaker-diarization/sherpa-onnx-wasm-main-speaker-diarization.cc

Comment on lines +17 to +19
// Zero uses the default window shift ratio of 0.1. Set a value in (0, 1]
// to change the sliding-window overlap.
config.segmentation.pyannote.window_shift_ratio = 0.1f;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Correct the sentinel and terminology in the C API example.

The C API maps every non-positive value, including negative values, to 0.1 in sherpa-onnx/c-api/c-api.cc Lines 3152-3155. The comment mentions only zero. Also, window_shift_ratio controls the shift. It does not directly specify the overlap.

Proposed documentation fix
-// Zero uses the default window shift ratio of 0.1. Set a value in (0, 1]
-// to change the sliding-window overlap.
+// Zero or a negative value uses the default window shift ratio of 0.1.
+// Set a value in (0, 1] to change the sliding-window shift and resulting overlap.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Zero uses the default window shift ratio of 0.1. Set a value in (0, 1]
// to change the sliding-window overlap.
config.segmentation.pyannote.window_shift_ratio = 0.1f;
// Zero or a negative value uses the default window shift ratio of 0.1.
// Set a value in (0, 1] to change the sliding-window shift and resulting overlap.
config.segmentation.pyannote.window_shift_ratio = 0.1f;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sherpa-onnx/c-api/docs/speaker-diarization.dox` around lines 17 - 19, Update
the comment above config.segmentation.pyannote.window_shift_ratio to state that
non-positive values use the default shift ratio of 0.1, and describe the setting
as controlling the sliding-window shift rather than overlap. Keep the example
value and valid range unchanged.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR exposes OfflineSpeakerSegmentationPyannoteModelConfig::window_shift_ratio (added previously in the C++ core/CLI) through the C API/CXX API and propagates it across existing language bindings and examples so the configuration knob is accessible outside the CLI.

Changes:

  • Extend the C API/CXX API speaker-diarization config structs/conversion to include window_shift_ratio, with C-side sentinel behavior (<= 0 → default 0.1) to preserve zero-initialized callers.
  • Thread the new field through multiple language bindings (Python, Rust, Java/Kotlin/JNI, Go, .NET, Flutter/Dart, Swift, Pascal, Node/WASM/HarmonyOS) and update examples accordingly.
  • Add a debug-gated log in the pyannote segmentation model reporting the computed window shift in samples, and adjust the WASM binding’s layout assumptions.

Reviewed changes

Copilot reviewed 38 out of 39 changed files in this pull request and generated no comments.

Show a summary per file
File Description
wasm/speaker-diarization/sherpa-onnx-wasm-main-speaker-diarization.cc Updates WASM-side struct size assertions and prints the new ratio for debugging.
wasm/speaker-diarization/sherpa-onnx-speaker-diarization.js Extends the WASM JS glue to write windowShiftRatio into the packed config struct and sets typed defaults.
swift-api-examples/speaker-diarization.swift Updates Swift example to pass windowShiftRatio.
swift-api-examples/SherpaOnnx.swift Extends Swift helper API to accept windowShiftRatio (default 0.1).
sherpa-onnx/rust/sherpa-onnx/src/offline_speaker_diarization.rs Adds window_shift_ratio to the safe Rust config and defaults it to 0.1.
sherpa-onnx/rust/sherpa-onnx-sys/src/offline_speaker_diarization.rs Extends the raw Rust FFI struct with the new window_shift_ratio field.
sherpa-onnx/python/csrc/offline-speaker-diarization.cc Exposes window_shift_ratio in the pybind11 config class (default 0.1).
sherpa-onnx/pascal-api/sherpa_onnx.pas Adds WindowShiftRatio to Pascal records, initializes defaults, and passes it into the C config.
sherpa-onnx/kotlin-api/OfflineSpeakerDiarization.kt Adds windowShiftRatio to Kotlin config data class (default 0.1f).
sherpa-onnx/jni/offline-speaker-diarization.cc Reads windowShiftRatio from JVM objects into the native config via JNI macro.
sherpa-onnx/java-api/src/main/java/com/k2fsa/sherpa/onnx/OfflineSpeakerSegmentationPyannoteModelConfig.java Adds windowShiftRatio to Java builder/config object (default 0.1f).
sherpa-onnx/csrc/offline-speaker-segmentation-pyannote-model.cc Adds debug-only logging of the computed shift (in samples).
sherpa-onnx/c-api/docs/speaker-diarization.dox Documents window_shift_ratio usage in the C API docs snippet.
sherpa-onnx/c-api/cxx-api.h Adds window_shift_ratio to the CXX API config with default 0.1f.
sherpa-onnx/c-api/cxx-api.cc Propagates window_shift_ratio from CXX API config into the C config struct.
sherpa-onnx/c-api/c-api.h Adds window_shift_ratio to the C struct, documenting sentinel semantics for <= 0.
sherpa-onnx/c-api/c-api.cc Implements sentinel mapping (<= 0 → 0.1f) during C→C++ config conversion.
scripts/node-addon-api/lib/types.js Updates Node addon JSDoc typedef to include windowShiftRatio default.
scripts/go/sherpa_onnx.go Adds WindowShiftRatio to Go config and passes it to the C struct.
scripts/dotnet/OfflineSpeakerSegmentationPyannoteModelConfig.cs Adds WindowShiftRatio to .NET struct and initializes it to 0.1f.
rust-api-examples/examples/offline_speaker_diarization.rs Updates Rust example to set window_shift_ratio.
python-api-examples/offline-speaker-diarization.py Updates Python example to pass window_shift_ratio.
pascal-api-examples/speaker-diarization/main.pas Updates Pascal example to set WindowShiftRatio.
nodejs-examples/test-offline-speaker-diarization.js Updates NodeJS example config to set windowShiftRatio.
nodejs-addon-examples/test_offline_speaker_diarization.js Updates Node addon example config to set windowShiftRatio.
kotlin-api-examples/test_offline_speaker_diarization.kt Updates Kotlin example to pass windowShiftRatio.
java-api-examples/OfflineSpeakerDiarizationDemo.java Updates Java example to set windowShiftRatio via builder.
harmony-os/SherpaOnnxSpeakerDiarization/entry/src/main/ets/workers/SpeakerDiarizationWorker.ets Sets windowShiftRatio in HarmonyOS worker config and fixes a trailing brace formatting change.
harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/ets/components/NonStreamingSpeakerDiarization.ets Adds windowShiftRatio to the ETS config class.
harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/non-streaming-speaker-diarization.cc Reads windowShiftRatio from N-API object into the native config.
go-api-examples/non-streaming-speaker-diarization/main.go Updates Go example to set WindowShiftRatio.
flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart Extends Flutter FFI struct with windowShiftRatio.
flutter/sherpa_onnx/lib/src/offline_speaker_diarization.dart Copies windowShiftRatio into the native config before creation.
flutter/sherpa_onnx/lib/src/offline_speaker_diarization_config.dart Adds windowShiftRatio to Dart config model, JSON, and toString.
dotnet-examples/offline-speaker-diarization/Program.cs Updates .NET example to set WindowShiftRatio.
dart-api-examples/speaker-diarization/bin/speaker-diarization.dart Updates Dart example to pass windowShiftRatio.
cxx-api-examples/offline-speaker-diarization-cxx-api.cc Updates CXX API example to set window_shift_ratio.
c-api-examples/offline-speaker-diarization-c-api.c Updates C API example and documents the “0 uses default” behavior.
android/SherpaOnnxSpeakerDiarization/app/src/main/java/com/k2fsa/sherpa/onnx/speaker/diarization/SpeakerDiarizationObject.kt Updates Android app wiring to pass windowShiftRatio.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

The C API example called the value the sliding-window overlap. It sets the
shift, and a smaller shift is what produces more overlap, so say that
directly and note the compute cost that comes with it.

@csukuangfj csukuangfj left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants