Skip to content

feat(bindings): who-said-what format parity for Python and C FFI - #29

Merged
ekhodzitsky merged 3 commits into
masterfrom
feat/binding-format-parity
Jul 9, 2026
Merged

ekhodzitsky merged 3 commits into
masterfrom
feat/binding-format-parity

Conversation

@ekhodzitsky

Copy link
Copy Markdown
Owner

Closes the language-parity gap for who-said-what surfaces: the canonical DiarizationResult v1 is now projectable to every format from Python and C, not just the CLI.

C FFI

  • New polyvoice_pipeline_run_format(..., format, ...) — renders the result as JSON / RTTM / SRT / VTT / TXT via a new PolyvoiceFormat (polyvoice_format_t) selector. Same contract as polyvoice_pipeline_run otherwise; RTTM uses the fixed file id audio; unknown formats return InvalidArg before the pipeline is touched.
  • Existing ABI untouched (additive only). include/polyvoice.h and the module contract updated (also fixed stale polyvoice_pipeline_free naming → polyvoice_pipeline_destroy, ABI v2 → v3).

Python

  • Typed DiarizationResult: from_json() / to_json() / to_rttm(file_id) / to_srt() / to_vtt() / to_txt() / to_dict() + turns / speakers / num_speakers / schema_version getters. Pipeline.run_result() returns it; Pipeline.run() (plain dict) unchanged.
  • .pyi stubs + py.typed marker ship in the wheel; __version__ now reads installed metadata (was a stale hardcoded string).
  • to_rttm validates file_id (RTTM is whitespace-delimited — a space would silently corrupt columns).

Format writers (shared by CLI / FFI / Python)

  • WebVTT transcribed cues now use the standard voice span <v SPEAKER_NN>text</v> (diarization-only cues keep the bare label).
  • Cue text is sanitized for single-line payloads (newlines collapse, literal --> broken up) and VTT-escaped (& → &amp;, < → &lt;) — hostile/ASR text can no longer break block structure.

Docs

  • examples/agent_quickstart.md — copy-paste integration paths (CLI --json, MCP, Python typed result, FFI formats, who-said-what from source).
  • python README: honest collar-disclosed DER row (replaces a stale headline number) + new API listed.

Verification

  • cargo nextest run --all-features: 419 passed.
  • cargo clippy --all-targets --all-features -- -D warnings: clean.
  • Model-gated ffi_run_format_renders_every_format (all five formats + unknown-format rejection on a valid handle) passes on real cached models.
  • maturin develop + pytest: 13 passed (golden projections for all five formats, JSON round-trip, v1-consumer compat, file_id validation).
  • Adversarially reviewed (two lenses + refutation pass); all confirmed findings fixed in this diff.

🤖 Generated with Claude Code

ekhodzitsky and others added 2 commits June 23, 2026 14:44
- C FFI: polyvoice_pipeline_run_format(..., format, ...) renders JSON/RTTM/
  SRT/VTT/TXT via a new PolyvoiceFormat selector; the existing
  polyvoice_pipeline_run ABI is untouched. Header + module contract updated.
- Python: typed DiarizationResult (from_json / to_json / to_rttm / to_srt /
  to_vtt / to_txt / to_dict + turns/speakers getters) and
  Pipeline.run_result(); .pyi stubs + py.typed ship in the wheel;
  __version__ now reflects installed package metadata.
- WebVTT: transcribed cues use the standard voice span <v SPEAKER_NN>text</v>;
  cue text is sanitized for single-line payloads (newlines, "-->") and
  spec-escaped (& <) across SRT/VTT.
- Python to_rttm validates file_id (RTTM is whitespace-delimited).
- examples/agent_quickstart.md: machine-readable integration paths; python
  README gets the honest collar-disclosed DER row.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov-commenter

codecov-commenter commented Jul 9, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 76.05634% with 34 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/ffi/mod.rs 67.30% 34 Missing ⚠️

📢 Thoughts on this report? Let us know!

…st fresh advisories

anyhow 1.0.102 -> 1.0.103 (unsound Error::downcast_mut, RUSTSEC-2026-0190);
crossbeam-epoch 0.9.18 -> 0.9.20 (invalid pointer deref in fmt::Pointer,
RUSTSEC-2026-0204). Lockfile-only, both semver-compatible.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ekhodzitsky
ekhodzitsky merged commit 9bbcdcd into master Jul 9, 2026
44 checks passed
@ekhodzitsky
ekhodzitsky deleted the feat/binding-format-parity branch July 9, 2026 19:31
ekhodzitsky added a commit that referenced this pull request Jul 31, 2026
* chore: ignore local git worktrees

* feat(bindings): who-said-what format parity for Python and C FFI

- C FFI: polyvoice_pipeline_run_format(..., format, ...) renders JSON/RTTM/
  SRT/VTT/TXT via a new PolyvoiceFormat selector; the existing
  polyvoice_pipeline_run ABI is untouched. Header + module contract updated.
- Python: typed DiarizationResult (from_json / to_json / to_rttm / to_srt /
  to_vtt / to_txt / to_dict + turns/speakers getters) and
  Pipeline.run_result(); .pyi stubs + py.typed ship in the wheel;
  __version__ now reflects installed package metadata.
- WebVTT: transcribed cues use the standard voice span <v SPEAKER_NN>text</v>;
  cue text is sanitized for single-line payloads (newlines, "-->") and
  spec-escaped (& <) across SRT/VTT.
- Python to_rttm validates file_id (RTTM is whitespace-delimited).
- examples/agent_quickstart.md: machine-readable integration paths; python
  README gets the honest collar-disclosed DER row.

* chore: rustfmt the new FFI code; update anyhow and crossbeam-epoch past fresh advisories

anyhow 1.0.102 -> 1.0.103 (unsound Error::downcast_mut, RUSTSEC-2026-0190);
crossbeam-epoch 0.9.18 -> 0.9.20 (invalid pointer deref in fmt::Pointer,
RUSTSEC-2026-0204). Lockfile-only, both semver-compatible.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ekhodzitsky added a commit that referenced this pull request Jul 31, 2026
* chore: ignore local git worktrees

* feat(bindings): who-said-what format parity for Python and C FFI

- C FFI: polyvoice_pipeline_run_format(..., format, ...) renders JSON/RTTM/
  SRT/VTT/TXT via a new PolyvoiceFormat selector; the existing
  polyvoice_pipeline_run ABI is untouched. Header + module contract updated.
- Python: typed DiarizationResult (from_json / to_json / to_rttm / to_srt /
  to_vtt / to_txt / to_dict + turns/speakers getters) and
  Pipeline.run_result(); .pyi stubs + py.typed ship in the wheel;
  __version__ now reflects installed package metadata.
- WebVTT: transcribed cues use the standard voice span <v SPEAKER_NN>text</v>;
  cue text is sanitized for single-line payloads (newlines, "-->") and
  spec-escaped (& <) across SRT/VTT.
- Python to_rttm validates file_id (RTTM is whitespace-delimited).
- examples/agent_quickstart.md: machine-readable integration paths; python
  README gets the honest collar-disclosed DER row.

* chore: rustfmt the new FFI code; update anyhow and crossbeam-epoch past fresh advisories

anyhow 1.0.102 -> 1.0.103 (unsound Error::downcast_mut, RUSTSEC-2026-0190);
crossbeam-epoch 0.9.18 -> 0.9.20 (invalid pointer deref in fmt::Pointer,
RUSTSEC-2026-0204). Lockfile-only, both semver-compatible.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants