@livekit/agents 1.0.25 → 1.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/dist/connection_pool.cjs +242 -0
  2. package/dist/connection_pool.cjs.map +1 -0
  3. package/dist/connection_pool.d.cts +123 -0
  4. package/dist/connection_pool.d.ts +123 -0
  5. package/dist/connection_pool.d.ts.map +1 -0
  6. package/dist/connection_pool.js +218 -0
  7. package/dist/connection_pool.js.map +1 -0
  8. package/dist/connection_pool.test.cjs +256 -0
  9. package/dist/connection_pool.test.cjs.map +1 -0
  10. package/dist/connection_pool.test.js +255 -0
  11. package/dist/connection_pool.test.js.map +1 -0
  12. package/dist/index.cjs +2 -0
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +1 -0
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +1 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/inference/tts.cjs +172 -58
  20. package/dist/inference/tts.cjs.map +1 -1
  21. package/dist/inference/tts.d.cts +3 -1
  22. package/dist/inference/tts.d.ts +3 -1
  23. package/dist/inference/tts.d.ts.map +1 -1
  24. package/dist/inference/tts.js +173 -59
  25. package/dist/inference/tts.js.map +1 -1
  26. package/dist/tts/stream_adapter.cjs +6 -3
  27. package/dist/tts/stream_adapter.cjs.map +1 -1
  28. package/dist/tts/stream_adapter.d.cts +1 -1
  29. package/dist/tts/stream_adapter.d.ts +1 -1
  30. package/dist/tts/stream_adapter.d.ts.map +1 -1
  31. package/dist/tts/stream_adapter.js +6 -3
  32. package/dist/tts/stream_adapter.js.map +1 -1
  33. package/dist/tts/tts.cjs +26 -15
  34. package/dist/tts/tts.cjs.map +1 -1
  35. package/dist/tts/tts.d.cts +7 -4
  36. package/dist/tts/tts.d.ts +7 -4
  37. package/dist/tts/tts.d.ts.map +1 -1
  38. package/dist/tts/tts.js +26 -15
  39. package/dist/tts/tts.js.map +1 -1
  40. package/dist/utils.cjs +20 -0
  41. package/dist/utils.cjs.map +1 -1
  42. package/dist/utils.d.cts +7 -0
  43. package/dist/utils.d.ts +7 -0
  44. package/dist/utils.d.ts.map +1 -1
  45. package/dist/utils.js +19 -0
  46. package/dist/utils.js.map +1 -1
  47. package/dist/voice/agent_activity.cjs +3 -1
  48. package/dist/voice/agent_activity.cjs.map +1 -1
  49. package/dist/voice/agent_activity.d.ts.map +1 -1
  50. package/dist/voice/agent_activity.js +3 -1
  51. package/dist/voice/agent_activity.js.map +1 -1
  52. package/dist/voice/agent_session.cjs +6 -1
  53. package/dist/voice/agent_session.cjs.map +1 -1
  54. package/dist/voice/agent_session.d.ts.map +1 -1
  55. package/dist/voice/agent_session.js +6 -1
  56. package/dist/voice/agent_session.js.map +1 -1
  57. package/dist/voice/avatar/datastream_io.cjs +1 -1
  58. package/dist/voice/avatar/datastream_io.cjs.map +1 -1
  59. package/dist/voice/avatar/datastream_io.js +1 -1
  60. package/dist/voice/avatar/datastream_io.js.map +1 -1
  61. package/dist/voice/background_audio.cjs +77 -37
  62. package/dist/voice/background_audio.cjs.map +1 -1
  63. package/dist/voice/background_audio.d.cts +10 -3
  64. package/dist/voice/background_audio.d.ts +10 -3
  65. package/dist/voice/background_audio.d.ts.map +1 -1
  66. package/dist/voice/background_audio.js +78 -37
  67. package/dist/voice/background_audio.js.map +1 -1
  68. package/dist/voice/index.cjs +1 -0
  69. package/dist/voice/index.cjs.map +1 -1
  70. package/dist/voice/index.d.cts +1 -0
  71. package/dist/voice/index.d.ts +1 -0
  72. package/dist/voice/index.d.ts.map +1 -1
  73. package/dist/voice/index.js +1 -0
  74. package/dist/voice/index.js.map +1 -1
  75. package/dist/voice/io.cjs +10 -1
  76. package/dist/voice/io.cjs.map +1 -1
  77. package/dist/voice/io.d.cts +18 -1
  78. package/dist/voice/io.d.ts +18 -1
  79. package/dist/voice/io.d.ts.map +1 -1
  80. package/dist/voice/io.js +10 -1
  81. package/dist/voice/io.js.map +1 -1
  82. package/dist/voice/recorder_io/recorder_io.cjs +1 -1
  83. package/dist/voice/recorder_io/recorder_io.cjs.map +1 -1
  84. package/dist/voice/recorder_io/recorder_io.js +1 -1
  85. package/dist/voice/recorder_io/recorder_io.js.map +1 -1
  86. package/dist/voice/room_io/_output.cjs +1 -1
  87. package/dist/voice/room_io/_output.cjs.map +1 -1
  88. package/dist/voice/room_io/_output.js +1 -1
  89. package/dist/voice/room_io/_output.js.map +1 -1
  90. package/dist/voice/transcription/synchronizer.cjs +1 -1
  91. package/dist/voice/transcription/synchronizer.cjs.map +1 -1
  92. package/dist/voice/transcription/synchronizer.js +1 -1
  93. package/dist/voice/transcription/synchronizer.js.map +1 -1
  94. package/dist/worker.cjs +4 -6
  95. package/dist/worker.cjs.map +1 -1
  96. package/dist/worker.d.ts.map +1 -1
  97. package/dist/worker.js +4 -6
  98. package/dist/worker.js.map +1 -1
  99. package/package.json +3 -3
  100. package/src/connection_pool.test.ts +346 -0
  101. package/src/connection_pool.ts +307 -0
  102. package/src/index.ts +1 -0
  103. package/src/inference/tts.ts +206 -65
  104. package/src/tts/stream_adapter.ts +10 -3
  105. package/src/tts/tts.ts +41 -18
  106. package/src/utils.ts +25 -0
  107. package/src/voice/agent_activity.ts +7 -1
  108. package/src/voice/agent_session.ts +6 -1
  109. package/src/voice/avatar/datastream_io.ts +1 -1
  110. package/src/voice/background_audio.ts +95 -55
  111. package/src/voice/index.ts +1 -0
  112. package/src/voice/io.ts +24 -0
  113. package/src/voice/recorder_io/recorder_io.ts +1 -1
  114. package/src/voice/room_io/_output.ts +1 -1
  115. package/src/voice/transcription/synchronizer.ts +1 -1
  116. package/src/worker.ts +4 -7
@@ -25,6 +25,7 @@ module.exports = __toCommonJS(tts_exports);
25
25
  var import_ws = require("ws");
26
26
  var import_exceptions = require("../_exceptions.cjs");
27
27
  var import_audio = require("../audio.cjs");
28
+ var import_connection_pool = require("../connection_pool.cjs");
28
29
  var import_log = require("../log.cjs");
29
30
  var import_stream_channel = require("../stream/stream_channel.cjs");
30
31
  var import_tokenize = require("../tokenize/index.cjs");
