{"version":3,"sources":["../src/stt_v2.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport {\n  type APIConnectOptions,\n  AudioByteStream,\n  Event,\n  calculateAudioDurationSeconds,\n  createTimedString,\n  log,\n  normalizeLanguage,\n  stt,\n} from '@livekit/agents';\nimport type { AudioFrame } from '@livekit/rtc-node';\nimport * as queryString from 'node:querystring';\nimport { WebSocket } from 'ws';\nimport { PeriodicCollector } from './_utils.js';\nimport type { V2Models } from './models.js';\n\nconst _CLOSE_MSG = JSON.stringify({ type: 'CloseStream' });\n\n// --- Configuration ---\n\n/**\n * Configuration options for STTv2 (Deepgram Flux model).\n */\nexport interface STTv2Options {\n  apiKey?: string;\n  model: V2Models | string;\n  sampleRate: number;\n  keyterms: string[];\n  endpointUrl: string;\n  language?: string;\n  eagerEotThreshold?: number;\n  eotThreshold?: number;\n  eotTimeoutMs?: number;\n  mipOptOut?: boolean;\n  tags?: string[];\n  /**\n   * List of language hints to bias the model for improved accuracy.\n   * Only usable with `flux-general-multi`.\n   */\n  // Ref: python livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/stt_v2.py - 61 line\n  languageHint?: string[];\n}\n\nconst defaultSTTv2Options: Omit<STTv2Options, 'apiKey'> = {\n  model: 'flux-general-en',\n  sampleRate: 16000,\n  keyterms: [],\n  endpointUrl: 'wss://api.deepgram.com/v2/listen',\n  language: 'en',\n  mipOptOut: false,\n};\n\nfunction validateTags(tags: string[]): string[] {\n  for (const tag of tags) {\n    if (tag.length > 128) {\n      throw new Error('tag must be no more than 128 characters');\n    }\n  }\n  return tags;\n}\n\n/**\n * Deepgram STTv2 using the Flux model for streaming speech-to-text.\n *\n * This uses Deepgram's V2 API (`/v2/listen`) which provides turn-based\n * transcription with support for preemptive generation.\n *\n * @remarks\n * Key differences from STT (V1):\n * - Uses `TurnInfo` events instead of `SpeechStarted`/`Results`\n * - Supports `eagerEotThreshold` for preemptive LLM generation\n * - Sends `PREFLIGHT_TRANSCRIPT` events when eager end-of-turn is detected\n *\n * @example\n * ```typescript\n * import { STTv2 } from '@livekit/agents-plugin-deepgram';\n *\n * const stt = new STTv2({\n *   model: 'flux-general-en',\n *   eagerEotThreshold: 0.5,  // Enable preemptive generation\n * });\n *\n * const stream = stt.stream();\n * stream.pushFrame(audioFrame);\n *\n * for await (const event of stream) {\n *   if (event.type === SpeechEventType.FINAL_TRANSCRIPT) {\n *     console.log(event.alternatives?.[0]?.text);\n *   }\n * }\n * ```\n */\nexport class STTv2 extends stt.STT {\n  readonly label = 'deepgram.STTv2';\n  #opts: STTv2Options;\n  #apiKey: string;\n  #logger = log();\n\n  /**\n   * Create a new Deepgram STTv2 instance.\n   *\n   * @param opts - Configuration options\n   * @param opts.apiKey - Deepgram API key (defaults to `DEEPGRAM_API_KEY` env var)\n   * @param opts.model - Model to use (default: `flux-general-en`)\n   * @param opts.eagerEotThreshold - Threshold (0.3-0.9) for preemptive generation\n   * @param opts.eotThreshold - End-of-turn detection threshold (default: 0.7)\n   * @param opts.eotTimeoutMs - End-of-turn timeout in ms (default: 3000)\n   * @param opts.keyterms - List of key terms to improve recognition\n   * @param opts.tags - Tags for usage reporting (max 128 chars each)\n   * @param opts.languageHint - List of language hints to bias the model for improved accuracy.\n   *   Only usable with `flux-general-multi`.\n   *\n   * @throws Error if no API key is provided\n   */\n  constructor(opts: Partial<STTv2Options> = {}) {\n    super({\n      streaming: true,\n      interimResults: true,\n      alignedTranscript: 'word',\n    });\n\n    this.#opts = {\n      ...defaultSTTv2Options,\n      ...opts,\n      language: opts.language ? normalizeLanguage(opts.language) : defaultSTTv2Options.language,\n    };\n\n    const apiKey = opts.apiKey || process.env.DEEPGRAM_API_KEY;\n    if (!apiKey) {\n      throw new Error('Deepgram API key is required');\n    }\n    this.#apiKey = apiKey;\n\n    if (this.#opts.tags) {\n      this.#opts.tags = validateTags(this.#opts.tags);\n    }\n\n    // Ref: python livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/stt_v2.py - 134-138 lines\n    if (\n      this.#opts.languageHint &&\n      this.#opts.languageHint.length > 0 &&\n      this.#opts.model !== 'flux-general-multi'\n    ) {\n      this.#logger.warn(\n        { model: this.#opts.model },\n        '`languageHint` is only supported by `flux-general-multi` and will be ignored for this model',\n      );\n    }\n  }\n\n  /** The model being used for transcription */\n  get model(): string {\n    return this.#opts.model;\n  }\n\n  /** The STT provider name */\n  get provider(): string {\n    return 'Deepgram';\n  }\n\n  protected async _recognize(\n    _frame: AudioFrame | AudioFrame[],\n    _abortSignal?: AbortSignal,\n  ): Promise<stt.SpeechEvent> {\n    throw new Error('V2 API does not support non-streaming recognize. Use .stream()');\n  }\n\n  /**\n   * Create a new streaming transcription session.\n   *\n   * @param options - Stream options\n   * @returns A SpeechStream that emits transcription events\n   */\n  stream(options?: { connOptions?: APIConnectOptions }): stt.SpeechStream {\n    const streamOpts = { ...this.#opts, apiKey: this.#apiKey };\n    return new SpeechStreamv2(this, streamOpts, options?.connOptions);\n  }\n\n  /**\n   * Update STT options. Changes will take effect on the next stream.\n   *\n   * @param opts - Partial options to update\n   */\n  updateOptions(opts: Partial<STTv2Options>) {\n    this.#opts = {\n      ...this.#opts,\n      ...opts,\n      language:\n        opts.language !== undefined ? normalizeLanguage(opts.language) : this.#opts.language,\n    };\n    if (opts.tags) this.#opts.tags = validateTags(opts.tags);\n    // Ref: python livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/stt_v2.py - 244-249 lines\n    if (\n      this.#opts.languageHint &&\n      this.#opts.languageHint.length > 0 &&\n      this.#opts.model !== 'flux-general-multi'\n    ) {\n      this.#logger.warn(\n        { model: this.#opts.model },\n        '`languageHint` is only supported by `flux-general-multi` and will be ignored for this model',\n      );\n    }\n    this.#logger.debug('Updated STTv2 options');\n  }\n}\n\n// --- Stream Implementation ---\n\nclass SpeechStreamv2 extends stt.SpeechStream {\n  readonly label = 'deepgram.SpeechStreamv2';\n  #opts: STTv2Options & { apiKey: string };\n  #logger = log();\n  #ws: WebSocket | null = null;\n\n  #audioDurationCollector: PeriodicCollector<number>;\n  #requestId = '';\n  #speaking = false;\n\n  // Parity: _reconnect_event - using existing Event class from @livekit/agents\n  #reconnectEvent = new Event();\n\n  constructor(\n    sttInstance: STTv2,\n    opts: STTv2Options & { apiKey: string },\n    connOptions?: APIConnectOptions,\n  ) {\n    super(sttInstance, opts.sampleRate, connOptions);\n    this.#opts = opts;\n\n    this.#audioDurationCollector = new PeriodicCollector(\n      (duration) => this.#onAudioDurationReport(duration),\n      { duration: 5.0 },\n    );\n  }\n\n  updateOptions(opts: Partial<STTv2Options>) {\n    this.#logger.debug('Stream received option update', opts);\n    this.#opts = {\n      ...this.#opts,\n      ...opts,\n      language:\n        opts.language !== undefined ? normalizeLanguage(opts.language) : this.#opts.language,\n    };\n    if (opts.tags) this.#opts.tags = validateTags(opts.tags);\n\n    // Trigger reconnection loop\n    this.#reconnectEvent.set();\n  }\n\n  protected async run() {\n    // Outer Loop: Handles reconnections (Configuration updates)\n    while (!this.closed) {\n      try {\n        this.#reconnectEvent.clear();\n\n        const url = this.#getDeepgramUrl();\n        this.#logger.debug(`Connecting to Deepgram: ${url}`);\n\n        this.#ws = new WebSocket(url, {\n          headers: { Authorization: `Token ${this.#opts.apiKey}` },\n        });\n\n        // 1. Wait for Connection Open\n        await new Promise<void>((resolve, reject) => {\n          if (!this.#ws) return reject(new Error('WebSocket not initialized'));\n\n          const onOpen = () => {\n            this.#ws?.off('error', onError);\n            resolve();\n          };\n          const onError = (err: Error) => {\n            this.#ws?.off('open', onOpen);\n            reject(err);\n          };\n\n          this.#ws.once('open', onOpen);\n          this.#ws.once('error', onError);\n        });\n\n        // 2. Run Concurrent Tasks (Send & Receive)\n        const sendPromise = this.#sendTask();\n        const recvPromise = this.#recvTask();\n        const reconnectWait = this.#reconnectEvent.wait();\n\n        // 3. Race: Normal Completion vs Reconnect Signal\n        const result = await Promise.race([\n          Promise.all([sendPromise, recvPromise]),\n          reconnectWait.then(() => 'RECONNECT'),\n        ]);\n\n        if (result === 'RECONNECT') {\n          this.#logger.debug('Reconnecting stream due to option update...');\n          // Close current socket; loop will restart and open a new one\n          this.#ws.close();\n        } else {\n          // Normal finish (Stream ended or Error thrown)\n          break;\n        }\n      } catch (error) {\n        this.#logger.error('Deepgram stream error', { error });\n        throw error; // Let Base Class handle retry logic\n      } finally {\n        if (this.#ws?.readyState === WebSocket.OPEN) {\n          this.#ws.close();\n        }\n      }\n    }\n    this.close();\n  }\n\n  async #sendTask() {\n    if (!this.#ws) return;\n\n    // Buffer audio into 50ms chunks (Parity)\n    const samples50ms = Math.floor(this.#opts.sampleRate / 20);\n    const audioBstream = new AudioByteStream(this.#opts.sampleRate, 1, samples50ms);\n\n    let hasEnded = false;\n\n    // Manual Iterator to allow racing against Reconnect Signal\n    const iterator = this.input[Symbol.asyncIterator]();\n\n    while (true) {\n      const nextPromise = iterator.next();\n      // If reconnect signal fires, abort the wait\n      const abortPromise = this.#reconnectEvent.wait().then(() => ({ abort: true }) as const);\n\n      const result = await Promise.race([nextPromise, abortPromise]);\n\n      // Check if we need to abort (Reconnect) or if stream is done\n      if ('abort' in result || result.done) {\n        if (!('abort' in result) && result.done) {\n          // Normal stream end\n          hasEnded = true;\n        } else {\n          // Reconnect triggered - break loop immediately\n          break;\n        }\n      }\n\n      // If we broke above, we don't process data. If not, 'result' is IteratorResult\n      if (hasEnded && result.value === undefined) {\n        // Process flush below\n      } else if ('value' in result) {\n        const data = result.value;\n        const frames: AudioFrame[] = [];\n\n        if (data === SpeechStreamv2.FLUSH_SENTINEL) {\n          frames.push(...audioBstream.flush());\n          hasEnded = true;\n        } else {\n          frames.push(...audioBstream.write((data as AudioFrame).data.buffer as ArrayBuffer));\n        }\n\n        for (const frame of frames) {\n          this.#audioDurationCollector.push(calculateAudioDurationSeconds(frame));\n\n          if (this.#ws!.readyState === WebSocket.OPEN) {\n            this.#ws!.send(frame.data);\n          }\n\n          if (hasEnded) {\n            this.#audioDurationCollector.flush();\n            hasEnded = false;\n          }\n        }\n      }\n\n      if (hasEnded) break;\n    }\n\n    // Only send CloseStream if we are exiting normally (not reconnecting)\n    if (!this.#reconnectEvent.isSet && this.#ws!.readyState === WebSocket.OPEN) {\n      this.#logger.debug('Sending CloseStream message to Deepgram');\n      this.#ws!.send(_CLOSE_MSG);\n    }\n  }\n\n  async #recvTask() {\n    if (!this.#ws) return;\n\n    return new Promise<void>((resolve) => {\n      if (!this.#ws) return resolve();\n\n      this.#ws.on('message', (data: Buffer, isBinary: boolean) => {\n        if (isBinary) {\n          this.#logger.warn('Received unexpected binary message from Deepgram');\n          return;\n        }\n        try {\n          const msg = JSON.parse(data.toString());\n          this.#processStreamEvent(msg);\n        } catch (error) {\n          this.#logger.error('Failed to parse Deepgram message', { error });\n        }\n      });\n\n      this.#ws.on('close', (code, reason) => {\n        this.#logger.debug(`Deepgram WebSocket closed: ${code} ${reason}`);\n        resolve();\n      });\n\n      // Errors are caught by run() listener, resolve here to clean up task\n      this.#ws.on('error', () => resolve());\n    });\n  }\n\n  #processStreamEvent(data: Record<string, unknown>) {\n    if (data.request_id) {\n      this.#requestId = data.request_id as string;\n    }\n\n    if (data.type === 'TurnInfo') {\n      const eventType = data.event;\n\n      if (eventType === 'StartOfTurn') {\n        if (this.#speaking) return;\n\n        this.#speaking = true;\n        this.queue.put({\n          type: stt.SpeechEventType.START_OF_SPEECH,\n          requestId: this.#requestId,\n        });\n\n        this.#sendTranscriptEvent(stt.SpeechEventType.INTERIM_TRANSCRIPT, data);\n      } else if (eventType === 'Update') {\n        if (!this.#speaking) return;\n        this.#sendTranscriptEvent(stt.SpeechEventType.INTERIM_TRANSCRIPT, data);\n      } else if (eventType === 'EagerEndOfTurn') {\n        if (!this.#speaking) return;\n        this.#sendTranscriptEvent(stt.SpeechEventType.PREFLIGHT_TRANSCRIPT, data);\n      } else if (eventType === 'TurnResumed') {\n        this.#sendTranscriptEvent(stt.SpeechEventType.INTERIM_TRANSCRIPT, data);\n      } else if (eventType === 'EndOfTurn') {\n        if (!this.#speaking) return;\n\n        this.#speaking = false;\n        this.#sendTranscriptEvent(stt.SpeechEventType.FINAL_TRANSCRIPT, data);\n\n        this.queue.put({\n          type: stt.SpeechEventType.END_OF_SPEECH,\n          requestId: this.#requestId,\n        });\n      }\n    } else if (data.type === 'Error') {\n      this.#logger.warn('deepgram sent an error', { data });\n      const desc = (data.description as string) || 'unknown error from deepgram';\n      throw new Error(`Deepgram API Error: ${desc}`);\n    }\n  }\n\n  #sendTranscriptEvent(eventType: stt.SpeechEventType, data: Record<string, unknown>) {\n    const alts = parseTranscription(this.#opts.language || 'en', data, this.startTimeOffset);\n\n    if (alts.length > 0) {\n      this.queue.put({\n        type: eventType,\n        requestId: this.#requestId,\n        alternatives: [alts[0]!, ...alts.slice(1)],\n      });\n    }\n  }\n\n  #onAudioDurationReport(duration: number) {\n    const usageEvent: stt.SpeechEvent = {\n      type: stt.SpeechEventType.RECOGNITION_USAGE,\n      requestId: this.#requestId,\n      recognitionUsage: {\n        audioDuration: duration,\n      },\n    };\n    this.queue.put(usageEvent);\n  }\n\n  #getDeepgramUrl(): string {\n    const params: Record<string, string | string[]> = {\n      model: this.#opts.model,\n      sample_rate: this.#opts.sampleRate.toString(),\n      encoding: 'linear16',\n      mip_opt_out: String(this.#opts.mipOptOut),\n    };\n\n    // Note: v2 API does NOT include 'language' parameter\n    if (this.#opts.eagerEotThreshold)\n      params.eager_eot_threshold = this.#opts.eagerEotThreshold.toString();\n    if (this.#opts.eotThreshold) params.eot_threshold = this.#opts.eotThreshold.toString();\n    if (this.#opts.eotTimeoutMs) params.eot_timeout_ms = this.#opts.eotTimeoutMs.toString();\n\n    if (this.#opts.keyterms.length > 0) params.keyterm = this.#opts.keyterms;\n    if (this.#opts.tags && this.#opts.tags.length > 0) params.tag = this.#opts.tags;\n\n    // Ref: python livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/stt_v2.py - 480-481 lines\n    if (this.#opts.languageHint && this.#opts.languageHint.length > 0) {\n      params.language_hint = this.#opts.languageHint;\n    }\n\n    const baseUrl = this.#opts.endpointUrl.replace(/^http/, 'ws');\n    const qs = queryString.stringify(params);\n    return `${baseUrl}?${qs}`;\n  }\n\n  override close() {\n    super.close();\n    this.#ws?.close();\n  }\n}\n\n// --- Helpers ---\n\nfunction parseTranscription(\n  language: string,\n  data: Record<string, unknown>,\n  startTimeOffset: number,\n): stt.SpeechData[] {\n  const transcript = data.transcript as string | undefined;\n  const wordsData = (data.words as Array<Record<string, unknown>>) || [];\n\n  if (!wordsData || wordsData.length === 0) {\n    return [];\n  }\n\n  let confidence = 0;\n  if (wordsData.length > 0) {\n    const sum = wordsData.reduce((acc: number, w) => acc + ((w.confidence as number) || 0), 0);\n    confidence = sum / wordsData.length;\n  }\n\n  // Ref: python livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/stt_v2.py - 587-591 lines\n  const detectedLanguagesRaw = Array.isArray(data.languages) ? (data.languages as string[]) : [];\n  const detectedLanguages = detectedLanguagesRaw.map((lang) => normalizeLanguage(lang));\n  const primaryLanguage =\n    detectedLanguages.length > 0 ? detectedLanguages[0]! : normalizeLanguage(language);\n\n  const sd: stt.SpeechData = {\n    language: primaryLanguage,\n    startTime: ((data.audio_window_start as number) || 0) + startTimeOffset,\n    endTime: ((data.audio_window_end as number) || 0) + startTimeOffset,\n    confidence: confidence,\n    text: transcript || '',\n    // Ref: python livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/stt_v2.py - 598 line\n    sourceLanguages: detectedLanguages.length > 0 ? detectedLanguages : undefined,\n    // Note: Deepgram V2 (Flux) API does not provide word-level timing (start/end).\n    // Words only contain 'word' and 'confidence' fields, so startTime/endTime will be 0.\n    // See: https://developers.deepgram.com/docs/flux/nova-3-migration\n    words: wordsData.map((word) =>\n      createTimedString({\n        text: (word.word as string) ?? '',\n        startTime: ((word.start as number) ?? 0) + startTimeOffset,\n        endTime: ((word.end as number) ?? 0) + startTimeOffset,\n        confidence: (word.confidence as number) ?? 0.0,\n        startTimeOffset,\n      }),\n    ),\n  };\n\n  return [sd];\n}\n"],"mappings":"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","names":["_a"]}