@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
TypeScript
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;
}