kcode-speaker-extract 0.1.0

Deterministic speaker extraction planning and strict response parsing for Kennedy
Documentation
# kcode-speaker-extract

Deterministic segment-range planning and strict speaker-response parsing. The library performs no I/O or persistence.

## API

```rust
pub struct SegmentPlan {
    pub policy: Key,
    pub source_duration_ms: u64,
    pub segments: Vec<PlannedSegment>,
}

pub struct PlannedSegment {
    pub ordinal: u16,
    pub start_ms: u64,
    pub end_ms: u64,
}

pub struct ExtractionContract {
    pub schema_key: Key,
    pub prompt: &'static str,
    pub response_mime: &'static str,
}

pub enum ExtractionOutcome {
    Scored(ScoredClip),
    Unscorable { reason: String },
}

pub struct ScoredClip {
    pub recording_quality: u8,
    pub speakers: Vec<SpeakerSample>,
}

pub struct SpeakerSample {
    pub speaker_ordinal: u16,
    pub primary_language: Key,
    pub closest_dialect: String,
    pub usable_speech_ms: u32,
    pub features: FeatureVector,
}

pub enum ExtractError {
    ZeroDuration,
    SegmentCountExceedsU16 { required: u128 },
    InvalidJson(String),
    InvalidResponse(&'static str),
}

pub fn plan_segments(duration_ms: u64) -> Result<SegmentPlan, ExtractError>;
pub fn contract() -> &'static ExtractionContract;
pub fn parse(
    response: &str,
    clip_duration_ms: u64,
) -> Result<ExtractionOutcome, ExtractError>;
```

`Key` and `FeatureVector` are re-exported from `kcode-speaker-types`.

## Planning

`plan_segments` returns policy `speaker-segments/1` and rejects zero duration. Durations below 240,000 ms produce one end-exclusive range. Longer sources receive the minimum deterministic number of ranges, each at most 239,999 ms, with exactly 5,000 ms overlap between adjacent ranges. Ranges cover from zero through the source end, differ in length by at most 1 ms, and use contiguous `u16` ordinals. A required count above `u16::MAX` returns `SegmentCountExceedsU16`.

The function computes ranges only; it does not slice or register media.

## Extraction

`contract` returns schema key `gemini-speaker-35/1`, the exact bytes embedded from `prompt-v1.txt`, and MIME `application/json`.

`parse` accepts exactly one scored or whole-clip-unscorable JSON object. Unknown, duplicate, missing, mixed-status, and wrongly typed data are rejected; object key order is irrelevant. Scored responses require at least one speaker whose ordinal equals its zero-based array position. Quality is `0..=100`. Each dialect is 1–128 bytes. Each usable duration is positive and no greater than `clip_duration_ms`; speaker durations may overlap. `primaryLanguage` and the exactly 35 integer features use shared `kcode-speaker-types` validation, including perceived age `0..=120` at index 11 and `0..=100` elsewhere. Unscorable reasons are 1–240 bytes. Validation failures return `InvalidJson` or `InvalidResponse`. No partial or per-speaker abstention form exists.