import { Observable } from 'rxjs'; import type { CacheOptions } from './legacy-phrase'; import type { TtsHandle } from './tts-handle'; /** * How TTS audio is chunked and fed to the mixer. * * - **`sentence`**: split on sentence boundaries and start synthesis per sentence (default). * - **`streaming`**: incremental chunks as they arrive, only for streaming-capable vendors * (for non-streaming vendors the runtime falls back to sentence handling). * - **`full`**: accumulate the whole input and synthesize it as one segment after the input completes. */ export type TtsStrategy = 'sentence' | 'streaming' | 'full'; /** * TTS vendor alias understood by ScriptEngine. * * Dedicated TTS connectors are selected by aliases such as **`"elevenlabs"`**, * **`"google"`**, and **`"voctiv"`**. The default TTS path can also accept * compatible aliases such as **`"azure"`** or **`"neuro_v3"`**, depending on * deployment configuration. The open string form keeps the SDK compatible with * deployment-specific aliases. */ export type TtsVendor = 'elevenlabs' | 'google' | 'azure' | 'yandex' | 'sber' | 'viettel' | 'voctiv' | 'neuro' | 'neuro_v2' | 'neuro_v3' | 'neuro_service' | 'async_azure' | 'stc' | (string & Record); /** * Options for {@link import('./media-channel').ChannelAudio.say}, * {@link import('./media-channel').ChannelAudio.play}, and * {@link import('./media-channel').ChannelAudio.presay}. * * ### Voctiv platform + `key_storage` (TTS credentials) * * Same idea as ASR: when Voctiv platform compatibility is on and keys are loaded from PostgreSQL, **`authentication_data`** * contains **`legacyTtsKeysByName`**, keyed by **`key_storage.name`** for **this dialog’s agent * and company** (agent is implied by the dialog — no UUID in the script). * * - **`name`** on **`PlayOptions`**: select that row’s flat credentials for this synthesis. * - Alternative: **`ttsConfig.name`** (the **`name`** entry is stripped before vendor params). * - If omitted, **`defaultTtsName`** on the channel (Omni / route) applies. * - Otherwise credentials come from **`authentication_data.tts.<engine>`** for the resolved vendor. * * ### Note on the field **`name`** * * This **`name`** is **not** the same as {@link import('./media-channel').LlmOptions.name} * (speaker label for LLM). It only selects the TTS key row when LE key catalogs (`legacyTtsKeysByName`, etc.) are present. */ export interface PlayOptions { /** * Mixer queue index **0–4**. Use separate queues to layer music, earcons, and agent TTS * so **`stop(queue)`** does not cut unrelated audio. * * SIP/WS runtimes pass this to the mixer; invalid indices are not part of the public contract. * @defaultValue 0 */ queue?: number; /** * Stable id for this queue item — used with **`remove`**, debug UIs, and completion tracking. * Should be unique per logical utterance if you need to cancel a specific playback. * * For sentence-split TTS the runtime creates item aliases by suffixing * this value (`alias-0`, `alias-1`, ...). For raw `play()` and direct streaming TTS, * the item uses this alias exactly. */ alias?: string; /** When `true`, the item restarts after it finishes until **`stop`** / **`remove`**. */ loop?: boolean; /** Milliseconds of silence between loop iterations (if **`loop`**). */ loopDelayMs?: number; /** * Linear gain for the whole mixer queue **0.0** (mute) – **1.0** (unity). * * This is not per-item volume: setting it on one `say()`/`play()` changes the queue * volume for subsequent items until it is changed again. */ volume?: number; /** Chunking strategy for TTS; see {@link TtsStrategy}. */ ttsStrategy?: TtsStrategy; /** * Force a specific TTS vendor for this call, overriding **`channel.params.ttsVendor`**. * Ignored for **`play()`** when the source is raw audio (no synthesis). * When {@link tts} is set, the handle's resolved vendor/config take precedence. */ ttsVendor?: TtsVendor; /** * Pre-warmed TTS session from {@link import('./media-channel').MediaChannel.createTts}. * Reuses the cached connector / streaming WebSocket so synthesis skips a fresh SSL handshake. * When set, the handle's resolved vendor and connector config are used (overrides * {@link ttsVendor} / {@link name} / {@link ttsConfig} for credential resolution). */ tts?: TtsHandle; /** * logic-executor **`key_storage.name`**: use **`authentication_data.legacyTtsKeysByName[name]`** * for credentials. Overrides **`defaultTtsName`** on the channel. */ name?: string; /** * Parameters passed to the TTS connector (voice id, model, `output_format`, nested JSON, …). * Primitives are stringified; objects and arrays are JSON-serialized. Merged after channel * defaults and catalog credentials; later wins. The key **`name`** is reserved for the * storage-row selector and is removed before sending to the vendor. */ ttsConfig?: Record; /** * Enable TTS result caching for `say()`. * * - **`true`** — read/write TTS file cache only (Redis + filesystem + `tts_cache` table or * LE `_cache` phrase in legacy mode). * - **`{ phraseName?, flag?, language? }`** — TTS cache **plus** persist into `record_phrase` / * `record_phrase_file` on the Voctiv platform so {@link import('./define-script').PlatformApi.getRecords} * can retrieve the audio later. `phraseName` defaults to `_cache`. */ cache?: true | CacheOptions; } /** * Options for {@link ChannelAudio.presay}. * * Caching and persistence to `record_phrase` always happen in legacy mode. * Use `cache` only to override the default phrase name / flag / language. */ export interface PresayOptions { ttsVendor?: TtsVendor; /** * Pre-warmed TTS session from {@link import('./media-channel').MediaChannel.createTts}. * Same reuse semantics as {@link PlayOptions.tts}. */ tts?: TtsHandle; name?: string; ttsConfig?: Record; ttsStrategy?: TtsStrategy; /** Override persist name/flag/language. Defaults to `{ phraseName: '_cache' }`. */ cache?: CacheOptions; } /** * Options for {@link ChannelAudio.preload}. * * In legacy mode the decoded PCM is always persisted to `record_phrase`. * Use `cache` only to override the default phrase name / flag / language. */ export interface PreloadOptions { /** Override persist name/flag/language. Defaults to `{ phraseName: '_cache' }`. */ cache?: CacheOptions; } /** * Per-queue mixer control: volume, observability, and manual removal. * * Obtain via **`channel.audio.queue(index)`**. */ export interface MixerQueueControl { /** Queue index **0–4** (matches **`PlayOptions.queue`**). */ readonly index: number; /** Current linear volume **0.0–1.0**; assign to change gain for this entire queue. */ volume: number; /** Emits **`alias`** when an item in this queue starts playing. */ readonly itemStarted$: Observable; /** Emits **`alias`** when an item finishes, is removed, or is skipped by queue clear. */ readonly itemFinished$: Observable; /** Emits whenever the queue becomes empty after all pending/current items are gone * and their PCM has been emitted to the mixer output (not merely dequeued). */ readonly queueEmpty$: Observable; /** * Remove a single item by **`alias`**. * @param alias - Same string passed in **`PlayOptions.alias`** for that item. */ remove(alias: string): void; /** Drop all queued and current items on this queue. */ clear(): void; } //# sourceMappingURL=mixer.d.ts.map