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

168 lines (167 loc) • 7.26 kB
import type { TTSChunk, TTSOptions, TTSResult, TTSVoice, TTSHandler } from "../../types/index.js"; export declare class GoogleTTSHandler implements TTSHandler { private client; private voicesCache; private static readonly CACHE_TTL_MS; /** * Google Cloud TTS maximum input size. * ~5000 bytes INCLUDING SSML tags. */ private static readonly DEFAULT_MAX_TEXT_LENGTH; /** * Default timeout for Google Cloud TTS API calls (milliseconds) * * Google typically responds within: * - 1–5 seconds for short or normal text * - 5–10 seconds for longer text or Neural2 voices */ private static readonly DEFAULT_API_TIMEOUT_MS; /** * Maximum text length supported by Google Cloud TTS (in bytes). * * NOTE: * Validation against this limit is performed by the shared TTS processor * before invoking provider handlers, not inside this class. */ readonly maxTextLength: number; private readonly credentialsPath; constructor(credentialsPath?: string); /** * Validate that the provider is properly configured * * @returns True if provider can generate TTS */ isConfigured(): boolean; /** * Lazily construct (and cache) the Google Cloud TTS client. * * `@google-cloud/text-to-speech` is an optional dependency: importing it * only happens here, on first actual use, so a handler instance can be * constructed (e.g. during auto-registration at module load) without the * package being installed. */ private getClient; /** * Get available voices for the provider * * Note: This method is optional in the TTSHandler interface, but Google Cloud TTS * fully implements it to provide comprehensive voice discovery capabilities. * * @param languageCode - Optional language filter (e.g., "en-US") * @returns List of available voices */ getVoices(languageCode?: string): Promise<TTSVoice[]>; /** * Generate audio from text using provider-specific TTS API * * @param text - Text or SSML to convert to speech * @param options - TTS configuration options * @returns Audio buffer with metadata */ synthesize(text: string, options: TTSOptions): Promise<TTSResult>; /** * Voice names Google's streaming endpoint will synthesize. * * Streaming is not a property of the API, it is a property of the voice: * every other family is rejected outright with `INVALID_ARGUMENT: * Currently, only Chirp 3: HD voices are supported for streaming * synthesis`. Measured against the live API — `Chirp3-HD` (en-US, en-GB and * de-DE), `Chirp-HD` and `Journey` all stream; `Neural2` and `Studio` are * refused. The locale prefix is required so a malformed name cannot reach * the wire and fail a segment that the buffered path would have served. */ private static readonly STREAMING_VOICE_PATTERN; /** * Sample rate requested for streamed audio, in Hz. * * Reported on every chunk so a consumer can interpret headerless `PCM` * bytes. Google honours the request — 16000 was measured returning * proportionally fewer bytes for the same text — and 24000 matches what * `getSampleRate()` reports for the buffered path. */ private static readonly STREAMING_SAMPLE_RATE_HZ; /** * How long a stream may go without delivering a response before it is * treated as stalled. * * Deliberately an *idle* bound rather than a bound on the whole call, which * is what `DEFAULT_API_TIMEOUT_MS` gives `synthesize()`. Streaming produces * audio at roughly playback speed, so a total bound would fail a long but * perfectly healthy segment purely for being long. */ private static readonly STREAMING_IDLE_TIMEOUT_MS; /** * Map a requested audio format to a streaming audio encoding, or * `undefined` when streaming cannot produce it. * * Only formats with direct wire proof of incremental delivery appear here. * `PCM` delivered 41 reads with the first at 697ms and the body complete at * 6131ms; `OGG_OPUS` delivered 11 reads with the first at 443ms. `MP3` and * `LINEAR16` — both valid for `synthesizeSpeech` — are rejected by the * streaming endpoint as unsupported encodings, so `mp3` and `wav` take the * buffered path. `mp3` being the default format is why a caller has to opt * in to streaming by asking for one of these two. */ private static mapStreamingFormat; /** * Coerce one streaming response into its audio payload, or `undefined` when * it carries none. * * The generated response type says `audioContent` is `Uint8Array | string | * null`, and which one arrives depends on how the transport was configured * — so both are handled rather than trusted. */ private static streamedAudio; /** * Stream one pre-validated segment's audio as Google produces it. * * Returns `undefined` — the contract's "not incrementally deliverable" * signal — unless the voice and the format are both ones the streaming * endpoint was measured to accept, and the text is not SSML. * `StreamingSynthesisInput` has no `ssml` field at all, so markup that * `synthesize()` would honour has to stay on the buffered path rather than * be sent as literal text. * * Every non-empty response is yielded as it arrives and carries `isFinal: * false`. `TTSProcessor` recomputes indexes, cumulative sizes and finality * globally across segments and discards whatever a handler reports, so * labelling the last response here would buy nothing and would cost a * one-response lookahead. */ synthesizeStream(text: string, options?: TTSOptions): AsyncIterable<TTSChunk> | undefined; /** * Extract language code from a Google Cloud voice name * * Example: * "en-US-Neural2-C" -> "en-US" * * @param voiceId - Google Cloud voice identifier * @returns Language code compatible with Google TTS */ private extractLanguageCode; /** * Map application audio format to Google Cloud audio encoding * * @param format - Audio format requested by the caller * @returns Google Cloud AudioEncoding enum value * @throws Error if format is unsupported */ private mapFormat; /** * Detect the voice type from a Google Cloud TTS voice name * * Parses the voice name to identify the underlying voice technology/model type. * Google Cloud TTS offers different voice types with varying quality and pricing. * * @param name - The full Google Cloud voice name (e.g., "en-US-Neural2-C") * @returns The detected voice type * * @example * detectVoiceType("en-US-Neural2-C") // returns "neural" * detectVoiceType("en-US-Wavenet-A") // returns "wavenet" * detectVoiceType("en-US-Standard-B") // returns "standard" * detectVoiceType("en-US-Chirp-A") // returns "chirp" * detectVoiceType("en-US-Journey-D") // returns "unknown" (unrecognized type) */ private detectVoiceType; }