@@ -41,6 +42,7 @@ const DEFAULT_LANGUAGE = "en";
41
42
  class TTS extends import_tts.TTS {
42
43
  opts;
43
44
  streams = /* @__PURE__ */ new Set();
45
+ pool;
44
46
  #logger = (0, import_log.log)();
45
47
  constructor(opts) {
46
48
  const sampleRate = (opts == null ? void 0 : opts.sampleRate) ?? DEFAULT_SAMPLE_RATE;
@@ -92,6 +94,14 @@ class TTS extends import_tts.TTS {
92
94
  apiSecret: lkApiSecret,
93
95
  modelOptions
94
96
  };
97
+ this.pool = new import_connection_pool.ConnectionPool({
98
+ connectCb: (timeout) => this.connectWs(timeout),
99
+ closeCb: (ws) => this.closeWs(ws),
100
+ maxSessionDuration: 3e5,
101
+ markRefreshedOnGet: true,
102
+ connectTimeout: 1e4
103
+ // 10 seconds default
104
+ });
95
105
  }
96
106
  get label() {
97
107
  return "inference.TTS";
@@ -135,6 +145,7 @@ class TTS extends import_tts.TTS {
135
145
  if (this.opts.voice) params.voice = this.opts.voice;
136
146
  if (this.opts.model) params.model = this.opts.model;
137
147
  if (this.opts.language) params.language = this.opts.language;
148
+ this.#logger.debug({ url }, "inference.TTS creating new websocket connection (pool miss)");
138
149
  const socket = await (0, import_utils2.connectWs)(url, headers, timeout);
139
150
  socket.send(JSON.stringify(params));
140
151
  return socket;
@@ -142,23 +153,25 @@ class TTS extends import_tts.TTS {
142
153
  async closeWs(ws) {
143
154
  await ws.close();
144
155
  }
156
+ prewarm() {
157
+ this.pool.prewarm();
158
+ }
145
159
  async close() {
146
160
  for (const stream of this.streams) {
147
161
  await stream.close();
148
162
  }
149
163
  this.streams.clear();
164
+ await this.pool.close();
150
165
  }
151
166
  }
152
167
  class SynthesizeStream extends import_tts.SynthesizeStream {
153
168
  opts;
154
169
  tts;
155
- connOptions;
156
170
  #logger = (0, import_log.log)();
157
171
  constructor(tts, opts, connOptions) {
158
172
  super(tts, connOptions);
159
173
  this.opts = opts;
160
174
  this.tts = tts;
161
- this.connOptions = connOptions;
162
175
  }
163
176
  get label() {
164
177
  return "inference.SynthesizeStream";
@@ -167,25 +180,23 @@ class SynthesizeStream extends import_tts.SynthesizeStream {
167
180
  this.opts = { ...this.opts, ...opts };
168
181
  }
169
182
  async run() {
170
- let ws = null;
171
183
  let closing = false;
172
- let finalReceived = false;
173
184
  let lastFrame;
174
185
  const sendTokenizerStream = new import_tokenize.basic.SentenceTokenizer().stream();
175
186
  const eventChannel = (0, import_stream_channel.createStreamChannel)();
176
187
  const requestId = (0, import_utils.shortuuid)("tts_request_");
177
- const resourceCleanup = () => {
188
+ const inputSentEvent = new import_utils.Event();
189
+ const completionFuture = new import_utils.Future();
190
+ const resourceCleanup = async () => {
178
191
  if (closing) return;
179
192
  closing = true;
180
193
  sendTokenizerStream.close();
181
- eventChannel.close();
182
- ws == null ? void 0 : ws.removeAllListeners();
183
- ws == null ? void 0 : ws.close();
194
+ await eventChannel.close();
184
195
  };
185
- const sendClientEvent = async (event) => {
186
- if (this.abortController.signal.aborted || closing) return;
196
+ const sendClientEvent = async (event, ws, signal) => {
197
+ if (signal.aborted || closing) return;
187
198
  const validatedEvent = await import_api_protos.ttsClientEventSchema.parseAsync(event);
188
- if (!ws || ws.readyState !== import_ws.WebSocket.OPEN) {
199
+ if (ws.readyState !== import_ws.WebSocket.OPEN) {
189
200
  this.#logger.warn("Trying to send client TTS event to a closed WebSocket");
190
201
  return;
191
202
  }
@@ -197,9 +208,9 @@ class SynthesizeStream extends import_tts.SynthesizeStream {
197
208
  lastFrame = void 0;
198
209
  }
199
210
  };
200
- const createInputTask = async () => {
211
+ const createInputTask = async (signal) => {
201
212
  for await (const data of this.input) {
202
- if (this.abortController.signal.aborted || closing) break;
213
+ if (signal.aborted || closing) break;
203
214
  if (data === SynthesizeStream.FLUSH_SENTINEL) {
204
215
  sendTokenizerStream.flush();
205
216
  continue;
@@ -210,54 +221,95 @@ class SynthesizeStream extends import_tts.SynthesizeStream {
210
221
  sendTokenizerStream.endInput();
211
222
  }
212
223
  };
213
- const createSentenceStreamTask = async () => {
224
+ const createSentenceStreamTask = async (ws, signal) => {
214
225
  for await (const ev of sendTokenizerStream) {
215
- if (this.abortController.signal.aborted) break;
216
- sendClientEvent({
217
- type: "input_transcript",
218
- transcript: ev.token + " "
219
- });
226
+ if (signal.aborted || closing) break;
227
+ await sendClientEvent(
228
+ {
229
+ type: "input_transcript",
230
+ transcript: ev.token + " "
231
+ },
232
+ ws,
233
+ signal
234
+ );
235
+ inputSentEvent.set();
220
236
  }
221
- sendClientEvent({ type: "session.flush" });
237
+ await sendClientEvent({ type: "session.flush" }, ws, signal);
238
+ inputSentEvent.set();
222
239
  };
223
- const createWsListenerTask = async (ws2) => {
224
- return new Promise((resolve, reject) => {
225
- this.abortController.signal.addEventListener("abort", () => {
226
- resourceCleanup();
227
- resolve();
228
- });
229
- ws2.on("message", async (data) => {
240
+ const createWsListenerTask = async (ws, signal) => {
241
+ const onMessage = (data) => {
242
+ try {
230
243
  const eventJson = JSON.parse(data.toString());
231
244
  const validatedEvent = import_api_protos.ttsServerEventSchema.parse(eventJson);
232
- eventChannel.write(validatedEvent);
233
- });
234
- ws2.on("error", (e) => {
235
- this.#logger.error({ error: e }, "WebSocket error");
236
- resourceCleanup();
237
- reject(e);
238
- });
239
- ws2.on("close", () => {
240
- resourceCleanup();
241
- if (!closing) return this.#logger.error("WebSocket closed unexpectedly");
242
- if (finalReceived) return resolve();
243
- reject(
245
+ void eventChannel.write(validatedEvent).catch((error) => {
246
+ this.#logger.debug(
247
+ { error },
248
+ "Failed writing TTS event to stream channel (likely closed)"
249
+ );
250
+ });
251
+ } catch (e) {
252
+ this.#logger.error({ error: e }, "Error parsing WebSocket message");
253
+ }
254
+ };
255
+ const onError = (e) => {
256
+ var _a;
257
+ this.#logger.error({ error: e }, "WebSocket error");
258
+ void resourceCleanup();
259
+ try {
260
+ (_a = ws.terminate) == null ? void 0 : _a.call(ws);
261
+ } catch {
262
+ }
263
+ this.tts.pool.remove(ws);
264
+ completionFuture.reject(e);
265
+ };
266
+ const onClose = () => {
267
+ if (!closing) {
268
+ this.#logger.error("WebSocket closed unexpectedly");
269
+ void resourceCleanup();
270
+ this.tts.pool.remove(ws);
271
+ completionFuture.reject(
244
272
  new import_exceptions.APIStatusError({
245
273
  message: "Gateway connection closed unexpectedly",
246
274
  options: { requestId }
247
275
  })
248
276
  );
249
- });
250
- });
277
+ }
278
+ };
279
+ const onAbort = () => {
280
+ var _a;
281
+ void resourceCleanup();
282
+ try {
283
+ (_a = ws.terminate) == null ? void 0 : _a.call(ws);
284
+ } catch {
285
+ }
286
+ this.tts.pool.remove(ws);
287
+ inputSentEvent.set();
288
+ completionFuture.resolve();
289
+ };
290
+ ws.on("message", onMessage);
291
+ ws.on("error", onError);
292
+ ws.on("close", onClose);
293
+ signal.addEventListener("abort", onAbort);
294
+ try {
295
+ await completionFuture.await;
296
+ } finally {
297
+ ws.off("message", onMessage);
298
+ ws.off("error", onError);
299
+ ws.off("close", onClose);
300
+ signal.removeEventListener("abort", onAbort);
301
+ }
251
302
  };
252
- const createRecvTask = async () => {
303
+ const createRecvTask = async (signal) => {
253
304
  let currentSessionId = null;
254
305
  const bstream = new import_audio.AudioByteStream(this.opts.sampleRate, NUM_CHANNELS);
255
306
  const serverEventStream = eventChannel.stream();
256
307
  const reader = serverEventStream.getReader();
257
308
  try {
258
- while (!this.closed && !this.abortController.signal.aborted) {
309
+ await inputSentEvent.wait();
310
+ while (!this.closed && !signal.aborted) {
259
311
  const result = await reader.read();
260
- if (this.abortController.signal.aborted) return;
312
+ if (signal.aborted) return;
261
313
  if (result.done) return;
262
314
  const serverEvent = result.value;
263
315
  switch (serverEvent.type) {
@@ -272,24 +324,29 @@ class SynthesizeStream extends import_tts.SynthesizeStream {
272
324
  }
273
325
  break;
274
326
  case "done":
275
- finalReceived = true;
276
327
  for (const frame of bstream.flush()) {
277
328
  sendLastFrame(currentSessionId, false);
278
329
  lastFrame = frame;
279
330
  }
280
331
  sendLastFrame(currentSessionId, true);
281
332
  this.queue.put(SynthesizeStream.END_OF_STREAM);
282
- break;
333
+ await resourceCleanup();
334
+ completionFuture.resolve();
335
+ return;
283
336
  case "session.closed":
284
- resourceCleanup();
285
- break;
337
+ await resourceCleanup();
338
+ completionFuture.resolve();
339
+ return;
286
340
  case "error":
287
341
  this.#logger.error(
288
342
  { serverEvent },
289
343
  "Received error message from LiveKit TTS WebSocket"
290
344
  );
291
- resourceCleanup();
292
- throw new import_exceptions.APIError(`LiveKit TTS returned error: ${serverEvent.message}`);
345
+ await resourceCleanup();
346
+ completionFuture.reject(
347
+ new import_exceptions.APIError(`LiveKit TTS returned error: ${serverEvent.message}`)
348
+ );
349
+ return;
293
350
  default:
294
351
  this.#logger.warn("Unexpected message %s", serverEvent);
295
352
  break;
@@ -305,15 +362,72 @@ class SynthesizeStream extends import_tts.SynthesizeStream {
305
362
  }
306
363
  };
307
364
  try {
308
- ws = await this.tts.connectWs(this.connOptions.timeoutMs);
309
- await Promise.all([
310
- createInputTask(),
311
- createSentenceStreamTask(),
312
- createWsListenerTask(ws),
313
- createRecvTask()
314
- ]);
365
+ await this.tts.pool.withConnection(
366
+ async (ws) => {
367
+ try {
368
+ const runController = new AbortController();
369
+ const onStreamAbort = () => runController.abort(this.abortController.signal.reason);
370
+ this.abortController.signal.addEventListener("abort", onStreamAbort, { once: true });
371
+ const tasks = [
372
+ import_utils.Task.from(
373
+ async (controller) => {
374
+ const combined = (0, import_utils.combineSignals)(runController.signal, controller.signal);
375
+ await createInputTask(combined);
376
+ },
377
+ void 0,
378
+ "inference-tts-input"
379
+ ),
380
+ import_utils.Task.from(
381
+ async (controller) => {
382
+ const combined = (0, import_utils.combineSignals)(runController.signal, controller.signal);
383
+ await createSentenceStreamTask(ws, combined);
384
+ },
385
+ void 0,
386
+ "inference-tts-sentence"
387
+ ),
388
+ import_utils.Task.from(
389
+ async (controller) => {
390
+ const combined = (0, import_utils.combineSignals)(runController.signal, controller.signal);
391
+ await createWsListenerTask(ws, combined);
392
+ },
393
+ void 0,
394
+ "inference-tts-ws-listener"
395
+ ),
396
+ import_utils.Task.from(
397
+ async (controller) => {
398
+ const combined = (0, import_utils.combineSignals)(runController.signal, controller.signal);
399
+ await createRecvTask(combined);
400
+ },
401
+ void 0,
402
+ "inference-tts-recv"
403
+ )
404
+ ];
405
+ try {
406
+ await Promise.all(tasks.map((t) => t.result));
407
+ } finally {
408
+ inputSentEvent.set();
409
+ await resourceCleanup();
410
+ await (0, import_utils.cancelAndWait)(tasks, 5e3);
411
+ this.abortController.signal.removeEventListener("abort", onStreamAbort);
412
+ }
413
+ } catch (e) {
414
+ if (e instanceof Error && e.name === "AbortError") {
415
+ return;
416
+ }
417
+ throw e;
418
+ }
419
+ },
420
+ {
421
+ timeout: this.connOptions.timeoutMs
422
+ }
423
+ );
424
+ } catch (e) {
425
+ if (e instanceof Error && e.name === "AbortError") {
426
+ return;
427
+ }
428
+ throw e;
315
429
  } finally {
316
- resourceCleanup();
430
+ await resourceCleanup();
317
431
  }
318
432
  }
319
433
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/inference/tts.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport { WebSocket } from 'ws';\nimport { APIError, APIStatusError } from '../_exceptions.js';\nimport { AudioByteStream } from '../audio.js';\nimport { log } from '../log.js';\nimport { createStreamChannel } from '../stream/stream_channel.js';\nimport { basic as tokenizeBasic } from '../tokenize/index.js';\nimport type { ChunkedStream } from '../tts/index.js';\nimport { SynthesizeStream as BaseSynthesizeStream, TTS as BaseTTS } from '../tts/index.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../types.js';\nimport { shortuuid } from '../utils.js';\nimport {\n type TtsClientEvent,\n type TtsServerEvent,\n type TtsSessionCreateEvent,\n ttsClientEventSchema,\n ttsServerEventSchema,\n} from './api_protos.js';\nimport { type AnyString, connectWs, createAccessToken } from './utils.js';\n\nexport type CartesiaModels =\n | 'cartesia'\n | 'cartesia/sonic'\n | 'cartesia/sonic-2'\n | 'cartesia/sonic-turbo';\n\nexport type ElevenlabsModels =\n | 'elevenlabs'\n | 'elevenlabs/eleven_flash_v2'\n | 'elevenlabs/eleven_flash_v2_5'\n | 'elevenlabs/eleven_turbo_v2'\n | 'elevenlabs/eleven_turbo_v2_5'\n | 'elevenlabs/eleven_multilingual_v2';\n\nexport type RimeModels = 'rime' | 'rime/mist' | 'rime/mistv2' | 'rime/arcana';\n\nexport type InworldModels = 'inworld' | 'inworld/inworld-tts-1';\n\nexport interface CartesiaOptions {\n duration?: number; // max duration of audio in seconds\n speed?: 'slow' | 'normal' | 'fast'; // default: not specified\n}\n\nexport interface ElevenlabsOptions {\n inactivity_timeout?: number; // default: 60\n apply_text_normalization?: 'auto' | 'off' | 'on'; // default: \"auto\"\n}\n\nexport interface RimeOptions {}\n\nexport interface InworldOptions {}\n\ntype _TTSModels = CartesiaModels | ElevenlabsModels | RimeModels | InworldModels;\n\nexport type TTSModels = CartesiaModels | ElevenlabsModels | RimeModels | InworldModels | AnyString;\n\nexport type ModelWithVoice = `${_TTSModels}:${string}` | TTSModels;\n\nexport type TTSOptions<TModel extends TTSModels> = TModel extends CartesiaModels\n ? CartesiaOptions\n : TModel extends ElevenlabsModels\n ? ElevenlabsOptions\n : TModel extends RimeOptions\n ? RimeOptions\n : TModel extends InworldOptions\n ? InworldOptions\n : Record<string, unknown>;\n\ntype TTSEncoding = 'pcm_s16le';\n\nconst DEFAULT_ENCODING: TTSEncoding = 'pcm_s16le';\nconst DEFAULT_SAMPLE_RATE = 16000;\nconst DEFAULT_BASE_URL = 'https://agent-gateway.livekit.cloud/v1';\nconst NUM_CHANNELS = 1;\nconst DEFAULT_LANGUAGE = 'en';\n\nexport interface InferenceTTSOptions<TModel extends TTSModels> {\n model?: TModel;\n voice?: string;\n language?: string;\n encoding: TTSEncoding;\n sampleRate: number;\n baseURL: string;\n apiKey: string;\n apiSecret: string;\n modelOptions: TTSOptions<TModel>;\n}\n\n/**\n * Livekit Cloud Inference TTS\n */\nexport class TTS<TModel extends TTSModels> extends BaseTTS {\n private opts: InferenceTTSOptions<TModel>;\n private streams: Set<SynthesizeStream<TModel>> = new Set();\n\n #logger = log();\n\n constructor(opts: {\n model: TModel;\n voice?: string;\n language?: string;\n baseURL?: string;\n encoding?: TTSEncoding;\n sampleRate?: number;\n apiKey?: string;\n apiSecret?: string;\n modelOptions?: TTSOptions<TModel>;\n }) {\n const sampleRate = opts?.sampleRate ?? DEFAULT_SAMPLE_RATE;\n super(sampleRate, 1, { streaming: true });\n\n const {\n model,\n voice,\n language = DEFAULT_LANGUAGE,\n baseURL,\n encoding = DEFAULT_ENCODING,\n apiKey,\n apiSecret,\n modelOptions = {} as TTSOptions<TModel>,\n } = opts || {};\n\n const lkBaseURL = baseURL || process.env.LIVEKIT_INFERENCE_URL || DEFAULT_BASE_URL;\n const lkApiKey = apiKey || process.env.LIVEKIT_INFERENCE_API_KEY || process.env.LIVEKIT_API_KEY;\n if (!lkApiKey) {\n throw new Error('apiKey is required: pass apiKey or set LIVEKIT_API_KEY');\n }\n\n const lkApiSecret =\n apiSecret || process.env.LIVEKIT_INFERENCE_API_SECRET || process.env.LIVEKIT_API_SECRET;\n if (!lkApiSecret) {\n throw new Error('apiSecret is required: pass apiSecret or set LIVEKIT_API_SECRET');\n }\n\n // read voice id from the model if provided: \"provider/model:voice_id\"\n let nextModel = model;\n let nextVoice = voice;\n if (typeof nextModel === 'string') {\n const idx = nextModel.lastIndexOf(':');\n if (idx !== -1) {\n const voiceFromModel = nextModel.slice(idx + 1);\n if (nextVoice && nextVoice !== voiceFromModel) {\n this.#logger.warn(\n '`voice` is provided via both argument and model, using the one from the argument',\n { voice: nextVoice, model: nextModel },\n );\n } else {\n nextVoice = voiceFromModel;\n }\n nextModel = nextModel.slice(0, idx) as TModel;\n }\n }\n\n this.opts = {\n model: nextModel,\n voice: nextVoice,\n language,\n encoding,\n sampleRate,\n baseURL: lkBaseURL,\n apiKey: lkApiKey,\n apiSecret: lkApiSecret,\n modelOptions,\n };\n }\n\n get label() {\n return 'inference.TTS';\n }\n\n static fromModelString(modelString: string): TTS<AnyString> {\n if (modelString.includes(':')) {\n const [model, voice] = modelString.split(':') as [TTSModels, string];\n return new TTS({ model, voice });\n }\n return new TTS({ model: modelString });\n }\n\n updateOptions(opts: Partial<Pick<InferenceTTSOptions<TModel>, 'model' | 'voice' | 'language'>>) {\n this.opts = { ...this.opts, ...opts };\n for (const stream of this.streams) {\n stream.updateOptions(opts);\n }\n }\n\n synthesize(_: string): ChunkedStream {\n throw new Error('ChunkedStream is not implemented');\n }\n\n stream(options?: { connOptions?: APIConnectOptions }): SynthesizeStream<TModel> {\n const { connOptions = DEFAULT_API_CONNECT_OPTIONS } = options || {};\n const stream = new SynthesizeStream(this, { ...this.opts }, connOptions);\n this.streams.add(stream);\n return stream;\n }\n\n async connectWs(timeout: number): Promise<WebSocket> {\n let baseURL = this.opts.baseURL;\n if (baseURL.startsWith('http://') || baseURL.startsWith('https://')) {\n baseURL = baseURL.replace('http', 'ws');\n }\n\n const token = await createAccessToken(this.opts.apiKey, this.opts.apiSecret);\n const url = `${baseURL}/tts`;\n const headers = { Authorization: `Bearer ${token}` } as Record<string, string>;\n\n const params = {\n type: 'session.create',\n sample_rate: String(this.opts.sampleRate),\n encoding: this.opts.encoding,\n extra: this.opts.modelOptions,\n } as TtsSessionCreateEvent;\n\n if (this.opts.voice) params.voice = this.opts.voice;\n if (this.opts.model) params.model = this.opts.model;\n if (this.opts.language) params.language = this.opts.language;\n\n const socket = await connectWs(url, headers, timeout);\n socket.send(JSON.stringify(params));\n return socket;\n }\n\n async closeWs(ws: WebSocket) {\n await ws.close();\n }\n\n async close() {\n for (const stream of this.streams) {\n await stream.close();\n }\n this.streams.clear();\n }\n}\n\nexport class SynthesizeStream<TModel extends TTSModels> extends BaseSynthesizeStream {\n private opts: InferenceTTSOptions<TModel>;\n private tts: TTS<TModel>;\n private connOptions: APIConnectOptions;\n\n #logger = log();\n\n constructor(tts: TTS<TModel>, opts: InferenceTTSOptions<TModel>, connOptions: APIConnectOptions) {\n super(tts, connOptions);\n this.opts = opts;\n this.tts = tts;\n this.connOptions = connOptions;\n }\n\n get label() {\n return 'inference.SynthesizeStream';\n }\n\n updateOptions(opts: Partial<Pick<InferenceTTSOptions<TModel>, 'model' | 'voice' | 'language'>>) {\n this.opts = { ...this.opts, ...opts };\n }\n\n protected async run(): Promise<void> {\n let ws: WebSocket | null = null;\n let closing = false;\n let finalReceived = false;\n let lastFrame: AudioFrame | undefined;\n\n const sendTokenizerStream = new tokenizeBasic.SentenceTokenizer().stream();\n const eventChannel = createStreamChannel<TtsServerEvent>();\n const requestId = shortuuid('tts_request_');\n\n const resourceCleanup = () => {\n if (closing) return;\n closing = true;\n sendTokenizerStream.close();\n eventChannel.close();\n ws?.removeAllListeners();\n ws?.close();\n };\n\n const sendClientEvent = async (event: TtsClientEvent) => {\n // Don't send events to a closed WebSocket or aborted controller\n if (this.abortController.signal.aborted || closing) return;\n\n const validatedEvent = await ttsClientEventSchema.parseAsync(event);\n if (!ws || ws.readyState !== WebSocket.OPEN) {\n this.#logger.warn('Trying to send client TTS event to a closed WebSocket');\n return;\n }\n ws.send(JSON.stringify(validatedEvent));\n };\n\n const sendLastFrame = (segmentId: string, final: boolean) => {\n if (lastFrame) {\n this.queue.put({ requestId, segmentId, frame: lastFrame, final });\n lastFrame = undefined;\n }\n };\n\n const createInputTask = async () => {\n for await (const data of this.input) {\n if (this.abortController.signal.aborted || closing) break;\n if (data === SynthesizeStream.FLUSH_SENTINEL) {\n sendTokenizerStream.flush();\n continue;\n }\n sendTokenizerStream.pushText(data);\n }\n // Only call endInput if the stream hasn't been closed by cleanup\n if (!closing) {\n sendTokenizerStream.endInput();\n }\n };\n\n const createSentenceStreamTask = async () => {\n for await (const ev of sendTokenizerStream) {\n if (this.abortController.signal.aborted) break;\n\n sendClientEvent({\n type: 'input_transcript',\n transcript: ev.token + ' ',\n });\n }\n\n sendClientEvent({ type: 'session.flush' });\n };\n\n const createWsListenerTask = async (ws: WebSocket) => {\n return new Promise<void>((resolve, reject) => {\n this.abortController.signal.addEventListener('abort', () => {\n resourceCleanup();\n resolve(); // Abort is triggered by close(), which is a normal shutdown, not an error\n });\n\n ws.on('message', async (data) => {\n const eventJson = JSON.parse(data.toString()) as Record<string, unknown>;\n const validatedEvent = ttsServerEventSchema.parse(eventJson);\n eventChannel.write(validatedEvent);\n });\n\n ws.on('error', (e) => {\n this.#logger.error({ error: e }, 'WebSocket error');\n resourceCleanup();\n reject(e);\n });\n\n ws.on('close', () => {\n resourceCleanup();\n\n if (!closing) return this.#logger.error('WebSocket closed unexpectedly');\n if (finalReceived) return resolve();\n\n reject(\n new APIStatusError({\n message: 'Gateway connection closed unexpectedly',\n options: { requestId },\n }),\n );\n });\n });\n };\n\n const createRecvTask = async () => {\n let currentSessionId: string | null = null;\n\n const bstream = new AudioByteStream(this.opts.sampleRate, NUM_CHANNELS);\n const serverEventStream = eventChannel.stream();\n const reader = serverEventStream.getReader();\n\n try {\n while (!this.closed && !this.abortController.signal.aborted) {\n const result = await reader.read();\n if (this.abortController.signal.aborted) return;\n if (result.done) return;\n\n const serverEvent = result.value;\n switch (serverEvent.type) {\n case 'session.created':\n currentSessionId = serverEvent.session_id;\n break;\n case 'output_audio':\n const base64Data = new Int8Array(Buffer.from(serverEvent.audio, 'base64'));\n for (const frame of bstream.write(base64Data.buffer)) {\n sendLastFrame(currentSessionId!, false);\n lastFrame = frame;\n }\n break;\n case 'done':\n finalReceived = true;\n for (const frame of bstream.flush()) {\n sendLastFrame(currentSessionId!, false);\n lastFrame = frame;\n }\n sendLastFrame(currentSessionId!, true);\n this.queue.put(SynthesizeStream.END_OF_STREAM);\n break;\n case 'session.closed':\n resourceCleanup();\n break;\n case 'error':\n this.#logger.error(\n { serverEvent },\n 'Received error message from LiveKit TTS WebSocket',\n );\n resourceCleanup();\n throw new APIError(`LiveKit TTS returned error: ${serverEvent.message}`);\n default:\n this.#logger.warn('Unexpected message %s', serverEvent);\n break;\n }\n }\n } finally {\n reader.releaseLock();\n try {\n await serverEventStream.cancel();\n } catch (e) {\n this.#logger.debug('Error cancelling serverEventStream (may already be cancelled):', e);\n }\n }\n };\n\n try {\n ws = await this.tts.connectWs(this.connOptions.timeoutMs);\n\n await Promise.all([\n createInputTask(),\n createSentenceStreamTask(),\n createWsListenerTask(ws),\n createRecvTask(),\n ]);\n } finally {\n resourceCleanup();\n }\n }\n}\n"],"mappings":"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","names":["import_utils","BaseTTS","BaseSynthesizeStream","tokenizeBasic","ws"]}
1
+ {"version":3,"sources":["../../src/inference/tts.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport { WebSocket } from 'ws';\nimport { APIError, APIStatusError } from '../_exceptions.js';\nimport { AudioByteStream } from '../audio.js';\nimport { ConnectionPool } from '../connection_pool.js';\nimport { log } from '../log.js';\nimport { createStreamChannel } from '../stream/stream_channel.js';\nimport { basic as tokenizeBasic } from '../tokenize/index.js';\nimport type { ChunkedStream } from '../tts/index.js';\nimport { SynthesizeStream as BaseSynthesizeStream, TTS as BaseTTS } from '../tts/index.js';\nimport { type APIConnectOptions, DEFAULT_API_CONNECT_OPTIONS } from '../types.js';\nimport { Event, Future, Task, cancelAndWait, combineSignals, shortuuid } from '../utils.js';\nimport {\n type TtsClientEvent,\n type TtsServerEvent,\n type TtsSessionCreateEvent,\n ttsClientEventSchema,\n ttsServerEventSchema,\n} from './api_protos.js';\nimport { type AnyString, connectWs, createAccessToken } from './utils.js';\n\nexport type CartesiaModels =\n | 'cartesia'\n | 'cartesia/sonic'\n | 'cartesia/sonic-2'\n | 'cartesia/sonic-turbo';\n\nexport type ElevenlabsModels =\n | 'elevenlabs'\n | 'elevenlabs/eleven_flash_v2'\n | 'elevenlabs/eleven_flash_v2_5'\n | 'elevenlabs/eleven_turbo_v2'\n | 'elevenlabs/eleven_turbo_v2_5'\n | 'elevenlabs/eleven_multilingual_v2';\n\nexport type RimeModels = 'rime' | 'rime/mist' | 'rime/mistv2' | 'rime/arcana';\n\nexport type InworldModels = 'inworld' | 'inworld/inworld-tts-1';\n\nexport interface CartesiaOptions {\n duration?: number; // max duration of audio in seconds\n speed?: 'slow' | 'normal' | 'fast'; // default: not specified\n}\n\nexport interface ElevenlabsOptions {\n inactivity_timeout?: number; // default: 60\n apply_text_normalization?: 'auto' | 'off' | 'on'; // default: \"auto\"\n}\n\nexport interface RimeOptions {}\n\nexport interface InworldOptions {}\n\ntype _TTSModels = CartesiaModels | ElevenlabsModels | RimeModels | InworldModels;\n\nexport type TTSModels = CartesiaModels | ElevenlabsModels | RimeModels | InworldModels | AnyString;\n\nexport type ModelWithVoice = `${_TTSModels}:${string}` | TTSModels;\n\nexport type TTSOptions<TModel extends TTSModels> = TModel extends CartesiaModels\n ? CartesiaOptions\n : TModel extends ElevenlabsModels\n ? ElevenlabsOptions\n : TModel extends RimeOptions\n ? RimeOptions\n : TModel extends InworldOptions\n ? InworldOptions\n : Record<string, unknown>;\n\ntype TTSEncoding = 'pcm_s16le';\n\nconst DEFAULT_ENCODING: TTSEncoding = 'pcm_s16le';\nconst DEFAULT_SAMPLE_RATE = 16000;\nconst DEFAULT_BASE_URL = 'https://agent-gateway.livekit.cloud/v1';\nconst NUM_CHANNELS = 1;\nconst DEFAULT_LANGUAGE = 'en';\n\nexport interface InferenceTTSOptions<TModel extends TTSModels> {\n model?: TModel;\n voice?: string;\n language?: string;\n encoding: TTSEncoding;\n sampleRate: number;\n baseURL: string;\n apiKey: string;\n apiSecret: string;\n modelOptions: TTSOptions<TModel>;\n}\n\n/**\n * Livekit Cloud Inference TTS\n */\nexport class TTS<TModel extends TTSModels> extends BaseTTS {\n private opts: InferenceTTSOptions<TModel>;\n private streams: Set<SynthesizeStream<TModel>> = new Set();\n pool: ConnectionPool<WebSocket>;\n\n #logger = log();\n\n constructor(opts: {\n model: TModel;\n voice?: string;\n language?: string;\n baseURL?: string;\n encoding?: TTSEncoding;\n sampleRate?: number;\n apiKey?: string;\n apiSecret?: string;\n modelOptions?: TTSOptions<TModel>;\n }) {\n const sampleRate = opts?.sampleRate ?? DEFAULT_SAMPLE_RATE;\n super(sampleRate, 1, { streaming: true });\n\n const {\n model,\n voice,\n language = DEFAULT_LANGUAGE,\n baseURL,\n encoding = DEFAULT_ENCODING,\n apiKey,\n apiSecret,\n modelOptions = {} as TTSOptions<TModel>,\n } = opts || {};\n\n const lkBaseURL = baseURL || process.env.LIVEKIT_INFERENCE_URL || DEFAULT_BASE_URL;\n const lkApiKey = apiKey || process.env.LIVEKIT_INFERENCE_API_KEY || process.env.LIVEKIT_API_KEY;\n if (!lkApiKey) {\n throw new Error('apiKey is required: pass apiKey or set LIVEKIT_API_KEY');\n }\n\n const lkApiSecret =\n apiSecret || process.env.LIVEKIT_INFERENCE_API_SECRET || process.env.LIVEKIT_API_SECRET;\n if (!lkApiSecret) {\n throw new Error('apiSecret is required: pass apiSecret or set LIVEKIT_API_SECRET');\n }\n\n // read voice id from the model if provided: \"provider/model:voice_id\"\n let nextModel = model;\n let nextVoice = voice;\n if (typeof nextModel === 'string') {\n const idx = nextModel.lastIndexOf(':');\n if (idx !== -1) {\n const voiceFromModel = nextModel.slice(idx + 1);\n if (nextVoice && nextVoice !== voiceFromModel) {\n this.#logger.warn(\n '`voice` is provided via both argument and model, using the one from the argument',\n { voice: nextVoice, model: nextModel },\n );\n } else {\n nextVoice = voiceFromModel;\n }\n nextModel = nextModel.slice(0, idx) as TModel;\n }\n }\n\n this.opts = {\n model: nextModel,\n voice: nextVoice,\n language,\n encoding,\n sampleRate,\n baseURL: lkBaseURL,\n apiKey: lkApiKey,\n apiSecret: lkApiSecret,\n modelOptions,\n };\n\n // Initialize connection pool\n this.pool = new ConnectionPool<WebSocket>({\n connectCb: (timeout) => this.connectWs(timeout),\n closeCb: (ws) => this.closeWs(ws),\n maxSessionDuration: 300_000,\n markRefreshedOnGet: true,\n connectTimeout: 10_000, // 10 seconds default\n });\n }\n\n get label() {\n return 'inference.TTS';\n }\n\n static fromModelString(modelString: string): TTS<AnyString> {\n if (modelString.includes(':')) {\n const [model, voice] = modelString.split(':') as [TTSModels, string];\n return new TTS({ model, voice });\n }\n return new TTS({ model: modelString });\n }\n\n updateOptions(opts: Partial<Pick<InferenceTTSOptions<TModel>, 'model' | 'voice' | 'language'>>) {\n this.opts = { ...this.opts, ...opts };\n for (const stream of this.streams) {\n stream.updateOptions(opts);\n }\n }\n\n synthesize(_: string): ChunkedStream {\n throw new Error('ChunkedStream is not implemented');\n }\n\n stream(options?: { connOptions?: APIConnectOptions }): SynthesizeStream<TModel> {\n const { connOptions = DEFAULT_API_CONNECT_OPTIONS } = options || {};\n const stream = new SynthesizeStream(this, { ...this.opts }, connOptions);\n this.streams.add(stream);\n return stream;\n }\n\n async connectWs(timeout: number): Promise<WebSocket> {\n let baseURL = this.opts.baseURL;\n if (baseURL.startsWith('http://') || baseURL.startsWith('https://')) {\n baseURL = baseURL.replace('http', 'ws');\n }\n\n const token = await createAccessToken(this.opts.apiKey, this.opts.apiSecret);\n const url = `${baseURL}/tts`;\n const headers = { Authorization: `Bearer ${token}` } as Record<string, string>;\n\n const params = {\n type: 'session.create',\n sample_rate: String(this.opts.sampleRate),\n encoding: this.opts.encoding,\n extra: this.opts.modelOptions,\n } as TtsSessionCreateEvent;\n\n if (this.opts.voice) params.voice = this.opts.voice;\n if (this.opts.model) params.model = this.opts.model;\n if (this.opts.language) params.language = this.opts.language;\n\n this.#logger.debug({ url }, 'inference.TTS creating new websocket connection (pool miss)');\n const socket = await connectWs(url, headers, timeout);\n socket.send(JSON.stringify(params));\n return socket;\n }\n\n async closeWs(ws: WebSocket) {\n await ws.close();\n }\n\n prewarm(): void {\n this.pool.prewarm();\n }\n\n async close() {\n for (const stream of this.streams) {\n await stream.close();\n }\n this.streams.clear();\n await this.pool.close();\n }\n}\n\nexport class SynthesizeStream<TModel extends TTSModels> extends BaseSynthesizeStream {\n private opts: InferenceTTSOptions<TModel>;\n private tts: TTS<TModel>;\n\n #logger = log();\n\n constructor(tts: TTS<TModel>, opts: InferenceTTSOptions<TModel>, connOptions: APIConnectOptions) {\n super(tts, connOptions);\n this.opts = opts;\n this.tts = tts;\n }\n\n get label() {\n return 'inference.SynthesizeStream';\n }\n\n updateOptions(opts: Partial<Pick<InferenceTTSOptions<TModel>, 'model' | 'voice' | 'language'>>) {\n this.opts = { ...this.opts, ...opts };\n }\n\n protected async run(): Promise<void> {\n let closing = false;\n let lastFrame: AudioFrame | undefined;\n\n const sendTokenizerStream = new tokenizeBasic.SentenceTokenizer().stream();\n const eventChannel = createStreamChannel<TtsServerEvent>();\n const requestId = shortuuid('tts_request_');\n const inputSentEvent = new Event();\n\n // Signal for protocol-driven completion (when 'done' message is received)\n const completionFuture = new Future<void>();\n\n const resourceCleanup = async () => {\n if (closing) return;\n closing = true;\n sendTokenizerStream.close();\n // close() returns a promise; don't leak it\n await eventChannel.close();\n };\n\n const sendClientEvent = async (event: TtsClientEvent, ws: WebSocket, signal: AbortSignal) => {\n // Don't send events to a closed WebSocket or aborted controller\n if (signal.aborted || closing) return;\n\n const validatedEvent = await ttsClientEventSchema.parseAsync(event);\n if (ws.readyState !== WebSocket.OPEN) {\n this.#logger.warn('Trying to send client TTS event to a closed WebSocket');\n return;\n }\n ws.send(JSON.stringify(validatedEvent));\n };\n\n const sendLastFrame = (segmentId: string, final: boolean) => {\n if (lastFrame) {\n this.queue.put({ requestId, segmentId, frame: lastFrame, final });\n lastFrame = undefined;\n }\n };\n\n const createInputTask = async (signal: AbortSignal) => {\n for await (const data of this.input) {\n if (signal.aborted || closing) break;\n if (data === SynthesizeStream.FLUSH_SENTINEL) {\n sendTokenizerStream.flush();\n continue;\n }\n sendTokenizerStream.pushText(data);\n }\n // Only call endInput if the stream hasn't been closed by cleanup\n if (!closing) {\n sendTokenizerStream.endInput();\n }\n };\n\n const createSentenceStreamTask = async (ws: WebSocket, signal: AbortSignal) => {\n for await (const ev of sendTokenizerStream) {\n if (signal.aborted || closing) break;\n\n await sendClientEvent(\n {\n type: 'input_transcript',\n transcript: ev.token + ' ',\n },\n ws,\n signal,\n );\n inputSentEvent.set();\n }\n\n await sendClientEvent({ type: 'session.flush' }, ws, signal);\n // needed in case empty input is sent\n inputSentEvent.set();\n };\n\n // Handles WebSocket message routing and error handling\n // Completes based on protocol messages, NOT on ws.close()\n const createWsListenerTask = async (ws: WebSocket, signal: AbortSignal) => {\n const onMessage = (data: Buffer) => {\n try {\n const eventJson = JSON.parse(data.toString()) as Record<string, unknown>;\n const validatedEvent = ttsServerEventSchema.parse(eventJson);\n // writer.write returns a promise; avoid unhandled rejections if stream is closed\n void eventChannel.write(validatedEvent).catch((error) => {\n this.#logger.debug(\n { error },\n 'Failed writing TTS event to stream channel (likely closed)',\n );\n });\n } catch (e) {\n this.#logger.error({ error: e }, 'Error parsing WebSocket message');\n }\n };\n\n const onError = (e: Error) => {\n this.#logger.error({ error: e }, 'WebSocket error');\n void resourceCleanup();\n try {\n // If the ws is misbehaving, hard-stop it immediately to avoid buffering.\n ws.terminate?.();\n } catch {\n // ignore\n }\n // Ensure this ws is not reused\n this.tts.pool.remove(ws);\n completionFuture.reject(e);\n };\n\n const onClose = () => {\n // WebSocket closed unexpectedly (not by us)\n if (!closing) {\n this.#logger.error('WebSocket closed unexpectedly');\n void resourceCleanup();\n // Ensure this ws is not reused\n this.tts.pool.remove(ws);\n completionFuture.reject(\n new APIStatusError({\n message: 'Gateway connection closed unexpectedly',\n options: { requestId },\n }),\n );\n }\n };\n\n const onAbort = () => {\n void resourceCleanup();\n try {\n // On interruption/abort, close the websocket immediately so the server stops streaming\n // and the ws library doesn't buffer unread frames in memory.\n ws.terminate?.();\n } catch {\n // ignore\n }\n this.tts.pool.remove(ws);\n inputSentEvent.set();\n completionFuture.resolve();\n };\n\n // Attach listeners\n ws.on('message', onMessage);\n ws.on('error', onError);\n ws.on('close', onClose);\n signal.addEventListener('abort', onAbort);\n\n try {\n // Wait for protocol-driven completion or error\n await completionFuture.await;\n } finally {\n // IMPORTANT: Remove listeners so connection can be reused\n ws.off('message', onMessage);\n ws.off('error', onError);\n ws.off('close', onClose);\n signal.removeEventListener('abort', onAbort);\n }\n };\n\n const createRecvTask = async (signal: AbortSignal) => {\n let currentSessionId: string | null = null;\n\n const bstream = new AudioByteStream(this.opts.sampleRate, NUM_CHANNELS);\n const serverEventStream = eventChannel.stream();\n const reader = serverEventStream.getReader();\n\n try {\n await inputSentEvent.wait();\n\n while (!this.closed && !signal.aborted) {\n const result = await reader.read();\n if (signal.aborted) return;\n if (result.done) return;\n\n const serverEvent = result.value;\n switch (serverEvent.type) {\n case 'session.created':\n currentSessionId = serverEvent.session_id;\n break;\n case 'output_audio':\n const base64Data = new Int8Array(Buffer.from(serverEvent.audio, 'base64'));\n for (const frame of bstream.write(base64Data.buffer)) {\n sendLastFrame(currentSessionId!, false);\n lastFrame = frame;\n }\n break;\n case 'done':\n for (const frame of bstream.flush()) {\n sendLastFrame(currentSessionId!, false);\n lastFrame = frame;\n }\n sendLastFrame(currentSessionId!, true);\n this.queue.put(SynthesizeStream.END_OF_STREAM);\n await resourceCleanup();\n completionFuture.resolve();\n return;\n case 'session.closed':\n await resourceCleanup();\n completionFuture.resolve();\n return;\n case 'error':\n this.#logger.error(\n { serverEvent },\n 'Received error message from LiveKit TTS WebSocket',\n );\n await resourceCleanup();\n completionFuture.reject(\n new APIError(`LiveKit TTS returned error: ${serverEvent.message}`),\n );\n return;\n default:\n this.#logger.warn('Unexpected message %s', serverEvent);\n break;\n }\n }\n } finally {\n reader.releaseLock();\n try {\n await serverEventStream.cancel();\n } catch (e) {\n this.#logger.debug('Error cancelling serverEventStream (may already be cancelled):', e);\n }\n }\n };\n\n try {\n await this.tts.pool.withConnection(\n async (ws: WebSocket) => {\n try {\n // IMPORTANT: don't cancel the stream's controller on normal completion,\n // otherwise the pool will remove+close the ws and every run becomes a pool miss.\n const runController = new AbortController();\n const onStreamAbort = () => runController.abort(this.abortController.signal.reason);\n this.abortController.signal.addEventListener('abort', onStreamAbort, { once: true });\n\n const tasks = [\n Task.from(\n async (controller) => {\n const combined = combineSignals(runController.signal, controller.signal);\n await createInputTask(combined);\n },\n undefined,\n 'inference-tts-input',\n ),\n Task.from(\n async (controller) => {\n const combined = combineSignals(runController.signal, controller.signal);\n await createSentenceStreamTask(ws, combined);\n },\n undefined,\n 'inference-tts-sentence',\n ),\n Task.from(\n async (controller) => {\n const combined = combineSignals(runController.signal, controller.signal);\n await createWsListenerTask(ws, combined);\n },\n undefined,\n 'inference-tts-ws-listener',\n ),\n Task.from(\n async (controller) => {\n const combined = combineSignals(runController.signal, controller.signal);\n await createRecvTask(combined);\n },\n undefined,\n 'inference-tts-recv',\n ),\n ];\n\n try {\n await Promise.all(tasks.map((t) => t.result));\n } finally {\n // Mirror python finally: unblock recv and cancel all tasks.\n inputSentEvent.set();\n await resourceCleanup();\n await cancelAndWait(tasks, 5000);\n this.abortController.signal.removeEventListener('abort', onStreamAbort);\n }\n } catch (e) {\n // If aborted, don't throw - let cleanup handle it\n if (e instanceof Error && e.name === 'AbortError') {\n return;\n }\n throw e;\n }\n },\n {\n timeout: this.connOptions.timeoutMs,\n },\n );\n } catch (e) {\n // Handle connection errors\n if (e instanceof Error && e.name === 'AbortError') {\n // Abort is expected during normal shutdown\n return;\n }\n throw e;\n } finally {\n // Ensure cleanup always runs (and don't leak the promise)\n await resourceCleanup();\n }\n }\n}\n"],"mappings":"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","names":["import_utils","BaseTTS","BaseSynthesizeStream","tokenizeBasic"]}
@@ -1,4 +1,5 @@
1
1
  import { WebSocket } from 'ws';
2
+ import { ConnectionPool } from '../connection_pool.js';
2
3
  import type { ChunkedStream } from '../tts/index.js';
3
4
  import { SynthesizeStream as BaseSynthesizeStream, TTS as BaseTTS } from '../tts/index.js';
4
5
  import { type APIConnectOptions } from '../types.js';
@@ -42,6 +43,7 @@ export declare class TTS<TModel extends TTSModels> extends BaseTTS {
42
43
  #private;
43
44
  private opts;
44
45
  private streams;
46
+ pool: ConnectionPool<WebSocket>;
45
47
  constructor(opts: {
46
48
  model: TModel;
47
49
  voice?: string;
@@ -62,13 +64,13 @@ export declare class TTS<TModel extends TTSModels> extends BaseTTS {
62
64
  }): SynthesizeStream<TModel>;
63
65
  connectWs(timeout: number): Promise<WebSocket>;
64
66
  closeWs(ws: WebSocket): Promise<void>;
67
+ prewarm(): void;
65
68
  close(): Promise<void>;
66
69
  }
67
70
  export declare class SynthesizeStream<TModel extends TTSModels> extends BaseSynthesizeStream {
68
71
  #private;
69
72
  private opts;
70
73
  private tts;
71
- private connOptions;
72
74
  constructor(tts: TTS<TModel>, opts: InferenceTTSOptions<TModel>, connOptions: APIConnectOptions);
73
75
  get label(): string;
74
76
  updateOptions(opts: Partial<Pick<InferenceTTSOptions<TModel>, 'model' | 'voice' | 'language'>>): void;
@@ -1,4 +1,5 @@
1
1
  import { WebSocket } from 'ws';
2
+ import { ConnectionPool } from '../connection_pool.js';
2
3
  import type { ChunkedStream } from '../tts/index.js';
3
4
  import { SynthesizeStream as BaseSynthesizeStream, TTS as BaseTTS } from '../tts/index.js';
4
5
  import { type APIConnectOptions } from '../types.js';
@@ -42,6 +43,7 @@ export declare class TTS<TModel extends TTSModels> extends BaseTTS {
42
43
  #private;
43
44
  private opts;
44
45
  private streams;
46
+ pool: ConnectionPool<WebSocket>;
45
47
  constructor(opts: {
46
48
  model: TModel;
47
49
  voice?: string;
@@ -62,13 +64,13 @@ export declare class TTS<TModel extends TTSModels> extends BaseTTS {
62
64
  }): SynthesizeStream<TModel>;
63
65
  connectWs(timeout: number): Promise<WebSocket>;
64
66
  closeWs(ws: WebSocket): Promise<void>;
67
+ prewarm(): void;
65
68
  close(): Promise<void>;
66
69
  }
67
70
  export declare class SynthesizeStream<TModel extends TTSModels> extends BaseSynthesizeStream {
68
71
  #private;
69
72
  private opts;
70
73
  private tts;
71
- private connOptions;
72
74
  constructor(tts: TTS<TModel>, opts: InferenceTTSOptions<TModel>, connOptions: APIConnectOptions);
73
75
  get label(): string;
74
76
  updateOptions(opts: Partial<Pick<InferenceTTSOptions<TModel>, 'model' | 'voice' | 'language'>>): void;
@@ -1 +1 @@
1
- {"version":3,"file":"tts.d.ts","sourceRoot":"","sources":["../../src/inference/tts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tts.d.ts","sourceRoot":"","sources":["../../src/inference/tts.ts"],"names":[],"mappings":"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"}