From 4655ac8e5c7d6840a36ad4e9651734689fed6fcc Mon Sep 17 00:00:00 2001 From: "rosetta-livekit-bot[bot]" <282703043+rosetta-livekit-bot[bot]@users.noreply.github.com> Date: Thu, 11 Jun 2026 17:47:53 +0000 Subject: [PATCH] feat(elevenlabs): add noVerbatim STT option --- .changeset/elevenlabs-no-verbatim.md | 5 +++++ plugins/elevenlabs/src/stt.ts | 25 +++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 .changeset/elevenlabs-no-verbatim.md diff --git a/.changeset/elevenlabs-no-verbatim.md b/.changeset/elevenlabs-no-verbatim.md new file mode 100644 index 000000000..391df6d38 --- /dev/null +++ b/.changeset/elevenlabs-no-verbatim.md @@ -0,0 +1,5 @@ +--- +'@livekit/agents-plugin-elevenlabs': minor +--- + +Add ElevenLabs STT `noVerbatim` option. diff --git a/plugins/elevenlabs/src/stt.ts b/plugins/elevenlabs/src/stt.ts index d179752de..8ce15b35c 100644 --- a/plugins/elevenlabs/src/stt.ts +++ b/plugins/elevenlabs/src/stt.ts @@ -59,6 +59,7 @@ export interface STTOptions { httpSession?: STTHTTPSession; modelId?: ElevenLabsSTTModels | string; keyterms?: string[]; + noVerbatim?: boolean; } interface ResolvedSTTOptions { @@ -71,6 +72,7 @@ interface ResolvedSTTOptions { sampleRate: STTRealtimeSampleRates; serverVad?: VADOptions | null; keyterms?: string[]; + noVerbatim: boolean; } export interface STTRecognizeOptions { @@ -234,6 +236,7 @@ export class STT extends stt.STT { includeTimestamps, modelId, keyterms: opts.keyterms, + noVerbatim: opts.noVerbatim ?? false, }; this.#session = opts.httpSession ?? {}; } @@ -347,6 +350,9 @@ export class STT extends stt.STT { form.append('keyterms', keyterm); } } + if (this.#opts.noVerbatim) { + form.append('no_verbatim', 'true'); + } try { const fetchFn = this.#session.fetch ?? fetch; @@ -428,6 +434,7 @@ export class STT extends stt.STT { tagAudioEvents?: boolean; serverVad?: VADOptions | null; keyterms?: string[]; + noVerbatim?: boolean; }): void { if (opts.tagAudioEvents !== undefined) { this.#opts.tagAudioEvents = opts.tagAudioEvents; @@ -441,10 +448,14 @@ export class STT extends stt.STT { this.#opts.keyterms = opts.keyterms; } + if (opts.noVerbatim !== undefined) { + this.#opts.noVerbatim = opts.noVerbatim; + } + for (const ref of this.#streams) { const stream = ref.deref(); if (stream) { - stream.updateOptions({ serverVad: opts.serverVad }); + stream.updateOptions({ serverVad: opts.serverVad, noVerbatim: opts.noVerbatim }); } else { this.#streams.delete(ref); } @@ -494,13 +505,19 @@ export class SpeechStream extends stt.SpeechStream { ); } - updateOptions(opts: { serverVad?: VADOptions | null }): void { + updateOptions(opts: { serverVad?: VADOptions | null; noVerbatim?: boolean }): void { if (opts.serverVad !== undefined) { this.#opts.serverVad = opts.serverVad; if (!this.#reconnectEvent.done) { this.#reconnectEvent.resolve(); } } + if (opts.noVerbatim !== undefined) { + this.#opts.noVerbatim = opts.noVerbatim; + if (!this.#reconnectEvent.done) { + this.#reconnectEvent.resolve(); + } + } } #onAudioDurationReport(duration: number): void { @@ -688,6 +705,10 @@ export class SpeechStream extends stt.SpeechStream { params.push('include_timestamps=true'); } + if (this.#opts.noVerbatim) { + params.push('no_verbatim=true'); + } + const baseURL = this.#opts.baseURL.replace('https://', 'wss://').replace('http://', 'ws://'); const wsUrl = `${baseURL}/speech-to-text/realtime?${params.join('&')}`; const headers = { [AUTHORIZATION_HEADER]: this.#opts.apiKey };