@mastra/voice-elevenlabs 0.1.3-alpha.9 → 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 -234
- package/eslint.config.js +0 -6
- package/src/index.test.ts +0 -141
- package/src/index.ts +0 -185
- package/tsconfig.json +0 -5
- package/vitest.config.ts +0 -8
package/dist/index.cjs
CHANGED
|
@@ -63,7 +63,11 @@ var ElevenLabsVoice = class extends voice.MastraVoice {
|
|
|
63
63
|
async streamToString(stream) {
|
|
64
64
|
const chunks = [];
|
|
65
65
|
for await (const chunk of stream) {
|
|
66
|
-
|
|
66
|
+
if (typeof chunk === "string") {
|
|
67
|
+
chunks.push(Buffer.from(chunk));
|
|
68
|
+
} else {
|
|
69
|
+
chunks.push(chunk);
|
|
70
|
+
}
|
|
67
71
|
}
|
|
68
72
|
return Buffer.concat(chunks).toString("utf-8");
|
|
69
73
|
}
|
|
@@ -117,7 +121,11 @@ var ElevenLabsVoice = class extends voice.MastraVoice {
|
|
|
117
121
|
const res = await this.traced(async () => {
|
|
118
122
|
const chunks = [];
|
|
119
123
|
for await (const chunk of input) {
|
|
120
|
-
|
|
124
|
+
if (typeof chunk === "string") {
|
|
125
|
+
chunks.push(Buffer.from(chunk));
|
|
126
|
+
} else {
|
|
127
|
+
chunks.push(chunk);
|
|
128
|
+
}
|
|
121
129
|
}
|
|
122
130
|
const buffer$1 = Buffer.concat(chunks);
|
|
123
131
|
const { language_code, tag_audio_events, num_speakers, filetype, ...requestOptions } = options || {};
|
package/dist/index.js
CHANGED
|
@@ -61,7 +61,11 @@ var ElevenLabsVoice = class extends MastraVoice {
|
|
|
61
61
|
async streamToString(stream) {
|
|
62
62
|
const chunks = [];
|
|
63
63
|
for await (const chunk of stream) {
|
|
64
|
-
|
|
64
|
+
if (typeof chunk === "string") {
|
|
65
|
+
chunks.push(Buffer.from(chunk));
|
|
66
|
+
} else {
|
|
67
|
+
chunks.push(chunk);
|
|
68
|
+
}
|
|
65
69
|
}
|
|
66
70
|
return Buffer.concat(chunks).toString("utf-8");
|
|
67
71
|
}
|
|
@@ -115,7 +119,11 @@ var ElevenLabsVoice = class extends MastraVoice {
|
|
|
115
119
|
const res = await this.traced(async () => {
|
|
116
120
|
const chunks = [];
|
|
117
121
|
for await (const chunk of input) {
|
|
118
|
-
|
|
122
|
+
if (typeof chunk === "string") {
|
|
123
|
+
chunks.push(Buffer.from(chunk));
|
|
124
|
+
} else {
|
|
125
|
+
chunks.push(chunk);
|
|
126
|
+
}
|
|
119
127
|
}
|
|
120
128
|
const buffer = Buffer.concat(chunks);
|
|
121
129
|
const { language_code, tag_audio_events, num_speakers, filetype, ...requestOptions } = options || {};
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/voice-elevenlabs",
|
|
3
|
-
"version": "0.1.3
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Mastra ElevenLabs 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
|
-
"elevenlabs": "^1.
|
|
23
|
-
"zod": "^3.24.
|
|
24
|
-
"@mastra/core": "^0.5.0
|
|
25
|
+
"elevenlabs": "^1.54.0",
|
|
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": "tsup 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-elevenlabs@0.1.3-alpha.9 build /home/runner/work/mastra/mastra/voice/elevenlabs
|
|
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 8109ms
|
|
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/elevenlabs/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/elevenlabs/dist/_tsup-dts-rollup.d.cts[39m
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in 8752ms
|
|
17
|
-
[34mCLI[39m Cleaning output folder
|
|
18
|
-
[34mESM[39m Build start
|
|
19
|
-
[34mCJS[39m Build start
|
|
20
|
-
[32mESM[39m [1mdist/index.js [22m[32m5.00 KB[39m
|
|
21
|
-
[32mESM[39m ⚡️ Build success in 324ms
|
|
22
|
-
[32mCJS[39m [1mdist/index.cjs [22m[32m5.04 KB[39m
|
|
23
|
-
[32mCJS[39m ⚡️ Build success in 323ms
|
package/CHANGELOG.md
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
# @mastra/voice-elevenlabs
|
|
2
|
-
|
|
3
|
-
## 0.1.3-alpha.9
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- Updated dependencies [e9fbac5]
|
|
8
|
-
- Updated dependencies [1e8bcbc]
|
|
9
|
-
- Updated dependencies [aeb5e36]
|
|
10
|
-
- Updated dependencies [f2301de]
|
|
11
|
-
- @mastra/core@0.5.0-alpha.9
|
|
12
|
-
|
|
13
|
-
## 0.1.3-alpha.8
|
|
14
|
-
|
|
15
|
-
### Patch Changes
|
|
16
|
-
|
|
17
|
-
- Updated dependencies [506f1d5]
|
|
18
|
-
- @mastra/core@0.5.0-alpha.8
|
|
19
|
-
|
|
20
|
-
## 0.1.3-alpha.7
|
|
21
|
-
|
|
22
|
-
### Patch Changes
|
|
23
|
-
|
|
24
|
-
- Updated dependencies [ee667a2]
|
|
25
|
-
- @mastra/core@0.5.0-alpha.7
|
|
26
|
-
|
|
27
|
-
## 0.1.3-alpha.6
|
|
28
|
-
|
|
29
|
-
### Patch Changes
|
|
30
|
-
|
|
31
|
-
- Updated dependencies [f6678e4]
|
|
32
|
-
- @mastra/core@0.5.0-alpha.6
|
|
33
|
-
|
|
34
|
-
## 0.1.3-alpha.5
|
|
35
|
-
|
|
36
|
-
### Patch Changes
|
|
37
|
-
|
|
38
|
-
- Updated dependencies [22643eb]
|
|
39
|
-
- Updated dependencies [6feb23f]
|
|
40
|
-
- Updated dependencies [f2d6727]
|
|
41
|
-
- Updated dependencies [301e4ee]
|
|
42
|
-
- Updated dependencies [dfbe4e9]
|
|
43
|
-
- Updated dependencies [9e81f35]
|
|
44
|
-
- Updated dependencies [caefaa2]
|
|
45
|
-
- Updated dependencies [c151ae6]
|
|
46
|
-
- Updated dependencies [52e0418]
|
|
47
|
-
- Updated dependencies [03236ec]
|
|
48
|
-
- Updated dependencies [3764e71]
|
|
49
|
-
- Updated dependencies [df982db]
|
|
50
|
-
- Updated dependencies [0461849]
|
|
51
|
-
- Updated dependencies [2259379]
|
|
52
|
-
- Updated dependencies [358f069]
|
|
53
|
-
- @mastra/core@0.5.0-alpha.5
|
|
54
|
-
|
|
55
|
-
## 0.1.3-alpha.4
|
|
56
|
-
|
|
57
|
-
### Patch Changes
|
|
58
|
-
|
|
59
|
-
- Updated dependencies [d79aedf]
|
|
60
|
-
- @mastra/core@0.5.0-alpha.4
|
|
61
|
-
|
|
62
|
-
## 0.1.3-alpha.3
|
|
63
|
-
|
|
64
|
-
### Patch Changes
|
|
65
|
-
|
|
66
|
-
- Updated dependencies [3d0e290]
|
|
67
|
-
- @mastra/core@0.5.0-alpha.3
|
|
68
|
-
|
|
69
|
-
## 0.1.3-alpha.2
|
|
70
|
-
|
|
71
|
-
### Patch Changes
|
|
72
|
-
|
|
73
|
-
- Updated dependencies [02ffb7b]
|
|
74
|
-
- @mastra/core@0.5.0-alpha.2
|
|
75
|
-
|
|
76
|
-
## 0.1.3-alpha.1
|
|
77
|
-
|
|
78
|
-
### Patch Changes
|
|
79
|
-
|
|
80
|
-
- Updated dependencies [dab255b]
|
|
81
|
-
- @mastra/core@0.5.0-alpha.1
|
|
82
|
-
|
|
83
|
-
## 0.1.3-alpha.0
|
|
84
|
-
|
|
85
|
-
### Patch Changes
|
|
86
|
-
|
|
87
|
-
- Updated dependencies [59df7b6]
|
|
88
|
-
- Updated dependencies [29f3a82]
|
|
89
|
-
- Updated dependencies [59df7b6]
|
|
90
|
-
- Updated dependencies [c139344]
|
|
91
|
-
- @mastra/core@0.5.0-alpha.0
|
|
92
|
-
|
|
93
|
-
## 0.1.2
|
|
94
|
-
|
|
95
|
-
### Patch Changes
|
|
96
|
-
|
|
97
|
-
- Updated dependencies [1da20e7]
|
|
98
|
-
- @mastra/core@0.4.4
|
|
99
|
-
|
|
100
|
-
## 0.1.2-alpha.0
|
|
101
|
-
|
|
102
|
-
### Patch Changes
|
|
103
|
-
|
|
104
|
-
- Updated dependencies [1da20e7]
|
|
105
|
-
- @mastra/core@0.4.4-alpha.0
|
|
106
|
-
|
|
107
|
-
## 0.1.1
|
|
108
|
-
|
|
109
|
-
### Patch Changes
|
|
110
|
-
|
|
111
|
-
- bb4f447: Add support for commonjs
|
|
112
|
-
- 705d69b: Add STT for ElevenlabsVoice
|
|
113
|
-
- Updated dependencies [0d185b1]
|
|
114
|
-
- Updated dependencies [ed55f1d]
|
|
115
|
-
- Updated dependencies [06aa827]
|
|
116
|
-
- Updated dependencies [0fd78ac]
|
|
117
|
-
- Updated dependencies [2512a93]
|
|
118
|
-
- Updated dependencies [e62de74]
|
|
119
|
-
- Updated dependencies [0d25b75]
|
|
120
|
-
- Updated dependencies [fd14a3f]
|
|
121
|
-
- Updated dependencies [8d13b14]
|
|
122
|
-
- Updated dependencies [3f369a2]
|
|
123
|
-
- Updated dependencies [3ee4831]
|
|
124
|
-
- Updated dependencies [4d4e1e1]
|
|
125
|
-
- Updated dependencies [bb4f447]
|
|
126
|
-
- Updated dependencies [108793c]
|
|
127
|
-
- Updated dependencies [5f28f44]
|
|
128
|
-
- Updated dependencies [dabecf4]
|
|
129
|
-
- @mastra/core@0.4.3
|
|
130
|
-
|
|
131
|
-
## 0.1.1-alpha.4
|
|
132
|
-
|
|
133
|
-
### Patch Changes
|
|
134
|
-
|
|
135
|
-
- Updated dependencies [dabecf4]
|
|
136
|
-
- @mastra/core@0.4.3-alpha.4
|
|
137
|
-
|
|
138
|
-
## 0.1.1-alpha.3
|
|
139
|
-
|
|
140
|
-
### Patch Changes
|
|
141
|
-
|
|
142
|
-
- bb4f447: Add support for commonjs
|
|
143
|
-
- Updated dependencies [0fd78ac]
|
|
144
|
-
- Updated dependencies [0d25b75]
|
|
145
|
-
- Updated dependencies [fd14a3f]
|
|
146
|
-
- Updated dependencies [3f369a2]
|
|
147
|
-
- Updated dependencies [4d4e1e1]
|
|
148
|
-
- Updated dependencies [bb4f447]
|
|
149
|
-
- @mastra/core@0.4.3-alpha.3
|
|
150
|
-
|
|
151
|
-
## 0.1.1-alpha.2
|
|
152
|
-
|
|
153
|
-
### Patch Changes
|
|
154
|
-
|
|
155
|
-
- Updated dependencies [2512a93]
|
|
156
|
-
- Updated dependencies [e62de74]
|
|
157
|
-
- @mastra/core@0.4.3-alpha.2
|
|
158
|
-
|
|
159
|
-
## 0.1.1-alpha.1
|
|
160
|
-
|
|
161
|
-
### Patch Changes
|
|
162
|
-
|
|
163
|
-
- 705d69b: Add STT for ElevenlabsVoice
|
|
164
|
-
- Updated dependencies [0d185b1]
|
|
165
|
-
- Updated dependencies [ed55f1d]
|
|
166
|
-
- Updated dependencies [8d13b14]
|
|
167
|
-
- Updated dependencies [3ee4831]
|
|
168
|
-
- Updated dependencies [108793c]
|
|
169
|
-
- Updated dependencies [5f28f44]
|
|
170
|
-
- @mastra/core@0.4.3-alpha.1
|
|
171
|
-
|
|
172
|
-
## 0.1.1-alpha.0
|
|
173
|
-
|
|
174
|
-
### Patch Changes
|
|
175
|
-
|
|
176
|
-
- Updated dependencies [06aa827]
|
|
177
|
-
- @mastra/core@0.4.3-alpha.0
|
|
178
|
-
|
|
179
|
-
## 0.1.0
|
|
180
|
-
|
|
181
|
-
### Patch Changes
|
|
182
|
-
|
|
183
|
-
- f626fbb: deprecate @mastra/speech-deepgram for @mastra/voice-deepgram
|
|
184
|
-
- Updated dependencies [7fceae1]
|
|
185
|
-
- Updated dependencies [8d94c3e]
|
|
186
|
-
- Updated dependencies [99dcdb5]
|
|
187
|
-
- Updated dependencies [6cb63e0]
|
|
188
|
-
- Updated dependencies [f626fbb]
|
|
189
|
-
- Updated dependencies [e752340]
|
|
190
|
-
- Updated dependencies [eb91535]
|
|
191
|
-
- @mastra/core@0.4.2
|
|
192
|
-
|
|
193
|
-
## 0.1.0-alpha.4
|
|
194
|
-
|
|
195
|
-
### Patch Changes
|
|
196
|
-
|
|
197
|
-
- Updated dependencies [8d94c3e]
|
|
198
|
-
- Updated dependencies [99dcdb5]
|
|
199
|
-
- Updated dependencies [e752340]
|
|
200
|
-
- Updated dependencies [eb91535]
|
|
201
|
-
- @mastra/core@0.4.2-alpha.2
|
|
202
|
-
|
|
203
|
-
## 0.1.0-alpha.3
|
|
204
|
-
|
|
205
|
-
### Patch Changes
|
|
206
|
-
|
|
207
|
-
- Updated dependencies [6cb63e0]
|
|
208
|
-
- @mastra/core@0.4.2-alpha.1
|
|
209
|
-
|
|
210
|
-
## 0.1.0-alpha.2
|
|
211
|
-
|
|
212
|
-
### Patch Changes
|
|
213
|
-
|
|
214
|
-
- f626fbb: deprecate @mastra/speech-deepgram for @mastra/voice-deepgram
|
|
215
|
-
- Updated dependencies [7fceae1]
|
|
216
|
-
- Updated dependencies [f626fbb]
|
|
217
|
-
- @mastra/core@0.4.2-alpha.0
|
|
218
|
-
|
|
219
|
-
## 0.1.0 (2024-XX-XX)
|
|
220
|
-
|
|
221
|
-
This package replaces the deprecated @mastra/speech-elevenlabs package. All functionality has been migrated to this new package with a more consistent naming scheme.
|
|
222
|
-
|
|
223
|
-
### Changes from @mastra/speech-elevenlabs
|
|
224
|
-
|
|
225
|
-
- Package renamed from @mastra/speech-elevenlabs to @mastra/voice-elevenlabs
|
|
226
|
-
- API changes:
|
|
227
|
-
- `ElevenLabsTTS` class renamed to `ElevenLabsVoice`
|
|
228
|
-
- `generate()` method renamed to `speak()`
|
|
229
|
-
- `voices()` method renamed to `getSpeakers()`
|
|
230
|
-
- Constructor configuration simplified
|
|
231
|
-
- All core functionality remains the same
|
|
232
|
-
- Import paths should be updated from '@mastra/speech-elevenlabs' to '@mastra/voice-elevenlabs'
|
|
233
|
-
|
|
234
|
-
For a complete history of changes prior to the rename, please see the changelog of the original package.
|
package/eslint.config.js
DELETED
package/src/index.test.ts
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { createWriteStream, writeFileSync, mkdirSync, createReadStream } from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { describe, expect, it, beforeAll } from 'vitest';
|
|
4
|
-
|
|
5
|
-
import { ElevenLabsVoice } from './index.js';
|
|
6
|
-
|
|
7
|
-
describe('ElevenLabsVoice Integration Tests', () => {
|
|
8
|
-
let voice: ElevenLabsVoice;
|
|
9
|
-
const outputDir = path.join(process.cwd(), 'test-outputs');
|
|
10
|
-
|
|
11
|
-
beforeAll(() => {
|
|
12
|
-
try {
|
|
13
|
-
mkdirSync(outputDir, { recursive: true });
|
|
14
|
-
} catch (err) {
|
|
15
|
-
console.log('Directory already exists: ', err);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
voice = new ElevenLabsVoice({
|
|
19
|
-
speechModel: {
|
|
20
|
-
name: 'eleven_multilingual_v2',
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
describe('getSpeakers', () => {
|
|
26
|
-
it('should list available speakers', async () => {
|
|
27
|
-
const speakers = await voice.getSpeakers();
|
|
28
|
-
console.log(speakers);
|
|
29
|
-
expect(speakers.length).toBeGreaterThan(0);
|
|
30
|
-
expect(speakers[0]).toHaveProperty('voiceId');
|
|
31
|
-
expect(speakers[0]).toHaveProperty('name');
|
|
32
|
-
expect(speakers[0]).toHaveProperty('language');
|
|
33
|
-
expect(speakers[0]).toHaveProperty('gender');
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
describe('speak', () => {
|
|
38
|
-
it('should speak with default values', async () => {
|
|
39
|
-
const defaultVoice = new ElevenLabsVoice();
|
|
40
|
-
const audioStream = await defaultVoice.speak('Hello World, how are you?');
|
|
41
|
-
|
|
42
|
-
const outputPath = path.join(outputDir, 'elevenlabs-speech-test-default.mp3');
|
|
43
|
-
const fileStream = createWriteStream(outputPath);
|
|
44
|
-
const chunks: Buffer[] = [];
|
|
45
|
-
|
|
46
|
-
audioStream.on('data', (chunk: Buffer) => chunks.push(chunk));
|
|
47
|
-
audioStream.pipe(fileStream);
|
|
48
|
-
writeFileSync(outputPath, Buffer.concat(chunks));
|
|
49
|
-
}, 10000);
|
|
50
|
-
|
|
51
|
-
it('should generate audio from text and save to file', async () => {
|
|
52
|
-
const speakers = await voice.getSpeakers();
|
|
53
|
-
const speaker = speakers[0].voiceId;
|
|
54
|
-
|
|
55
|
-
const audioStream = await voice.speak('Hello World', { speaker });
|
|
56
|
-
|
|
57
|
-
return new Promise((resolve, reject) => {
|
|
58
|
-
const outputPath = path.join(outputDir, 'elevenlabs-speech-test.mp3');
|
|
59
|
-
const fileStream = createWriteStream(outputPath);
|
|
60
|
-
const chunks: Buffer[] = [];
|
|
61
|
-
|
|
62
|
-
audioStream.on('data', (chunk: Buffer) => chunks.push(chunk));
|
|
63
|
-
audioStream.pipe(fileStream);
|
|
64
|
-
|
|
65
|
-
fileStream.on('finish', () => {
|
|
66
|
-
expect(chunks.length).toBeGreaterThan(0);
|
|
67
|
-
resolve(undefined);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
audioStream.on('error', reject);
|
|
71
|
-
fileStream.on('error', reject);
|
|
72
|
-
});
|
|
73
|
-
}, 10000);
|
|
74
|
-
|
|
75
|
-
it('should work with different speaker', async () => {
|
|
76
|
-
const speakers = await voice.getSpeakers();
|
|
77
|
-
const speaker = speakers[1]?.voiceId;
|
|
78
|
-
|
|
79
|
-
const audioStream = await voice.speak('Test with different speaker', { speaker });
|
|
80
|
-
|
|
81
|
-
return new Promise((resolve, reject) => {
|
|
82
|
-
const outputPath = path.join(outputDir, 'elevenlabs-speech-test-params.mp3');
|
|
83
|
-
const fileStream = createWriteStream(outputPath);
|
|
84
|
-
const chunks: Buffer[] = [];
|
|
85
|
-
|
|
86
|
-
audioStream.on('data', (chunk: Buffer) => chunks.push(chunk));
|
|
87
|
-
audioStream.pipe(fileStream);
|
|
88
|
-
|
|
89
|
-
fileStream.on('finish', () => {
|
|
90
|
-
expect(chunks.length).toBeGreaterThan(0);
|
|
91
|
-
resolve(undefined);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
audioStream.on('error', reject);
|
|
95
|
-
fileStream.on('error', reject);
|
|
96
|
-
});
|
|
97
|
-
}, 10000);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
describe('listen', () => {
|
|
101
|
-
it('should convert audio to text', async () => {
|
|
102
|
-
const outputPath = path.join(outputDir, 'elevenlabs-speech-test-params.mp3');
|
|
103
|
-
const audio = createReadStream(outputPath);
|
|
104
|
-
const result = await voice.listen(audio);
|
|
105
|
-
|
|
106
|
-
if (typeof result !== 'string') {
|
|
107
|
-
return expect(result).toBeInstanceOf(String);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
expect(typeof result).toBe('string');
|
|
111
|
-
expect(result.length).toBeGreaterThan(0);
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it('should handle API errors gracefully', async () => {
|
|
115
|
-
// Create a voice instance with an invalid API key to force an error
|
|
116
|
-
const invalidVoice = new ElevenLabsVoice({
|
|
117
|
-
listeningModel: {
|
|
118
|
-
name: 'eleven_multilingual_v2',
|
|
119
|
-
apiKey: 'invalid-api-key',
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
const outputPath = path.join(outputDir, 'elevenlabs-speech-test-params.mp3');
|
|
124
|
-
const audio = createReadStream(outputPath);
|
|
125
|
-
|
|
126
|
-
// The API call should fail with an authentication error
|
|
127
|
-
await expect(invalidVoice.listen(audio)).rejects.toThrow();
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('should handle invalid audio input', async () => {
|
|
131
|
-
// Create a path to a non-existent file
|
|
132
|
-
const nonExistentPath = path.join(outputDir, 'non-existent-file.mp3');
|
|
133
|
-
|
|
134
|
-
// Attempting to create a read stream from a non-existent file should throw
|
|
135
|
-
await expect(async () => {
|
|
136
|
-
const audio = createReadStream(nonExistentPath);
|
|
137
|
-
await voice.listen(audio);
|
|
138
|
-
}).rejects.toThrow();
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { File } from 'node:buffer';
|
|
2
|
-
import { MastraVoice } from '@mastra/core/voice';
|
|
3
|
-
import { ElevenLabsClient } from 'elevenlabs';
|
|
4
|
-
|
|
5
|
-
type ElevenLabsModel =
|
|
6
|
-
| 'eleven_multilingual_v2'
|
|
7
|
-
| 'eleven_flash_v2_5'
|
|
8
|
-
| 'eleven_flash_v2'
|
|
9
|
-
| 'eleven_multilingual_sts_v2'
|
|
10
|
-
| 'eleven_english_sts_v2'
|
|
11
|
-
| 'scribe_v1';
|
|
12
|
-
|
|
13
|
-
interface ElevenLabsVoiceConfig {
|
|
14
|
-
name?: ElevenLabsModel;
|
|
15
|
-
apiKey?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
interface SpeechToTextOptions {
|
|
19
|
-
language_code?: string;
|
|
20
|
-
tag_audio_events?: boolean;
|
|
21
|
-
num_speakers?: number;
|
|
22
|
-
filetype?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface RequestOptions {
|
|
26
|
-
timeoutInSeconds?: number;
|
|
27
|
-
maxRetries?: number;
|
|
28
|
-
abortSignal?: AbortSignal;
|
|
29
|
-
apiKey?: string | undefined;
|
|
30
|
-
headers?: Record<string, string>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Combined options type
|
|
34
|
-
type ElevenLabsListenOptions = SpeechToTextOptions & RequestOptions;
|
|
35
|
-
|
|
36
|
-
export class ElevenLabsVoice extends MastraVoice {
|
|
37
|
-
private client: ElevenLabsClient;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Creates an instance of the ElevenLabsVoice class.
|
|
41
|
-
*
|
|
42
|
-
* @param {Object} options - The options for the voice configuration.
|
|
43
|
-
* @param {ElevenLabsVoiceConfig} [options.speechModel] - The configuration for the speech model, including the model name and API key.
|
|
44
|
-
* @param {string} [options.speaker] - The ID of the speaker to use. If not provided, a default speaker will be used.
|
|
45
|
-
*
|
|
46
|
-
* @throws {Error} If the ELEVENLABS_API_KEY is not set in the environment variables.
|
|
47
|
-
*/
|
|
48
|
-
constructor({
|
|
49
|
-
speechModel,
|
|
50
|
-
listeningModel,
|
|
51
|
-
speaker,
|
|
52
|
-
}: { speechModel?: ElevenLabsVoiceConfig; listeningModel?: ElevenLabsVoiceConfig; speaker?: string } = {}) {
|
|
53
|
-
const apiKey = speechModel?.apiKey ?? process.env.ELEVENLABS_API_KEY;
|
|
54
|
-
super({
|
|
55
|
-
speechModel: {
|
|
56
|
-
name: speechModel?.name ?? 'eleven_multilingual_v2',
|
|
57
|
-
apiKey: speechModel?.apiKey,
|
|
58
|
-
},
|
|
59
|
-
listeningModel: {
|
|
60
|
-
name: listeningModel?.name ?? 'scribe_v1',
|
|
61
|
-
apiKey: listeningModel?.apiKey,
|
|
62
|
-
},
|
|
63
|
-
speaker,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
if (!apiKey) {
|
|
67
|
-
throw new Error('ELEVENLABS_API_KEY is not set');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
this.client = new ElevenLabsClient({
|
|
71
|
-
apiKey,
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
this.speaker = speaker || '9BWtsMINqrJLrRacOk9x'; // Aria is the default speaker
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Retrieves a list of available speakers from the Eleven Labs API.
|
|
79
|
-
* Each speaker includes their ID, name, language, and gender.
|
|
80
|
-
*
|
|
81
|
-
* @returns {Promise<Array<{ voiceId: string, name: string, language: string, gender: string }>>}
|
|
82
|
-
* A promise that resolves to an array of speaker objects.
|
|
83
|
-
*/
|
|
84
|
-
async getSpeakers() {
|
|
85
|
-
const res = await this.traced(async () => {
|
|
86
|
-
const voices = await this.client.voices.getAll();
|
|
87
|
-
return (
|
|
88
|
-
voices?.voices?.map(voice => ({
|
|
89
|
-
voiceId: voice.voice_id,
|
|
90
|
-
name: voice.name,
|
|
91
|
-
language: voice.labels?.language || 'en',
|
|
92
|
-
gender: voice.labels?.gender || 'neutral',
|
|
93
|
-
})) ?? []
|
|
94
|
-
);
|
|
95
|
-
}, 'voice.elevenlabs.voices')();
|
|
96
|
-
|
|
97
|
-
return res;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private async streamToString(stream: NodeJS.ReadableStream): Promise<string> {
|
|
101
|
-
const chunks: Buffer[] = [];
|
|
102
|
-
for await (const chunk of stream) {
|
|
103
|
-
chunks.push(Buffer.from(chunk));
|
|
104
|
-
}
|
|
105
|
-
return Buffer.concat(chunks).toString('utf-8');
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Converts text or audio input into speech using the Eleven Labs API.
|
|
110
|
-
*
|
|
111
|
-
* @param {string | NodeJS.ReadableStream} input - The text to be converted to speech or a stream containing audio data.
|
|
112
|
-
* @param {Object} [options] - Optional parameters for the speech generation.
|
|
113
|
-
* @param {string} [options.speaker] - The ID of the speaker to use for the speech. If not provided, the default speaker will be used.
|
|
114
|
-
*
|
|
115
|
-
* @returns {Promise<NodeJS.ReadableStream>} A promise that resolves to a readable stream of the generated speech.
|
|
116
|
-
*
|
|
117
|
-
* @throws {Error} If no speaker is specified or if no speech model is set.
|
|
118
|
-
*/
|
|
119
|
-
async speak(input: string | NodeJS.ReadableStream, options?: { speaker?: string }): Promise<NodeJS.ReadableStream> {
|
|
120
|
-
const speaker = options?.speaker || this.speaker;
|
|
121
|
-
if (!speaker) {
|
|
122
|
-
throw new Error('No speaker specified');
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (!this.speechModel?.name) {
|
|
126
|
-
throw new Error('No speech model specified');
|
|
127
|
-
}
|
|
128
|
-
const text = typeof input === 'string' ? input : await this.streamToString(input);
|
|
129
|
-
const res = await this.traced(async () => {
|
|
130
|
-
return await this.client.generate({
|
|
131
|
-
text,
|
|
132
|
-
voice: speaker,
|
|
133
|
-
model_id: this.speechModel?.name as ElevenLabsModel,
|
|
134
|
-
stream: true,
|
|
135
|
-
});
|
|
136
|
-
}, 'voice.elevenlabs.speak')();
|
|
137
|
-
|
|
138
|
-
return res;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Converts audio input to text using ElevenLabs Speech-to-Text API.
|
|
143
|
-
*
|
|
144
|
-
* @param input - A readable stream containing the audio data to transcribe
|
|
145
|
-
* @param options - Configuration options for the transcription
|
|
146
|
-
* @param options.language_code - ISO language code (e.g., 'en', 'fr', 'es')
|
|
147
|
-
* @param options.tag_audio_events - Whether to tag audio events like [MUSIC], [LAUGHTER], etc.
|
|
148
|
-
* @param options.num_speakers - Number of speakers to detect in the audio
|
|
149
|
-
* @param options.filetype - Audio file format (e.g., 'mp3', 'wav', 'ogg')
|
|
150
|
-
* @param options.timeoutInSeconds - Request timeout in seconds
|
|
151
|
-
* @param options.maxRetries - Maximum number of retry attempts
|
|
152
|
-
* @param options.abortSignal - Signal to abort the request
|
|
153
|
-
*
|
|
154
|
-
* @returns A Promise that resolves to the transcribed text
|
|
155
|
-
*
|
|
156
|
-
*/
|
|
157
|
-
async listen(input: NodeJS.ReadableStream, options?: ElevenLabsListenOptions): Promise<string> {
|
|
158
|
-
const res = await this.traced(async () => {
|
|
159
|
-
const chunks: Buffer[] = [];
|
|
160
|
-
for await (const chunk of input) {
|
|
161
|
-
chunks.push(Buffer.from(chunk));
|
|
162
|
-
}
|
|
163
|
-
const buffer = Buffer.concat(chunks);
|
|
164
|
-
|
|
165
|
-
const { language_code, tag_audio_events, num_speakers, filetype, ...requestOptions } = options || {};
|
|
166
|
-
|
|
167
|
-
const file = new File([buffer], `audio.${filetype || 'mp3'}`);
|
|
168
|
-
|
|
169
|
-
const transcription = await this.client.speechToText.convert(
|
|
170
|
-
{
|
|
171
|
-
file: file,
|
|
172
|
-
model_id: this.listeningModel?.name as ElevenLabsModel,
|
|
173
|
-
language_code,
|
|
174
|
-
tag_audio_events,
|
|
175
|
-
num_speakers,
|
|
176
|
-
},
|
|
177
|
-
requestOptions,
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
return transcription.text;
|
|
181
|
-
}, 'voice.elevenlabs.listen')();
|
|
182
|
-
|
|
183
|
-
return res;
|
|
184
|
-
}
|
|
185
|
-
}
|
package/tsconfig.json
DELETED