UNPKG

@juspay/neurolink

Version:

The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002

82 lines (81 loc) • 3.92 kB
/** * Energy-gated endpointer for client-side streaming of batch STT engines. * * Pure and synchronous: feed it float samples at any input rate, get back * utterance start / end / drop events. It knows nothing about engines; the * chunked adapter decides what to transcribe and when. * * The rules and their constants were measured on live microphones and on a * 45 s three-speaker meeting slice, where they recover 155 of the 156 words a * batch transcription of the whole file finds (a plain fixed-threshold gate * recovered 125): * * - Work on 20 ms blocks. * - The noise floor is a minimum statistic — the quietest block of the last * 1.5 s — allowed to rise by at most ~2× per second and never below 0.0005. * Because it follows the quietest block, a loud talker can never raise it * enough to push a quieter second speaker below the gate. * - Hysteresis: speech starts above `max(onsetRms, floor × 3)` and is * sustained above `max(onsetRms × 0.58, floor × 1.8)`, so soft word endings * are kept inside the utterance instead of counting as silence. * - `prerollMs` of audio before the onset is kept, so the first consonant is * not clipped. * - An utterance ends after `endSilenceMs` without sustained speech. One with * less than `minSpeechMs` of speech is a cough and is dropped — unless a * pass already heard words in it, which must never be lost. * - A long turn (`softCutSeconds`) ends at the next ≥ 320 ms gap; a turn with * no gap at all is hard-cut at `maxUtteranceSeconds` at the quietest block * of the last 3 s, and the remainder becomes the start of the next * utterance, so no audio falls between the two. * * @module voice/streaming/endpointer */ import type { STTEndpointerConfig, STTEndpointerEvent, STTEndpointerUtterance, STTStreamingOptions } from "../../types/index.js"; /** Sample rate every engine pass receives. */ export declare const ENGINE_SAMPLE_RATE = 16000; /** Defaults of `STTStreamingOptions` that the endpointer reads. */ export declare const ENDPOINTER_DEFAULTS: { readonly endSilenceMs: 750; readonly softCutSeconds: 16; readonly maxUtteranceSeconds: 28; readonly onsetRms: 0.006; readonly prerollMs: 350; readonly minSpeechMs: 250; }; /** Applies the defaults to caller tuning; non-finite or non-positive values fall back. */ export declare function resolveEndpointerConfig(options: STTStreamingOptions | undefined, inputRate: number): STTEndpointerConfig; export declare function rmsOf(samples: Float32Array): number; /** Linear-interpolation resampler to 16 kHz; returns the input untouched when it already is. */ export declare function resampleTo16k(samples: Float32Array, inputRate: number): Float32Array; export declare class Endpointer { readonly config: STTEndpointerConfig; private readonly blockLen; private block; private blockFill; private noise; private readonly noiseWin; private pre; private preLen; private utt; private seq; /** Input samples that went through the gate so far: the audio clock, in whole blocks. */ private consumed; constructor(config: STTEndpointerConfig); /** The utterance being built, if speech is in progress. */ get current(): STTEndpointerUtterance | null; /** Seconds of input consumed so far. */ get audioSeconds(): number; /** Feeds samples at the input rate; returns the events they caused, in order. */ push(samples: Float32Array): STTEndpointerEvent[]; /** * Ends the stream: a partial block is folded into the open utterance, which * is then ended (`flush`) — or dropped when it is a cough nobody heard. */ flush(): STTEndpointerEvent[]; /** The utterance's audio at 16 kHz. */ pcm16k(u: STTEndpointerUtterance): Float32Array; private sustainThreshold; private newUtterance; private onBlock; private hardCut; }