From 65a1bcc854c2663921f9fc6cb51380664d1fa026 Mon Sep 17 00:00:00 2001 From: Bram Roets Date: Thu, 6 Feb 2025 16:31:07 +0100 Subject: [PATCH 1/3] Add TTS support to deepgram --- plugins/deepgram/package.json | 1 + plugins/deepgram/src/index.ts | 1 + plugins/deepgram/src/models.ts | 16 ++ plugins/deepgram/src/tts.spec.ts | 15 ++ plugins/deepgram/src/tts.test.ts | 15 ++ plugins/deepgram/src/tts.ts | 242 +++++++++++++++++++++++++++++++ pnpm-lock.yaml | 46 ++++-- 7 files changed, 325 insertions(+), 11 deletions(-) create mode 100644 plugins/deepgram/src/tts.spec.ts create mode 100644 plugins/deepgram/src/tts.test.ts create mode 100644 plugins/deepgram/src/tts.ts diff --git a/plugins/deepgram/package.json b/plugins/deepgram/package.json index 06cfdd5f..d8ab8d29 100644 --- a/plugins/deepgram/package.json +++ b/plugins/deepgram/package.json @@ -31,6 +31,7 @@ }, "devDependencies": { "@livekit/agents": "workspace:^x", + "@livekit/agents-plugin-openai": "^0.8.1", "@livekit/agents-plugin-silero": "workspace:^x", "@livekit/agents-plugins-test": "workspace:^x", "@livekit/rtc-node": "^0.13.2", diff --git a/plugins/deepgram/src/index.ts b/plugins/deepgram/src/index.ts index a649b5ef..8696b2d4 100644 --- a/plugins/deepgram/src/index.ts +++ b/plugins/deepgram/src/index.ts @@ -3,3 +3,4 @@ // SPDX-License-Identifier: Apache-2.0 export * from './stt.js'; +export * from './tts.js'; diff --git a/plugins/deepgram/src/models.ts b/plugins/deepgram/src/models.ts index 63b60b05..76a1e12f 100644 --- a/plugins/deepgram/src/models.ts +++ b/plugins/deepgram/src/models.ts @@ -2,6 +2,22 @@ // // SPDX-License-Identifier: Apache-2.0 +export type TTSModels = + | 'aura-asteria-en' + | 'aura-luna-en' + | 'aura-stella-en' + | 'aura-athena-en' + | 'aura-hera-en' + | 'aura-orion-en' + | 'aura-arcas-en' + | 'aura-perseus-en' + | 'aura-angus-en' + | 'aura-orpheus-en' + | 'aura-helios-en' + | 'aura-zeus-en'; + +export type TTSEncoding = 'linear16' | 'mulaw' | 'alaw' | 'mp3' | 'opus' | 'flac' | 'aac'; + export type STTModels = | 'nova-general' | 'nova-phonecall' diff --git a/plugins/deepgram/src/tts.spec.ts b/plugins/deepgram/src/tts.spec.ts new file mode 100644 index 00000000..605b698e --- /dev/null +++ b/plugins/deepgram/src/tts.spec.ts @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2024 LiveKit, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +import { STT } from '@livekit/agents-plugin-openai'; +import { tts } from '@livekit/agents-plugins-test'; +import { describe } from 'vitest'; +import { TTS } from './tts.js'; + +describe( + 'Deepgram', + { timeout: 30_000 }, // For some reason it takes a while before deepgram closes the connection + async () => { + await tts(new TTS(), new STT()); + }, +); diff --git a/plugins/deepgram/src/tts.test.ts b/plugins/deepgram/src/tts.test.ts new file mode 100644 index 00000000..605b698e --- /dev/null +++ b/plugins/deepgram/src/tts.test.ts @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2024 LiveKit, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +import { STT } from '@livekit/agents-plugin-openai'; +import { tts } from '@livekit/agents-plugins-test'; +import { describe } from 'vitest'; +import { TTS } from './tts.js'; + +describe( + 'Deepgram', + { timeout: 30_000 }, // For some reason it takes a while before deepgram closes the connection + async () => { + await tts(new TTS(), new STT()); + }, +); diff --git a/plugins/deepgram/src/tts.ts b/plugins/deepgram/src/tts.ts new file mode 100644 index 00000000..4e879b93 --- /dev/null +++ b/plugins/deepgram/src/tts.ts @@ -0,0 +1,242 @@ +// SPDX-FileCopyrightText: 2024 LiveKit, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +import { AudioByteStream, log, tokenize, tts } from '@livekit/agents'; +import { randomUUID } from 'node:crypto'; +import { request } from 'node:https'; +import { WebSocket } from 'ws'; +import type { TTSEncoding, TTSModels } from './models.js'; + +const AUTHORIZATION_HEADER = 'Authorization'; +const NUM_CHANNELS = 1; +const BUFFERED_WORDS_COUNT = 8; + +// @see https://github.com/livekit/agents/blob/main/livekit-plugins/livekit-plugins-deepgram/livekit/plugins/deepgram/tts.py +// @see https://developers.deepgram.com/docs/tts-websocket + +export interface TTSOptions { + model: TTSModels | string; + encoding: TTSEncoding; + sampleRate: number; + apiKey?: string; + baseUrl?: string; +} + +const defaultTTSOptions: TTSOptions = { + model: 'aura-asteria-en', + encoding: 'linear16', + sampleRate: 24000, + apiKey: process.env.DEEPGRAM_API_KEY, + baseUrl: 'https://api.deepgram.com/v1/speak', +}; + +export class TTS extends tts.TTS { + #opts: TTSOptions; + label = 'deepgram.TTS'; + + constructor(opts: Partial = {}) { + super(opts.sampleRate || defaultTTSOptions.sampleRate, NUM_CHANNELS, { + streaming: true, + }); + + this.#opts = { + ...defaultTTSOptions, + ...opts, + }; + + if (this.#opts.apiKey === undefined) { + throw new Error( + 'Deepgram API key is required, whether as an argument or as $DEEPGRAM_API_KEY', + ); + } + } + + synthesize(text: string): tts.ChunkedStream { + return new ChunkedStream(this, text, this.#opts); + } + + stream(): tts.SynthesizeStream { + return new SynthesizeStream(this, this.#opts); + } +} + +export class ChunkedStream extends tts.ChunkedStream { + label = 'deepgram.ChunkedStream'; + #opts: TTSOptions; + #logger = log(); + #text: string; + + constructor(tts: TTS, text: string, opts: TTSOptions) { + super(text, tts); + this.#text = text; + this.#opts = opts; + this.#run(); + } + + async #run() { + const requestId = randomUUID(); + const bstream = new AudioByteStream(this.#opts.sampleRate, NUM_CHANNELS); + const json = { text: this.#text }; + const url = new URL(this.#opts.baseUrl!); + url.searchParams.append('sample_rate', this.#opts.sampleRate.toString()); + url.searchParams.append('model', this.#opts.model); + url.searchParams.append('encoding', this.#opts.encoding); + + const req = request( + { + hostname: url.hostname, + port: 443, + path: url.pathname, + method: 'POST', + headers: { + [AUTHORIZATION_HEADER]: `Token ${this.#opts.apiKey!}`, + }, + }, + (res) => { + if (res.statusCode !== 200) { + throw new Error(`Failed to synthesize audio: ${res.statusCode}`); + } + + res.on('data', (chunk) => { + for (const frame of bstream.write(chunk)) { + this.queue.put({ + requestId, + frame, + final: false, + segmentId: requestId, + }); + } + }); + + res.on('error', (err) => { + this.#logger.error(`Error: ${err}`); + }); + + res.on('close', () => { + for (const frame of bstream.flush()) { + this.queue.put({ + requestId, + frame, + final: false, + segmentId: requestId, + }); + } + this.queue.close(); + }); + }, + ); + req.write(JSON.stringify(json)); + req.end(); + } +} + +export class SynthesizeStream extends tts.SynthesizeStream { + #opts: TTSOptions; + #logger = log(); + #tokenizer = new tokenize.basic.SentenceTokenizer(undefined, BUFFERED_WORDS_COUNT).stream(); + label = 'deepgram.SynthesizeStream'; + + constructor(tts: TTS, opts: TTSOptions) { + super(tts); + this.#opts = opts; + this.#run(); + } + + async #run() { + const requestId = randomUUID(); + const segmentId = randomUUID(); + let closing = false; + + const sentenceStreamTask = async (ws: WebSocket) => { + for await (const event of this.#tokenizer) { + ws.send( + JSON.stringify({ + type: 'Speak', + text: event.token, + }), + ); + } + + ws.send( + JSON.stringify({ + type: 'Flush', + }), + ); + + closing = true; + ws.send( + JSON.stringify({ + type: 'Close', + }), + ); + }; + + const inputTask = async () => { + for await (const data of this.input) { + if (data === SynthesizeStream.FLUSH_SENTINEL) { + this.#tokenizer.flush(); + continue; + } + this.#tokenizer.pushText(data); + } + this.#tokenizer.endInput(); + this.#tokenizer.close(); + }; + + const recvTask = async (ws: WebSocket) => { + const bstream = new AudioByteStream(this.#opts.sampleRate, NUM_CHANNELS); + + ws.on('message', (data, isBinary) => { + if (!isBinary) { + const message = JSON.parse(data.toString()); + + if (message.type === 'Flushed') { + for (const frame of bstream.flush()) { + this.queue.put({ requestId, segmentId, frame, final: false }); + } + this.queue.put(SynthesizeStream.END_OF_STREAM); + } + + return; + } + + for (const frame of bstream.write(new Int8Array(data as Buffer))) { + this.queue.put({ requestId, segmentId, frame, final: false }); + } + }); + ws.on('error', (error) => { + this.#logger.error(`WebSocket error: ${error}`); + }); + ws.on('close', (code, reason) => { + if (!closing) { + this.#logger.error(`WebSocket closed with code ${code}: ${reason}`); + } + ws.removeAllListeners(); + }); + }; + + const url = new URL(this.#opts.baseUrl!); + url.searchParams.append('sample_rate', this.#opts.sampleRate.toString()); + url.searchParams.append('model', this.#opts.model); + url.searchParams.append('encoding', this.#opts.encoding); + url.protocol = 'wss:'; + + const ws = new WebSocket(url, { + headers: { + [AUTHORIZATION_HEADER]: `Token ${this.#opts.apiKey!}`, + }, + }); + + try { + await new Promise((resolve, reject) => { + ws.on('open', resolve); + ws.on('error', reject); + ws.on('close', (code) => reject(`WebSocket returned ${code}`)); + }); + + await Promise.all([inputTask(), sentenceStreamTask(ws), recvTask(ws)]); + } catch (e) { + throw new Error(`failed to connect to Deepgram: ${e}`); + } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5a507ab3..ac0e636d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -43,7 +43,7 @@ importers: version: 1.13.3(eslint@8.57.0) eslint-plugin-import: specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + version: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-n: specifier: ^16.6.2 version: 16.6.2(eslint@8.57.0) @@ -204,6 +204,9 @@ importers: '@livekit/agents': specifier: workspace:^x version: link:../../agents + '@livekit/agents-plugin-openai': + specifier: ^0.8.1 + version: 0.8.1(@livekit/agents@agents)(@livekit/rtc-node@0.13.2)(zod@3.23.8) '@livekit/agents-plugin-silero': specifier: workspace:^x version: link:../silero @@ -1108,6 +1111,12 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@livekit/agents-plugin-openai@0.8.1': + resolution: {integrity: sha512-gvrhhXQkqFixIGYjh/wFwWce/UnEMQ8DccPiGbo44n6eBkIZrndamFT7OSx5avvOnPwT9qLcTJ0BI7b9pQlYtA==} + peerDependencies: + '@livekit/agents': ^0.6.2x + '@livekit/rtc-node': ^0.13.2 + '@livekit/changesets-changelog-github@0.0.4': resolution: {integrity: sha512-MXaiLYwgkYciZb8G2wkVtZ1pJJzZmVx5cM30Q+ClslrIYyAqQhRbPmZDM79/5CGxb1MTemR/tfOM25tgJgAK0g==} @@ -2817,9 +2826,11 @@ packages: lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -4681,6 +4692,19 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 + '@livekit/agents-plugin-openai@0.8.1(@livekit/agents@agents)(@livekit/rtc-node@0.13.2)(zod@3.23.8)': + dependencies: + '@livekit/agents': link:agents + '@livekit/rtc-node': 0.13.2 + openai: 4.70.2(zod@3.23.8) + sharp: 0.33.5 + ws: 8.17.0 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + - zod + '@livekit/changesets-changelog-github@0.0.4': dependencies: '@changesets/get-github-info': 0.5.2 @@ -5796,8 +5820,8 @@ snapshots: '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) eslint-plugin-react: 7.34.1(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -5814,7 +5838,7 @@ snapshots: eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint-plugin-n@16.6.2(eslint@8.57.0))(eslint-plugin-promise@6.1.1(eslint@8.57.0))(eslint@8.57.0): dependencies: eslint: 8.57.0 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-n: 16.6.2(eslint@8.57.0) eslint-plugin-promise: 6.1.1(eslint@8.57.0) @@ -5831,13 +5855,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 4.3.4 enhanced-resolve: 5.16.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.13.1 @@ -5848,14 +5872,14 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 6.21.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - supports-color @@ -5866,7 +5890,7 @@ snapshots: eslint: 8.57.0 eslint-compat-utils: 0.5.0(eslint@8.57.0) - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -5876,7 +5900,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 From e209a157804955a8f3d4d3d8314af4af5d0378b3 Mon Sep 17 00:00:00 2001 From: Bram Roets Date: Thu, 6 Feb 2025 16:32:25 +0100 Subject: [PATCH 2/3] Fix package.json depedency --- plugins/deepgram/package.json | 2 +- pnpm-lock.yaml | 25 ++----------------------- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/plugins/deepgram/package.json b/plugins/deepgram/package.json index d8ab8d29..9ce99f91 100644 --- a/plugins/deepgram/package.json +++ b/plugins/deepgram/package.json @@ -31,7 +31,7 @@ }, "devDependencies": { "@livekit/agents": "workspace:^x", - "@livekit/agents-plugin-openai": "^0.8.1", + "@livekit/agents-plugin-openai": "workspace:^x", "@livekit/agents-plugin-silero": "workspace:^x", "@livekit/agents-plugins-test": "workspace:^x", "@livekit/rtc-node": "^0.13.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac0e636d..07d55622 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -205,8 +205,8 @@ importers: specifier: workspace:^x version: link:../../agents '@livekit/agents-plugin-openai': - specifier: ^0.8.1 - version: 0.8.1(@livekit/agents@agents)(@livekit/rtc-node@0.13.2)(zod@3.23.8) + specifier: workspace:^x + version: link:../openai '@livekit/agents-plugin-silero': specifier: workspace:^x version: link:../silero @@ -1111,12 +1111,6 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@livekit/agents-plugin-openai@0.8.1': - resolution: {integrity: sha512-gvrhhXQkqFixIGYjh/wFwWce/UnEMQ8DccPiGbo44n6eBkIZrndamFT7OSx5avvOnPwT9qLcTJ0BI7b9pQlYtA==} - peerDependencies: - '@livekit/agents': ^0.6.2x - '@livekit/rtc-node': ^0.13.2 - '@livekit/changesets-changelog-github@0.0.4': resolution: {integrity: sha512-MXaiLYwgkYciZb8G2wkVtZ1pJJzZmVx5cM30Q+ClslrIYyAqQhRbPmZDM79/5CGxb1MTemR/tfOM25tgJgAK0g==} @@ -2826,11 +2820,9 @@ packages: lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} - deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -4692,19 +4684,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - '@livekit/agents-plugin-openai@0.8.1(@livekit/agents@agents)(@livekit/rtc-node@0.13.2)(zod@3.23.8)': - dependencies: - '@livekit/agents': link:agents - '@livekit/rtc-node': 0.13.2 - openai: 4.70.2(zod@3.23.8) - sharp: 0.33.5 - ws: 8.17.0 - transitivePeerDependencies: - - bufferutil - - encoding - - utf-8-validate - - zod - '@livekit/changesets-changelog-github@0.0.4': dependencies: '@changesets/get-github-info': 0.5.2 From 1ef9827c8279438200a56932fd47fd961af52e6f Mon Sep 17 00:00:00 2001 From: Bram Roets Date: Thu, 6 Feb 2025 16:33:03 +0100 Subject: [PATCH 3/3] Remove duplicate test --- plugins/deepgram/src/tts.spec.ts | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 plugins/deepgram/src/tts.spec.ts diff --git a/plugins/deepgram/src/tts.spec.ts b/plugins/deepgram/src/tts.spec.ts deleted file mode 100644 index 605b698e..00000000 --- a/plugins/deepgram/src/tts.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-FileCopyrightText: 2024 LiveKit, Inc. -// -// SPDX-License-Identifier: Apache-2.0 -import { STT } from '@livekit/agents-plugin-openai'; -import { tts } from '@livekit/agents-plugins-test'; -import { describe } from 'vitest'; -import { TTS } from './tts.js'; - -describe( - 'Deepgram', - { timeout: 30_000 }, // For some reason it takes a while before deepgram closes the connection - async () => { - await tts(new TTS(), new STT()); - }, -);