Skip to main content
The SDK follows semantic versioning. The authoritative SDK changelog lives in CHANGELOG.md.

API — streaming finals: faster, and without the jitter

  • Finals arrive faster, at every utterance length, with no outliers. Decode input shapes are now drawn from a small pre-warmed set and an endpoint decode takes priority over pending partial work on the GPU, so no live request ever pays first-use kernel planning. Measured from Almaty against production at a 200 ms end-of-utterance threshold: finals went from a 539 ms median with a 1,034 ms tail to ~420 ms with a 511 ms worst case across 32 consecutive finals. Transcription accuracy re-measured through the full streaming path: unchanged (0.5 pp better on FLEURS Kazakh).
  • Repeat connections shake hands faster. Successful key authorization is reused for five minutes and no longer blocks other sockets on the same container; a warm reconnect measures ~0.6–0.7 s.
  • Cold starts restore from a GPU memory snapshot instead of booting from scratch: the first connection after an idle period now waits ~15 s (from ~20–25 s), and every boot — fresh or restored — re-warms its decode shapes before serving, so a just-started container has no first-request penalty.

API — live streaming transcription

  • New WebSocket endpoint wss://geko--seta-stream-streamer-api.modal.run/v1/stream transcribes speech as it is spoken, emitting partial results while someone is still talking and final ones that are never revised. See streaming.
  • Runs as a separate service from file transcription, so the two scale independently and a streaming incident cannot take /v1/transcribe down with it. Same API key, same credit balance.
  • Audio is PCM16-LE, mono, 16 kHz. Nothing is resampled server-side.
  • **Priced at 6 credits/audio-second (0.864/audiohour),against2.5(0.864/audio-hour)**, against 2.5 (0.36/audio-hour) for files. Keeping a partial transcript current re-decodes uncommitted audio on every update, so a second of speech passes through the model roughly six times. If you have a file, POST /v1/transcribe is more accurate and a third of the price.
  • Billed on audio accepted, once, when the socket closes — including on an abrupt disconnect.

SDK 0.6.0

  • geko.stt.stream() opens a session: send() audio, iterate it for events, stop() when the audio ends. New SttStream export and SttStream* event types.
  • geko.stt.estimateStreamCredits(seconds) prices a stream before you spend it.
  • Still zero-dependency: uses the platform WebSocket. Node 20 has none (stable in Node 22) — upgrade, or pass { webSocket }.
  • openTimeout defaults to 60s, because the service scales to zero and a first connection after idle waits ~15–25s for a cold start.

API — word-level timestamps

  • POST /v1/transcribe?timestamps=true now also returns words ({ word, start, end }) and segments ({ id, text, start, end }), in seconds from the start of the audio. See word-level timestamps.
  • Free. The alignment is a by-product of the same CTC decode pass; billing is unchanged at ceil(audio_seconds × 2.5).
  • Opt-in. Both fields are absent unless requested, so no existing caller’s response shape changes.
  • Long audio is split at pauses before decoding, and each piece’s times are shifted back into the timeline of the whole file — so start/end are always measured from the beginning of your audio.
  • OpenAI-compatible endpoint: response_format=srt and vtt now return real subtitles instead of 400, and verbose_json returns populated segments and words.

SDK 0.5.0

  • transcribe({ timestamps: true }) surfaces words and segments. New exported types Word and TranscriptSegment.
  • toSubtitles(transcription, "srt" | "vtt") — pure formatter, exported standalone and as geko.stt.toSubtitles(). Uses segments, because one cue per word is unwatchable.
  • CLI: transcribe --words prints start<TAB>end<TAB>word; --srt / --vtt print subtitles.

SDK 0.4.0

  • Speech-to-text: geko.stt.transcribe({ audio }) or { url } → the transcript plus timing and the credits actually charged. Backed by seta-kk-ru-v2, which handles Kazakh/Russian code-switching at 8.71% WER on the KSC2 official test set, where Whisper large-v3 scores 44.95% on the same audio. See accuracy.
  • There is deliberately no language parameter — both alphabets share one 70-character output vocabulary, so the model is never told which language to expect. Transcripts are lowercase and unpunctuated because that vocabulary contains neither.
  • geko.stt.models() lists what the endpoint serves. geko.stt.estimateCredits(seconds) prices a file with no request — ceil(seconds × 2.5), i.e. $0.36/audio-hour.
  • One API key, one balance, both services. TTS and STT are separately scaled GPU services on two hosts; the client hides that. New sttBaseUrl option (plus GEKO_STT_BASE_URL and --stt-base-url) if you need to point it elsewhere.
  • CLI: gekoai transcribe <file> and gekoai transcribe --url <url>. The transcript goes to stdout and the cost line to stderr, so > transcript.txt captures only text.
  • Audio uploads as an octet-stream rather than multipart, which keeps the body replayable — so transcriptions keep the existing retry-on-5xx behavior.

SDK 0.3.0

  • Streaming: geko.tts.stream() — an async iterable yielding one WAV chunk per sentence for lower time-to-first-audio on long text. Consumes the framed wav-frames-v1 protocol.
  • No retries on streams (a consumed stream can’t be replayed); AbortSignal and per-call timeout still apply.

SDK 0.2.0

  • CLI: npx @gekoai/sdk say | voices | models. See CLI.
  • Clarified browser usage (proxy through your server; keep your key secret).

SDK 0.1.0

  • Initial release: Geko client with tts.create(), tts.voices(), models(), health(). Zero runtime dependencies, dual ESM + CommonJS, typed errors, timeouts, and automatic retries.

API