{"version":3,"sources":["../src/tts.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {\n  type APIConnectOptions,\n  APIConnectionError,\n  APIError,\n  APIStatusError,\n  APITimeoutError,\n  AudioByteStream,\n  log,\n  shortuuid,\n  tokenize,\n  tts,\n} from '@livekit/agents';\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport { request } from 'node:https';\nimport { type RawData, WebSocket } from 'ws';\nimport type { TTSEncoding, TTSModels } from './models.js';\n\nconst AUTHORIZATION_HEADER = 'Authorization';\nconst NUM_CHANNELS = 1;\nconst MIN_SENTENCE_LENGTH = 8;\n\nexport interface TTSOptions {\n  model: TTSModels | string;\n  encoding: TTSEncoding;\n  sampleRate: number;\n  speed?: number;\n  apiKey?: string;\n  baseUrl?: string;\n  sentenceTokenizer: tokenize.SentenceTokenizer;\n  capabilities: tts.TTSCapabilities;\n}\n\nconst defaultTTSOptions: TTSOptions = {\n  model: 'aura-asteria-en',\n  encoding: 'linear16',\n  sampleRate: 24000,\n  apiKey: process.env.DEEPGRAM_API_KEY,\n  baseUrl: 'https://api.deepgram.com',\n  capabilities: {\n    streaming: true,\n  },\n  sentenceTokenizer: new tokenize.basic.SentenceTokenizer({\n    minSentenceLength: MIN_SENTENCE_LENGTH,\n  }),\n};\n\nexport class TTS extends tts.TTS {\n  private opts: TTSOptions;\n  label = 'deepgram.TTS';\n\n  get model(): string {\n    return this.opts.model;\n  }\n\n  get provider(): string {\n    return 'Deepgram';\n  }\n\n  constructor(opts: Partial<TTSOptions> = {}) {\n    super(opts.sampleRate || defaultTTSOptions.sampleRate, NUM_CHANNELS, {\n      streaming: opts.capabilities?.streaming ?? defaultTTSOptions.capabilities.streaming,\n    });\n\n    this.opts = {\n      ...defaultTTSOptions,\n      ...opts,\n    };\n\n    if (this.opts.apiKey === undefined) {\n      throw new Error(\n        'Deepgram API key is required, whether as an argument or as $DEEPGRAM_API_KEY',\n      );\n    }\n\n    if (this.opts.speed !== undefined && (this.opts.speed < 0.7 || this.opts.speed > 1.5)) {\n      throw new Error(`Deepgram TTS speed must be between 0.7 and 1.5, got ${this.opts.speed}`);\n    }\n  }\n\n  synthesize(\n    text: string,\n    connOptions?: APIConnectOptions,\n    abortSignal?: AbortSignal,\n  ): tts.ChunkedStream {\n    return new ChunkedStream(this, text, this.opts, connOptions, abortSignal);\n  }\n\n  stream(options?: { connOptions?: APIConnectOptions }): tts.SynthesizeStream {\n    return new SynthesizeStream(this, this.opts, options?.connOptions);\n  }\n}\n\nexport class ChunkedStream extends tts.ChunkedStream {\n  label = 'deepgram.ChunkedStream';\n  #logger = log();\n  private opts: TTSOptions;\n  private text: string;\n\n  constructor(\n    tts: TTS,\n    text: string,\n    opts: TTSOptions,\n    connOptions?: APIConnectOptions,\n    abortSignal?: AbortSignal,\n  ) {\n    super(text, tts, connOptions, abortSignal);\n    this.text = text;\n    this.opts = opts;\n  }\n\n  protected async run() {\n    const requestId = shortuuid();\n    const bstream = new AudioByteStream(this.opts.sampleRate, NUM_CHANNELS);\n    const json = { text: this.text };\n    const url = new URL(`${this.opts.baseUrl!}/v1/speak`);\n    url.searchParams.append('sample_rate', this.opts.sampleRate.toString());\n    url.searchParams.append('model', this.opts.model);\n    url.searchParams.append('encoding', this.opts.encoding);\n    if (this.opts.speed !== undefined) {\n      url.searchParams.append('speed', this.opts.speed.toString());\n    }\n\n    await new Promise<void>((resolve, reject) => {\n      let settled = false;\n      const settle = (fn: () => void) => {\n        if (!settled) {\n          settled = true;\n          fn();\n        }\n      };\n\n      const req = request(\n        {\n          hostname: url.hostname,\n          port: 443,\n          path: url.pathname + url.search,\n          method: 'POST',\n          headers: {\n            [AUTHORIZATION_HEADER]: `Token ${this.opts.apiKey!}`,\n            'Content-Type': 'application/json',\n          },\n          signal: this.abortSignal,\n        },\n        (res) => {\n          if (res.statusCode !== 200) {\n            settle(() =>\n              reject(\n                new Error(\n                  `Deepgram TTS HTTP request failed: ${res.statusCode} ${res.statusMessage}`,\n                ),\n              ),\n            );\n            return;\n          }\n\n          res.on('data', (chunk) => {\n            for (const frame of bstream.write(chunk)) {\n              if (!this.queue.closed) {\n                this.queue.put({\n                  requestId,\n                  frame,\n                  final: false,\n                  segmentId: requestId,\n                });\n              }\n            }\n          });\n\n          res.on('error', (err) => {\n            if (err.message === 'aborted') return;\n            this.#logger.error({ err }, 'Deepgram TTS response error');\n            settle(() => reject(err));\n          });\n\n          res.on('close', () => {\n            for (const frame of bstream.flush()) {\n              if (!this.queue.closed) {\n                this.queue.put({\n                  requestId,\n                  frame,\n                  final: false,\n                  segmentId: requestId,\n                });\n              }\n            }\n            if (!this.queue.closed) {\n              this.queue.close();\n            }\n            settle(() => resolve());\n          });\n        },\n      );\n\n      req.on('error', (err) => {\n        if (err.name === 'AbortError') return;\n        this.#logger.error({ err }, 'Deepgram TTS request error');\n        settle(() => reject(err));\n      });\n\n      req.on('close', () => settle(() => resolve()));\n      req.write(JSON.stringify(json));\n      req.end();\n    });\n  }\n}\n\nexport class SynthesizeStream extends tts.SynthesizeStream {\n  private opts: TTSOptions;\n  private tokenizer: tokenize.SentenceStream;\n  #logger = log();\n  label = 'deepgram.SynthesizeStream';\n\n  private static readonly FLUSH_MSG = JSON.stringify({ type: 'Flush' });\n  private static readonly CLOSE_MSG = JSON.stringify({ type: 'Close' });\n\n  constructor(tts: TTS, opts: TTSOptions, connOptions?: APIConnectOptions) {\n    super(tts, connOptions);\n    this.opts = opts;\n    this.tokenizer = opts.sentenceTokenizer.stream();\n  }\n\n  private async closeWebSocket(ws: WebSocket): Promise<void> {\n    try {\n      // Send Flush and Close messages to ensure Deepgram processes all remaining audio\n      // and properly terminates the session, preventing lingering TTS sessions\n      if (ws.readyState === WebSocket.OPEN) {\n        ws.send(SynthesizeStream.FLUSH_MSG);\n        ws.send(SynthesizeStream.CLOSE_MSG);\n\n        // Wait for server acknowledgment to prevent race conditions and ensure\n        // proper cleanup, avoiding 429 Too Many Requests errors from lingering sessions\n        try {\n          await new Promise<void>((resolve, _reject) => {\n            const timeout = setTimeout(() => {\n              resolve();\n            }, 1000);\n\n            ws.once('message', () => {\n              clearTimeout(timeout);\n              resolve();\n            });\n\n            ws.once('close', () => {\n              clearTimeout(timeout);\n              resolve();\n            });\n\n            ws.once('error', () => {\n              clearTimeout(timeout);\n              resolve();\n            });\n          });\n        } catch (e) {\n          // Ignore timeout or other errors during close sequence\n        }\n      }\n    } catch (e) {\n      console.warn(`Error during WebSocket close sequence: ${e}`);\n    } finally {\n      if (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) {\n        ws.close();\n      }\n    }\n  }\n\n  protected async run() {\n    const requestId = shortuuid();\n    const segmentId = shortuuid();\n\n    const wsUrl = this.opts.baseUrl!.replace(/^http/, 'ws');\n    const url = new URL(`${wsUrl}/v1/speak`);\n    url.searchParams.append('sample_rate', this.opts.sampleRate.toString());\n    url.searchParams.append('model', this.opts.model);\n    url.searchParams.append('encoding', this.opts.encoding);\n    if (this.opts.speed !== undefined) {\n      url.searchParams.append('speed', this.opts.speed.toString());\n    }\n\n    const ws = new WebSocket(url, {\n      headers: {\n        [AUTHORIZATION_HEADER]: `Token ${this.opts.apiKey!}`,\n      },\n    });\n\n    await new Promise((resolve, reject) => {\n      ws.on('open', resolve);\n      ws.on('error', (error) => reject(error));\n      ws.on('close', (code) => reject(`WebSocket returned ${code}`));\n    });\n\n    const inputTask = async () => {\n      for await (const data of this.input) {\n        if (data === SynthesizeStream.FLUSH_SENTINEL) {\n          this.tokenizer.flush();\n          continue;\n        }\n        this.tokenizer.pushText(data);\n      }\n      this.tokenizer.endInput();\n      this.tokenizer.close();\n    };\n\n    let markInputSent: () => void = () => {};\n    const inputSent = new Promise<void>((resolve) => {\n      markInputSent = resolve;\n    });\n\n    const sendTask = async () => {\n      try {\n        for await (const event of this.tokenizer) {\n          if (this.abortController.signal.aborted) break;\n\n          let text = event.token;\n          if (!text.endsWith(' ')) {\n            text += ' ';\n          }\n\n          const message = JSON.stringify({\n            type: 'Speak',\n            text: text,\n          });\n\n          ws.send(message);\n          markInputSent();\n        }\n\n        if (!this.abortController.signal.aborted) {\n          ws.send(SynthesizeStream.FLUSH_MSG);\n          markInputSent();\n        }\n      } finally {\n        markInputSent();\n      }\n    };\n\n    const recvTask = async () => {\n      const bstream = new AudioByteStream(this.opts.sampleRate, NUM_CHANNELS);\n      let finalReceived = false;\n      let timeout: NodeJS.Timeout | null = null;\n      let lastFrame: AudioFrame | undefined;\n\n      const sendLastFrame = (segmentId: string, final: boolean) => {\n        if (lastFrame && !this.queue.closed) {\n          this.queue.put({ requestId, segmentId, frame: lastFrame, final });\n          lastFrame = undefined;\n        }\n      };\n\n      const clearMessageTimeout = () => {\n        if (timeout) {\n          clearTimeout(timeout);\n          timeout = null;\n        }\n      };\n\n      const resetMessageTimeout = (reject: (reason?: unknown) => void) => {\n        clearMessageTimeout();\n        timeout = setTimeout(() => {\n          reject(new APITimeoutError({ message: 'Deepgram TTS recv idle timeout' }));\n        }, this.connOptions.timeoutMs);\n      };\n\n      await inputSent;\n      if (this.abortController.signal.aborted) return;\n\n      return new Promise<void>((resolve, reject) => {\n        resetMessageTimeout(reject);\n\n        ws.on('message', (data: RawData, isBinary: boolean) => {\n          clearMessageTimeout();\n\n          if (!isBinary) {\n            const message = JSON.parse(data.toString());\n            if (message.type === 'Flushed') {\n              finalReceived = true;\n              for (const frame of bstream.flush()) {\n                sendLastFrame(segmentId, false);\n                lastFrame = frame;\n              }\n              sendLastFrame(segmentId, true);\n\n              if (!this.queue.closed) {\n                this.queue.put(SynthesizeStream.END_OF_STREAM);\n              }\n              resolve();\n              return;\n            } else if (message.type === 'Warning') {\n              this.#logger.warn(`Deepgram warning: ${message.warn_msg}`);\n            } else if (message.type === 'Error' || message.type === 'error') {\n              reject(new APIError('Deepgram TTS returned error', { body: message }));\n              return;\n            } else if (message.type !== 'Metadata') {\n              this.#logger.warn({ message }, 'Unknown Deepgram message type');\n            }\n\n            resetMessageTimeout(reject);\n            return;\n          }\n\n          const buffer =\n            data instanceof Buffer\n              ? data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength)\n              : (data as ArrayBuffer);\n          for (const frame of bstream.write(buffer as ArrayBuffer)) {\n            sendLastFrame(segmentId, false);\n            lastFrame = frame;\n          }\n          resetMessageTimeout(reject);\n        });\n\n        ws.on('close', (code, reason) => {\n          clearMessageTimeout();\n          if (!finalReceived) {\n            reject(\n              new APIStatusError({\n                message: 'Deepgram websocket connection closed unexpectedly',\n                options: {\n                  statusCode: code || -1,\n                  body: { reason: reason.toString() },\n                },\n              }),\n            );\n            return;\n          }\n          resolve();\n        });\n\n        ws.on('error', (error) => {\n          clearMessageTimeout();\n          reject(error);\n        });\n      });\n    };\n\n    try {\n      await Promise.all([inputTask(), sendTask(), recvTask()]);\n    } catch (e) {\n      if (this.abortController.signal.aborted) return;\n      if (e instanceof APIError) throw e;\n      throw new APIConnectionError({\n        message: `Deepgram TTS WebSocket failed: ${(e as Error).message ?? 'unknown error'}`,\n      });\n    } finally {\n      await this.closeWebSocket(ws);\n    }\n  }\n}\n"],"mappings":"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","names":["tts","segmentId"]}