@mastra/voice-deepgram 0.1.3-alpha.8 → 0.1.3
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.
- package/dist/index.cjs +10 -2
- package/dist/index.js +10 -2
- package/package.json +15 -12
- package/.turbo/turbo-build.log +0 -23
- package/CHANGELOG.md +0 -219
- package/__fixtures__/voice-test.m4a +0 -0
- package/eslint.config.js +0 -6
- package/src/index.test.ts +0 -134
- package/src/index.ts +0 -190
- package/src/voices.ts +0 -28
- package/tsconfig.json +0 -5
- package/vitest.config.ts +0 -9
package/dist/index.cjs
CHANGED
|
@@ -79,7 +79,11 @@ var DeepgramVoice = class extends voice.MastraVoice {
|
|
|
79
79
|
if (typeof input !== "string") {
|
|
80
80
|
const chunks = [];
|
|
81
81
|
for await (const chunk of input) {
|
|
82
|
-
|
|
82
|
+
if (typeof chunk === "string") {
|
|
83
|
+
chunks.push(Buffer.from(chunk));
|
|
84
|
+
} else {
|
|
85
|
+
chunks.push(chunk);
|
|
86
|
+
}
|
|
83
87
|
}
|
|
84
88
|
text = Buffer.concat(chunks).toString("utf-8");
|
|
85
89
|
} else {
|
|
@@ -137,7 +141,11 @@ var DeepgramVoice = class extends voice.MastraVoice {
|
|
|
137
141
|
}
|
|
138
142
|
const chunks = [];
|
|
139
143
|
for await (const chunk of audioStream) {
|
|
140
|
-
|
|
144
|
+
if (typeof chunk === "string") {
|
|
145
|
+
chunks.push(Buffer.from(chunk));
|
|
146
|
+
} else {
|
|
147
|
+
chunks.push(chunk);
|
|
148
|
+
}
|
|
141
149
|
}
|
|
142
150
|
const buffer = Buffer.concat(chunks);
|
|
143
151
|
return this.traced(async () => {
|
package/dist/index.js
CHANGED
|
@@ -77,7 +77,11 @@ var DeepgramVoice = class extends MastraVoice {
|
|
|
77
77
|
if (typeof input !== "string") {
|
|
78
78
|
const chunks = [];
|
|
79
79
|
for await (const chunk of input) {
|
|
80
|
-
|
|
80
|
+
if (typeof chunk === "string") {
|
|
81
|
+
chunks.push(Buffer.from(chunk));
|
|
82
|
+
} else {
|
|
83
|
+
chunks.push(chunk);
|
|
84
|
+
}
|
|
81
85
|
}
|
|
82
86
|
text = Buffer.concat(chunks).toString("utf-8");
|
|
83
87
|
} else {
|
|
@@ -135,7 +139,11 @@ var DeepgramVoice = class extends MastraVoice {
|
|
|
135
139
|
}
|
|
136
140
|
const chunks = [];
|
|
137
141
|
for await (const chunk of audioStream) {
|
|
138
|
-
|
|
142
|
+
if (typeof chunk === "string") {
|
|
143
|
+
chunks.push(Buffer.from(chunk));
|
|
144
|
+
} else {
|
|
145
|
+
chunks.push(chunk);
|
|
146
|
+
}
|
|
139
147
|
}
|
|
140
148
|
const buffer = Buffer.concat(chunks);
|
|
141
149
|
return this.traced(async () => {
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/voice-deepgram",
|
|
3
|
-
"version": "0.1.3
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Mastra Deepgram voice integration",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
6
9
|
"main": "dist/index.js",
|
|
7
10
|
"types": "dist/index.d.ts",
|
|
8
11
|
"exports": {
|
|
@@ -19,21 +22,21 @@
|
|
|
19
22
|
"./package.json": "./package.json"
|
|
20
23
|
},
|
|
21
24
|
"dependencies": {
|
|
22
|
-
"@deepgram/sdk": "^3.
|
|
23
|
-
"zod": "^3.24.
|
|
24
|
-
"@mastra/core": "^0.5.0
|
|
25
|
+
"@deepgram/sdk": "^3.11.2",
|
|
26
|
+
"zod": "^3.24.2",
|
|
27
|
+
"@mastra/core": "^0.5.0"
|
|
25
28
|
},
|
|
26
29
|
"devDependencies": {
|
|
27
|
-
"@microsoft/api-extractor": "^7.
|
|
28
|
-
"@types/node": "^22.13.
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"@internal/lint": "0.0.
|
|
30
|
+
"@microsoft/api-extractor": "^7.52.1",
|
|
31
|
+
"@types/node": "^22.13.10",
|
|
32
|
+
"eslint": "^9.22.0",
|
|
33
|
+
"tsup": "^8.4.0",
|
|
34
|
+
"typescript": "^5.8.2",
|
|
35
|
+
"vitest": "^2.1.9",
|
|
36
|
+
"@internal/lint": "0.0.1"
|
|
34
37
|
},
|
|
35
38
|
"scripts": {
|
|
36
|
-
"build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake",
|
|
39
|
+
"build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
|
|
37
40
|
"build:watch": "pnpm build --watch",
|
|
38
41
|
"test": "vitest run",
|
|
39
42
|
"lint": "eslint ."
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @mastra/voice-deepgram@0.1.3-alpha.8 build /home/runner/work/mastra/mastra/voice/deepgram
|
|
3
|
-
> tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake
|
|
4
|
-
|
|
5
|
-
[34mCLI[39m Building entry: src/index.ts
|
|
6
|
-
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
|
-
[34mCLI[39m tsup v8.3.6
|
|
8
|
-
[34mTSC[39m Build start
|
|
9
|
-
[32mTSC[39m ⚡️ Build success in 8012ms
|
|
10
|
-
[34mDTS[39m Build start
|
|
11
|
-
[34mCLI[39m Target: es2022
|
|
12
|
-
Analysis will use the bundled TypeScript version 5.7.3
|
|
13
|
-
[36mWriting package typings: /home/runner/work/mastra/mastra/voice/deepgram/dist/_tsup-dts-rollup.d.ts[39m
|
|
14
|
-
Analysis will use the bundled TypeScript version 5.7.3
|
|
15
|
-
[36mWriting package typings: /home/runner/work/mastra/mastra/voice/deepgram/dist/_tsup-dts-rollup.d.cts[39m
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in 9392ms
|
|
17
|
-
[34mCLI[39m Cleaning output folder
|
|
18
|
-
[34mESM[39m Build start
|
|
19
|
-
[34mCJS[39m Build start
|
|
20
|
-
[32mESM[39m [1mdist/index.js [22m[32m4.40 KB[39m
|
|
21
|
-
[32mESM[39m ⚡️ Build success in 420ms
|
|
22
|
-
[32mCJS[39m [1mdist/index.cjs [22m[32m4.43 KB[39m
|
|
23
|
-
[32mCJS[39m ⚡️ Build success in 421ms
|
package/CHANGELOG.md
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 0.1.3-alpha.8
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- Updated dependencies [506f1d5]
|
|
8
|
-
- @mastra/core@0.5.0-alpha.8
|
|
9
|
-
|
|
10
|
-
## 0.1.3-alpha.7
|
|
11
|
-
|
|
12
|
-
### Patch Changes
|
|
13
|
-
|
|
14
|
-
- Updated dependencies [ee667a2]
|
|
15
|
-
- @mastra/core@0.5.0-alpha.7
|
|
16
|
-
|
|
17
|
-
## 0.1.3-alpha.6
|
|
18
|
-
|
|
19
|
-
### Patch Changes
|
|
20
|
-
|
|
21
|
-
- Updated dependencies [f6678e4]
|
|
22
|
-
- @mastra/core@0.5.0-alpha.6
|
|
23
|
-
|
|
24
|
-
## 0.1.3-alpha.5
|
|
25
|
-
|
|
26
|
-
### Patch Changes
|
|
27
|
-
|
|
28
|
-
- Updated dependencies [22643eb]
|
|
29
|
-
- Updated dependencies [6feb23f]
|
|
30
|
-
- Updated dependencies [f2d6727]
|
|
31
|
-
- Updated dependencies [301e4ee]
|
|
32
|
-
- Updated dependencies [dfbe4e9]
|
|
33
|
-
- Updated dependencies [9e81f35]
|
|
34
|
-
- Updated dependencies [caefaa2]
|
|
35
|
-
- Updated dependencies [c151ae6]
|
|
36
|
-
- Updated dependencies [52e0418]
|
|
37
|
-
- Updated dependencies [03236ec]
|
|
38
|
-
- Updated dependencies [3764e71]
|
|
39
|
-
- Updated dependencies [df982db]
|
|
40
|
-
- Updated dependencies [0461849]
|
|
41
|
-
- Updated dependencies [2259379]
|
|
42
|
-
- Updated dependencies [358f069]
|
|
43
|
-
- @mastra/core@0.5.0-alpha.5
|
|
44
|
-
|
|
45
|
-
## 0.1.3-alpha.4
|
|
46
|
-
|
|
47
|
-
### Patch Changes
|
|
48
|
-
|
|
49
|
-
- Updated dependencies [d79aedf]
|
|
50
|
-
- @mastra/core@0.5.0-alpha.4
|
|
51
|
-
|
|
52
|
-
## 0.1.3-alpha.3
|
|
53
|
-
|
|
54
|
-
### Patch Changes
|
|
55
|
-
|
|
56
|
-
- Updated dependencies [3d0e290]
|
|
57
|
-
- @mastra/core@0.5.0-alpha.3
|
|
58
|
-
|
|
59
|
-
## 0.1.3-alpha.2
|
|
60
|
-
|
|
61
|
-
### Patch Changes
|
|
62
|
-
|
|
63
|
-
- Updated dependencies [02ffb7b]
|
|
64
|
-
- @mastra/core@0.5.0-alpha.2
|
|
65
|
-
|
|
66
|
-
## 0.1.3-alpha.1
|
|
67
|
-
|
|
68
|
-
### Patch Changes
|
|
69
|
-
|
|
70
|
-
- Updated dependencies [dab255b]
|
|
71
|
-
- @mastra/core@0.5.0-alpha.1
|
|
72
|
-
|
|
73
|
-
## 0.1.3-alpha.0
|
|
74
|
-
|
|
75
|
-
### Patch Changes
|
|
76
|
-
|
|
77
|
-
- Updated dependencies [59df7b6]
|
|
78
|
-
- Updated dependencies [29f3a82]
|
|
79
|
-
- Updated dependencies [59df7b6]
|
|
80
|
-
- Updated dependencies [c139344]
|
|
81
|
-
- @mastra/core@0.5.0-alpha.0
|
|
82
|
-
|
|
83
|
-
## 0.1.2
|
|
84
|
-
|
|
85
|
-
### Patch Changes
|
|
86
|
-
|
|
87
|
-
- Updated dependencies [1da20e7]
|
|
88
|
-
- @mastra/core@0.4.4
|
|
89
|
-
|
|
90
|
-
## 0.1.2-alpha.0
|
|
91
|
-
|
|
92
|
-
### Patch Changes
|
|
93
|
-
|
|
94
|
-
- Updated dependencies [1da20e7]
|
|
95
|
-
- @mastra/core@0.4.4-alpha.0
|
|
96
|
-
|
|
97
|
-
## 0.1.1
|
|
98
|
-
|
|
99
|
-
### Patch Changes
|
|
100
|
-
|
|
101
|
-
- bb4f447: Add support for commonjs
|
|
102
|
-
- Updated dependencies [0d185b1]
|
|
103
|
-
- Updated dependencies [ed55f1d]
|
|
104
|
-
- Updated dependencies [06aa827]
|
|
105
|
-
- Updated dependencies [0fd78ac]
|
|
106
|
-
- Updated dependencies [2512a93]
|
|
107
|
-
- Updated dependencies [e62de74]
|
|
108
|
-
- Updated dependencies [0d25b75]
|
|
109
|
-
- Updated dependencies [fd14a3f]
|
|
110
|
-
- Updated dependencies [8d13b14]
|
|
111
|
-
- Updated dependencies [3f369a2]
|
|
112
|
-
- Updated dependencies [3ee4831]
|
|
113
|
-
- Updated dependencies [4d4e1e1]
|
|
114
|
-
- Updated dependencies [bb4f447]
|
|
115
|
-
- Updated dependencies [108793c]
|
|
116
|
-
- Updated dependencies [5f28f44]
|
|
117
|
-
- Updated dependencies [dabecf4]
|
|
118
|
-
- @mastra/core@0.4.3
|
|
119
|
-
|
|
120
|
-
## 0.1.1-alpha.4
|
|
121
|
-
|
|
122
|
-
### Patch Changes
|
|
123
|
-
|
|
124
|
-
- Updated dependencies [dabecf4]
|
|
125
|
-
- @mastra/core@0.4.3-alpha.4
|
|
126
|
-
|
|
127
|
-
## 0.1.1-alpha.3
|
|
128
|
-
|
|
129
|
-
### Patch Changes
|
|
130
|
-
|
|
131
|
-
- bb4f447: Add support for commonjs
|
|
132
|
-
- Updated dependencies [0fd78ac]
|
|
133
|
-
- Updated dependencies [0d25b75]
|
|
134
|
-
- Updated dependencies [fd14a3f]
|
|
135
|
-
- Updated dependencies [3f369a2]
|
|
136
|
-
- Updated dependencies [4d4e1e1]
|
|
137
|
-
- Updated dependencies [bb4f447]
|
|
138
|
-
- @mastra/core@0.4.3-alpha.3
|
|
139
|
-
|
|
140
|
-
## 0.1.1-alpha.2
|
|
141
|
-
|
|
142
|
-
### Patch Changes
|
|
143
|
-
|
|
144
|
-
- Updated dependencies [2512a93]
|
|
145
|
-
- Updated dependencies [e62de74]
|
|
146
|
-
- @mastra/core@0.4.3-alpha.2
|
|
147
|
-
|
|
148
|
-
## 0.1.1-alpha.1
|
|
149
|
-
|
|
150
|
-
### Patch Changes
|
|
151
|
-
|
|
152
|
-
- Updated dependencies [0d185b1]
|
|
153
|
-
- Updated dependencies [ed55f1d]
|
|
154
|
-
- Updated dependencies [8d13b14]
|
|
155
|
-
- Updated dependencies [3ee4831]
|
|
156
|
-
- Updated dependencies [108793c]
|
|
157
|
-
- Updated dependencies [5f28f44]
|
|
158
|
-
- @mastra/core@0.4.3-alpha.1
|
|
159
|
-
|
|
160
|
-
## 0.1.1-alpha.0
|
|
161
|
-
|
|
162
|
-
### Patch Changes
|
|
163
|
-
|
|
164
|
-
- Updated dependencies [06aa827]
|
|
165
|
-
- @mastra/core@0.4.3-alpha.0
|
|
166
|
-
|
|
167
|
-
## 0.1.0
|
|
168
|
-
|
|
169
|
-
### Patch Changes
|
|
170
|
-
|
|
171
|
-
- abe4600: deprecate @mastra/speech-deepgram for @mastra/voice-deepgram
|
|
172
|
-
- 1a10ac1: fix deepgram security issue
|
|
173
|
-
- Updated dependencies [7fceae1]
|
|
174
|
-
- Updated dependencies [8d94c3e]
|
|
175
|
-
- Updated dependencies [99dcdb5]
|
|
176
|
-
- Updated dependencies [6cb63e0]
|
|
177
|
-
- Updated dependencies [f626fbb]
|
|
178
|
-
- Updated dependencies [e752340]
|
|
179
|
-
- Updated dependencies [eb91535]
|
|
180
|
-
- @mastra/core@0.4.2
|
|
181
|
-
|
|
182
|
-
## 0.1.0-alpha.4
|
|
183
|
-
|
|
184
|
-
### Patch Changes
|
|
185
|
-
|
|
186
|
-
- Updated dependencies [8d94c3e]
|
|
187
|
-
- Updated dependencies [99dcdb5]
|
|
188
|
-
- Updated dependencies [e752340]
|
|
189
|
-
- Updated dependencies [eb91535]
|
|
190
|
-
- @mastra/core@0.4.2-alpha.2
|
|
191
|
-
|
|
192
|
-
## 0.1.0-alpha.3
|
|
193
|
-
|
|
194
|
-
### Patch Changes
|
|
195
|
-
|
|
196
|
-
- 1a10ac1: fix deepgram security issue
|
|
197
|
-
- Updated dependencies [6cb63e0]
|
|
198
|
-
- @mastra/core@0.4.2-alpha.1
|
|
199
|
-
|
|
200
|
-
## 0.1.0-alpha.2
|
|
201
|
-
|
|
202
|
-
### Patch Changes
|
|
203
|
-
|
|
204
|
-
- abe4600: deprecate @mastra/speech-deepgram for @mastra/voice-deepgram
|
|
205
|
-
- Updated dependencies [7fceae1]
|
|
206
|
-
- Updated dependencies [f626fbb]
|
|
207
|
-
- @mastra/core@0.4.2-alpha.0
|
|
208
|
-
|
|
209
|
-
## 0.1.0 (2024-XX-XX)
|
|
210
|
-
|
|
211
|
-
This package replaces the deprecated @mastra/speech-deepgram package. All functionality has been migrated to this new package with a more consistent naming scheme.
|
|
212
|
-
|
|
213
|
-
### Changes from @mastra/speech-deepgram
|
|
214
|
-
|
|
215
|
-
- Package renamed from @mastra/speech-deepgram to @mastra/voice-deepgram
|
|
216
|
-
- All functionality remains the same
|
|
217
|
-
- Import paths should be updated from '@mastra/speech-deepgram' to '@mastra/voice-deepgram'
|
|
218
|
-
|
|
219
|
-
For a complete history of changes prior to the rename, please see the changelog of the original package.
|
|
Binary file
|
package/eslint.config.js
DELETED
package/src/index.test.ts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { writeFileSync, mkdirSync, createReadStream } from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { PassThrough } from 'stream';
|
|
4
|
-
import { describe, expect, it, beforeAll } from 'vitest';
|
|
5
|
-
|
|
6
|
-
import { DeepgramVoice } from './index.js';
|
|
7
|
-
|
|
8
|
-
describe('DeepgramVoice Integration Tests', () => {
|
|
9
|
-
let voice: DeepgramVoice;
|
|
10
|
-
const outputDir = path.join(process.cwd(), 'test-outputs');
|
|
11
|
-
|
|
12
|
-
beforeAll(() => {
|
|
13
|
-
try {
|
|
14
|
-
mkdirSync(outputDir, { recursive: true });
|
|
15
|
-
} catch (err) {
|
|
16
|
-
console.log('Directory already exists: ', err);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
voice = new DeepgramVoice({
|
|
20
|
-
speechModel: {
|
|
21
|
-
name: 'aura',
|
|
22
|
-
},
|
|
23
|
-
listeningModel: {
|
|
24
|
-
name: 'whisper',
|
|
25
|
-
},
|
|
26
|
-
speaker: 'asteria-en',
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe('getSpeakers', () => {
|
|
31
|
-
it('should list available voices', async () => {
|
|
32
|
-
const speakers = await voice.getSpeakers();
|
|
33
|
-
const expectedVoiceIds = ['asteria-en', 'stella-en', 'luna-en'];
|
|
34
|
-
expectedVoiceIds.forEach(voiceId => {
|
|
35
|
-
expect(speakers.some(s => s.voiceId === voiceId)).toBe(true);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
describe('speak', () => {
|
|
41
|
-
it('should generate audio and save to file', async () => {
|
|
42
|
-
const audioResult = await voice.speak('Hello World', {
|
|
43
|
-
text: 'Hello World',
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const chunks: Buffer[] = [];
|
|
47
|
-
for await (const chunk of audioResult) {
|
|
48
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
49
|
-
}
|
|
50
|
-
const audioBuffer = Buffer.concat(chunks);
|
|
51
|
-
const outputPath = path.join(outputDir, 'deepgram-speech-test.mp3');
|
|
52
|
-
writeFileSync(outputPath, audioBuffer);
|
|
53
|
-
expect(audioBuffer.length).toBeGreaterThan(0);
|
|
54
|
-
}, 10000);
|
|
55
|
-
|
|
56
|
-
it('should work with different parameters', async () => {
|
|
57
|
-
const audioResult = await voice.speak('Hello World', {
|
|
58
|
-
text: 'Test with parameters',
|
|
59
|
-
speaker: 'luna-en',
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
const chunks: Buffer[] = [];
|
|
63
|
-
for await (const chunk of audioResult) {
|
|
64
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
65
|
-
}
|
|
66
|
-
const audioBuffer = Buffer.concat(chunks);
|
|
67
|
-
const outputPath = path.join(outputDir, 'deepgram-speech-test-params.mp3');
|
|
68
|
-
writeFileSync(outputPath, audioBuffer);
|
|
69
|
-
expect(audioBuffer.length).toBeGreaterThan(0);
|
|
70
|
-
}, 10000);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// Error cases
|
|
74
|
-
describe('error handling', () => {
|
|
75
|
-
it('should handle invalid voice names', async () => {
|
|
76
|
-
await expect(voice.speak('Test', { speaker: 'invalid_voice' })).rejects.toThrow();
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should handle empty text', async () => {
|
|
80
|
-
await expect(voice.speak('', { speaker: 'asteria-en' })).rejects.toThrow('Input text is empty');
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('should handle whitespace-only text', async () => {
|
|
84
|
-
await expect(voice.speak(' \n\t ', { speaker: 'asteria-en' })).rejects.toThrow('Input text is empty');
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
describe('listen', () => {
|
|
89
|
-
it('should transcribe audio buffer', async () => {
|
|
90
|
-
// First generate some audio to transcribe
|
|
91
|
-
const audioResult = await voice.speak('This is a test of transcription');
|
|
92
|
-
|
|
93
|
-
// Collect audio chunks
|
|
94
|
-
const chunks: Buffer[] = [];
|
|
95
|
-
for await (const chunk of audioResult) {
|
|
96
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
97
|
-
}
|
|
98
|
-
const audioBuffer = Buffer.concat(chunks);
|
|
99
|
-
|
|
100
|
-
// Create stream from the buffer
|
|
101
|
-
const stream = new PassThrough();
|
|
102
|
-
stream.end(audioBuffer);
|
|
103
|
-
const result = await voice.listen(stream);
|
|
104
|
-
|
|
105
|
-
expect(typeof result).toBe('string');
|
|
106
|
-
expect(result.toLowerCase()).toContain('test');
|
|
107
|
-
expect(result.toLowerCase()).toContain('transcription');
|
|
108
|
-
}, 15000);
|
|
109
|
-
|
|
110
|
-
it('should transcribe audio from fixture file', async () => {
|
|
111
|
-
const fixturePath = path.join(process.cwd(), '__fixtures__', 'voice-test.m4a');
|
|
112
|
-
const audioStream = createReadStream(fixturePath);
|
|
113
|
-
|
|
114
|
-
console.log('listening to audio stream');
|
|
115
|
-
const text = await voice.listen(audioStream, {
|
|
116
|
-
filetype: 'm4a',
|
|
117
|
-
});
|
|
118
|
-
console.log('text', text);
|
|
119
|
-
|
|
120
|
-
expect(text).toBeTruthy();
|
|
121
|
-
console.log(text);
|
|
122
|
-
expect(typeof text).toBe('string');
|
|
123
|
-
expect(text.length).toBeGreaterThan(0);
|
|
124
|
-
}, 15000);
|
|
125
|
-
|
|
126
|
-
it('should handle invalid audio', async () => {
|
|
127
|
-
const invalidAudio = Buffer.from('not valid audio');
|
|
128
|
-
const stream = new PassThrough();
|
|
129
|
-
stream.end(invalidAudio);
|
|
130
|
-
|
|
131
|
-
await expect(voice.listen(stream)).rejects.toThrow();
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { PassThrough } from 'stream';
|
|
2
|
-
|
|
3
|
-
import { createClient } from '@deepgram/sdk';
|
|
4
|
-
import { MastraVoice } from '@mastra/core/voice';
|
|
5
|
-
|
|
6
|
-
import { DEEPGRAM_VOICES } from './voices';
|
|
7
|
-
import type { DeepgramVoiceId, DeepgramModel } from './voices';
|
|
8
|
-
|
|
9
|
-
interface DeepgramVoiceConfig {
|
|
10
|
-
name?: DeepgramModel;
|
|
11
|
-
apiKey?: string;
|
|
12
|
-
properties?: Record<string, any>;
|
|
13
|
-
language?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export class DeepgramVoice extends MastraVoice {
|
|
17
|
-
private speechClient?: ReturnType<typeof createClient>;
|
|
18
|
-
private listeningClient?: ReturnType<typeof createClient>;
|
|
19
|
-
|
|
20
|
-
constructor({
|
|
21
|
-
speechModel,
|
|
22
|
-
listeningModel,
|
|
23
|
-
speaker,
|
|
24
|
-
}: { speechModel?: DeepgramVoiceConfig; listeningModel?: DeepgramVoiceConfig; speaker?: DeepgramVoiceId } = {}) {
|
|
25
|
-
const defaultApiKey = process.env.DEEPGRAM_API_KEY;
|
|
26
|
-
|
|
27
|
-
const defaultSpeechModel = {
|
|
28
|
-
name: 'aura',
|
|
29
|
-
apiKey: defaultApiKey,
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const defaultListeningModel = {
|
|
33
|
-
name: 'nova',
|
|
34
|
-
apiKey: defaultApiKey,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
super({
|
|
38
|
-
speechModel: {
|
|
39
|
-
name: speechModel?.name ?? defaultSpeechModel.name,
|
|
40
|
-
apiKey: speechModel?.apiKey ?? defaultSpeechModel.apiKey,
|
|
41
|
-
},
|
|
42
|
-
listeningModel: {
|
|
43
|
-
name: listeningModel?.name ?? defaultListeningModel.name,
|
|
44
|
-
apiKey: listeningModel?.apiKey ?? defaultListeningModel.apiKey,
|
|
45
|
-
},
|
|
46
|
-
speaker,
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const speechApiKey = speechModel?.apiKey || defaultApiKey;
|
|
50
|
-
const listeningApiKey = listeningModel?.apiKey || defaultApiKey;
|
|
51
|
-
|
|
52
|
-
if (!speechApiKey && !listeningApiKey) {
|
|
53
|
-
throw new Error('At least one of DEEPGRAM_API_KEY, speechModel.apiKey, or listeningModel.apiKey must be set');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (speechApiKey) {
|
|
57
|
-
this.speechClient = createClient(speechApiKey);
|
|
58
|
-
}
|
|
59
|
-
if (listeningApiKey) {
|
|
60
|
-
this.listeningClient = createClient(listeningApiKey);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
this.speaker = speaker || 'asteria-en';
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async getSpeakers() {
|
|
67
|
-
return this.traced(async () => {
|
|
68
|
-
return DEEPGRAM_VOICES.map(voice => ({
|
|
69
|
-
voiceId: voice,
|
|
70
|
-
}));
|
|
71
|
-
}, 'voice.deepgram.getSpeakers')();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async speak(
|
|
75
|
-
input: string | NodeJS.ReadableStream,
|
|
76
|
-
options?: {
|
|
77
|
-
speaker?: string;
|
|
78
|
-
[key: string]: any;
|
|
79
|
-
},
|
|
80
|
-
): Promise<NodeJS.ReadableStream> {
|
|
81
|
-
if (!this.speechClient) {
|
|
82
|
-
throw new Error('Deepgram speech client not configured');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
let text: string;
|
|
86
|
-
if (typeof input !== 'string') {
|
|
87
|
-
const chunks: Buffer[] = [];
|
|
88
|
-
for await (const chunk of input) {
|
|
89
|
-
chunks.push(Buffer.from(chunk));
|
|
90
|
-
}
|
|
91
|
-
text = Buffer.concat(chunks).toString('utf-8');
|
|
92
|
-
} else {
|
|
93
|
-
text = input;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (text.trim().length === 0) {
|
|
97
|
-
throw new Error('Input text is empty');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return this.traced(async () => {
|
|
101
|
-
if (!this.speechClient) {
|
|
102
|
-
throw new Error('No speech client configured');
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
let model;
|
|
106
|
-
if (options?.speaker) {
|
|
107
|
-
model = this.speechModel?.name + '-' + options.speaker;
|
|
108
|
-
} else if (this.speaker) {
|
|
109
|
-
model = this.speechModel?.name + '-' + this.speaker;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const speakClient = this.speechClient.speak;
|
|
113
|
-
const response = await speakClient.request(
|
|
114
|
-
{ text },
|
|
115
|
-
{
|
|
116
|
-
model,
|
|
117
|
-
...options,
|
|
118
|
-
},
|
|
119
|
-
);
|
|
120
|
-
|
|
121
|
-
const webStream = await response.getStream();
|
|
122
|
-
if (!webStream) {
|
|
123
|
-
throw new Error('No stream returned from Deepgram');
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const reader = webStream.getReader();
|
|
127
|
-
const nodeStream = new PassThrough();
|
|
128
|
-
|
|
129
|
-
// Add error handling for the stream processing
|
|
130
|
-
(async () => {
|
|
131
|
-
try {
|
|
132
|
-
while (true) {
|
|
133
|
-
const { done, value } = await reader.read();
|
|
134
|
-
if (done) {
|
|
135
|
-
nodeStream.end();
|
|
136
|
-
break;
|
|
137
|
-
}
|
|
138
|
-
nodeStream.write(value);
|
|
139
|
-
}
|
|
140
|
-
} catch (error) {
|
|
141
|
-
nodeStream.destroy(error as Error);
|
|
142
|
-
}
|
|
143
|
-
})().catch(error => {
|
|
144
|
-
nodeStream.destroy(error as Error);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
return nodeStream;
|
|
148
|
-
}, 'voice.deepgram.speak')();
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
async listen(
|
|
152
|
-
audioStream: NodeJS.ReadableStream,
|
|
153
|
-
options?: {
|
|
154
|
-
[key: string]: any;
|
|
155
|
-
},
|
|
156
|
-
): Promise<string> {
|
|
157
|
-
if (!this.listeningClient) {
|
|
158
|
-
throw new Error('Deepgram listening client not configured');
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const chunks: Buffer[] = [];
|
|
162
|
-
for await (const chunk of audioStream) {
|
|
163
|
-
chunks.push(Buffer.from(chunk));
|
|
164
|
-
}
|
|
165
|
-
const buffer = Buffer.concat(chunks);
|
|
166
|
-
|
|
167
|
-
return this.traced(async () => {
|
|
168
|
-
if (!this.listeningClient) {
|
|
169
|
-
throw new Error('No listening client configured');
|
|
170
|
-
}
|
|
171
|
-
const { result, error } = await this.listeningClient.listen.prerecorded.transcribeFile(buffer, {
|
|
172
|
-
model: this.listeningModel?.name,
|
|
173
|
-
...options,
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
if (error) {
|
|
177
|
-
throw error;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const transcript = result.results?.channels?.[0]?.alternatives?.[0]?.transcript;
|
|
181
|
-
if (!transcript) {
|
|
182
|
-
throw new Error('No transcript found in Deepgram response');
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
return transcript;
|
|
186
|
-
}, 'voice.deepgram.listen')();
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export type { DeepgramVoiceConfig, DeepgramVoiceId, DeepgramModel };
|
package/src/voices.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* List of available Deepgram voice models for text-to-speech
|
|
3
|
-
* Each voice is designed for specific use cases and languages
|
|
4
|
-
* Format: {name}-{language} (e.g. asteria-en)
|
|
5
|
-
*/
|
|
6
|
-
export const DEEPGRAM_VOICES = [
|
|
7
|
-
'asteria-en',
|
|
8
|
-
'luna-en',
|
|
9
|
-
'stella-en',
|
|
10
|
-
'athena-en',
|
|
11
|
-
'hera-en',
|
|
12
|
-
'orion-en',
|
|
13
|
-
'arcas-en',
|
|
14
|
-
'perseus-en',
|
|
15
|
-
'angus-en',
|
|
16
|
-
'orpheus-en',
|
|
17
|
-
'helios-en',
|
|
18
|
-
'zeus-en',
|
|
19
|
-
] as const;
|
|
20
|
-
|
|
21
|
-
export type DeepgramVoiceId = (typeof DEEPGRAM_VOICES)[number];
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* List of available Deepgram models for text-to-speech and speech-to-text
|
|
25
|
-
*/
|
|
26
|
-
export const DEEPGRAM_MODELS = ['aura', 'whisper', 'base', 'enhanced', 'nova', 'nova-2', 'nova-3'] as const;
|
|
27
|
-
|
|
28
|
-
export type DeepgramModel = (typeof DEEPGRAM_MODELS)[number];
|
package/tsconfig.json
DELETED