/** * Output formats accepted by OpenRouter's `/audio/speech` endpoint * (April 2026 docs). Only `mp3` and `pcm` are supported — narrower than * OpenAI's direct API which also exposes opus/aac/flac/wav. */ export type TtsResponseFormat = 'mp3' | 'pcm'; export interface TtsClientConfig { apiKey: string; /** Override base URL — useful for tests or pointing at OpenAI directly. Default: OpenRouter. */ baseUrl?: string; /** Default model for this client. Default: `openai/gpt-4o-mini-tts`. */ defaultModel?: string; /** Per-request timeout. Default: 30s. */ timeoutMs?: number; /** Number of retry attempts on transient HTTP failures (5xx, network). Default: 2. */ maxRetries?: number; } export interface TtsRequest { /** Text to synthesize. The provider rejects empty strings; keep chunks under ~4k chars. */ text: string; /** Voice handle, e.g. 'nova', 'alloy', 'echo'. Provider-specific. */ voice: string; /** Optional model override. Defaults to client.defaultModel. */ model?: string; /** Output container/codec. Default: 'mp3'. */ format?: TtsResponseFormat; /** Speaking-rate multiplier (0.25..4.0). Provider may clamp. Default: 1.0. */ speed?: number; /** Optional abort signal for cancellation. */ signal?: AbortSignal; } export interface TtsResponse { /** Raw audio bytes in the requested format. */ audioBuffer: Buffer; /** Mime type matching the requested format. */ mimeType: string; /** Audio duration in ms, measured via ffprobe on the produced buffer. */ durationMs: number; /** Effective model used. */ model: string; /** Voice used. */ voice: string; /** * OpenRouter generation id for async cost resolution via /api/v1/generation. * Sourced from the `x-request-id` header. May be null if the provider does * not return one. */ generationId: string | null; } export declare class TtsError extends Error { readonly status?: number | undefined; readonly providerBody?: string | undefined; constructor(message: string, status?: number | undefined, providerBody?: string | undefined); } /** * POST a single TTS chunk to the configured provider, retry on 5xx / network * errors up to `maxRetries`, then probe the resulting buffer for duration. * * Throws `TtsError` (with HTTP status when available) on permanent failure. */ export declare function generateTtsChunk(config: TtsClientConfig, request: TtsRequest): Promise; /** * Mutable indirection used by `generateTtsChunk` to find its dependencies. * Tests reach into this object to swap `probeAudioDurationMs` for a fake * (ESM exports are immutable bindings, so a plain `vi.spyOn` on the named * export does not affect the in-module reference). */ export declare const ttsTestHooks: { probeAudioDurationMs: (audioBuffer: Buffer, format: TtsResponseFormat) => Promise; }; /** * Write the buffer to a tempfile, run ffprobe to get the format duration, * clean up. Errors propagate (caller can wrap as TtsError if needed). * * Exported under both the legacy name (`probeAudioDurationMs`) and via the * `ttsTestHooks` indirection so unit tests can override it. */ export declare const probeAudioDurationMs: typeof defaultProbeAudioDurationMs; declare function defaultProbeAudioDurationMs(audioBuffer: Buffer, format: TtsResponseFormat): Promise; export {};