@mastra/voice-playai 0.12.0-beta.0 → 0.12.0
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/CHANGELOG.md +44 -0
- package/dist/docs/README.md +32 -0
- package/dist/docs/SKILL.md +33 -0
- package/dist/docs/SOURCE_MAP.json +6 -0
- package/dist/docs/agents/01-adding-voice.md +352 -0
- package/dist/docs/voice/01-overview.md +1019 -0
- package/dist/docs/voice/02-reference.md +460 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +10 -9
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
# Voice API Reference
|
|
2
|
+
|
|
3
|
+
> API reference for voice - 4 entries
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Reference: CompositeVoice
|
|
9
|
+
|
|
10
|
+
> Documentation for the CompositeVoice class, which enables combining multiple voice providers for flexible text-to-speech and speech-to-text operations.
|
|
11
|
+
|
|
12
|
+
The CompositeVoice class allows you to combine different voice providers for text-to-speech and speech-to-text operations. This is particularly useful when you want to use the best provider for each operation - for example, using OpenAI for speech-to-text and PlayAI for text-to-speech.
|
|
13
|
+
|
|
14
|
+
CompositeVoice supports both Mastra voice providers and AI SDK model providers
|
|
15
|
+
|
|
16
|
+
## Constructor Parameters
|
|
17
|
+
|
|
18
|
+
## Methods
|
|
19
|
+
|
|
20
|
+
### speak()
|
|
21
|
+
|
|
22
|
+
Converts text to speech using the configured speaking provider.
|
|
23
|
+
|
|
24
|
+
Notes:
|
|
25
|
+
|
|
26
|
+
- If no speaking provider is configured, this method will throw an error
|
|
27
|
+
- Options are passed through to the configured speaking provider
|
|
28
|
+
- Returns a stream of audio data
|
|
29
|
+
|
|
30
|
+
### listen()
|
|
31
|
+
|
|
32
|
+
Converts speech to text using the configured listening provider.
|
|
33
|
+
|
|
34
|
+
Notes:
|
|
35
|
+
|
|
36
|
+
- If no listening provider is configured, this method will throw an error
|
|
37
|
+
- Options are passed through to the configured listening provider
|
|
38
|
+
- Returns either a string or a stream of transcribed text, depending on the provider
|
|
39
|
+
|
|
40
|
+
### getSpeakers()
|
|
41
|
+
|
|
42
|
+
Returns a list of available voices from the speaking provider, where each node contains:
|
|
43
|
+
|
|
44
|
+
Notes:
|
|
45
|
+
|
|
46
|
+
- Returns voices from the speaking provider only
|
|
47
|
+
- If no speaking provider is configured, returns an empty array
|
|
48
|
+
- Each voice object will have at least a voiceId property
|
|
49
|
+
- Additional voice properties depend on the speaking provider
|
|
50
|
+
|
|
51
|
+
## Usage Examples
|
|
52
|
+
|
|
53
|
+
### Using Mastra Voice Providers
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { CompositeVoice } from "@mastra/core/voice";
|
|
57
|
+
import { OpenAIVoice } from "@mastra/voice-openai";
|
|
58
|
+
import { PlayAIVoice } from "@mastra/voice-playai";
|
|
59
|
+
|
|
60
|
+
// Create voice providers
|
|
61
|
+
const openai = new OpenAIVoice();
|
|
62
|
+
const playai = new PlayAIVoice();
|
|
63
|
+
|
|
64
|
+
// Use OpenAI for listening (speech-to-text) and PlayAI for speaking (text-to-speech)
|
|
65
|
+
const voice = new CompositeVoice({
|
|
66
|
+
input: openai,
|
|
67
|
+
output: playai,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Convert speech to text using OpenAI
|
|
71
|
+
const text = await voice.listen(audioStream);
|
|
72
|
+
|
|
73
|
+
// Convert text to speech using PlayAI
|
|
74
|
+
const audio = await voice.speak("Hello, world!");
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Using AI SDK Model Providers
|
|
78
|
+
|
|
79
|
+
You can pass AI SDK transcription and speech models directly to CompositeVoice:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { CompositeVoice } from "@mastra/core/voice";
|
|
83
|
+
import { openai } from "@ai-sdk/openai";
|
|
84
|
+
import { elevenlabs } from "@ai-sdk/elevenlabs";
|
|
85
|
+
|
|
86
|
+
// Use AI SDK models directly - they will be auto-wrapped
|
|
87
|
+
const voice = new CompositeVoice({
|
|
88
|
+
input: openai.transcription('whisper-1'), // AI SDK transcription
|
|
89
|
+
output: elevenlabs.speech('eleven_turbo_v2'), // AI SDK speech
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Works the same way as with Mastra providers
|
|
93
|
+
const text = await voice.listen(audioStream);
|
|
94
|
+
const audio = await voice.speak("Hello from AI SDK!");
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Mix and Match
|
|
98
|
+
|
|
99
|
+
You can combine Mastra providers with AI SDK models:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { CompositeVoice } from "@mastra/core/voice";
|
|
103
|
+
import { PlayAIVoice } from "@mastra/voice-playai";
|
|
104
|
+
import { groq } from "@ai-sdk/groq";
|
|
105
|
+
|
|
106
|
+
const voice = new CompositeVoice({
|
|
107
|
+
input: groq.transcription('whisper-large-v3'), // AI SDK for STT
|
|
108
|
+
output: new PlayAIVoice(), // Mastra for TTS
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Reference: PlayAI
|
|
115
|
+
|
|
116
|
+
> Documentation for the PlayAI voice implementation, providing text-to-speech capabilities.
|
|
117
|
+
|
|
118
|
+
The PlayAI voice implementation in Mastra provides text-to-speech capabilities using PlayAI's API.
|
|
119
|
+
|
|
120
|
+
## Usage Example
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { PlayAIVoice } from "@mastra/voice-playai";
|
|
124
|
+
|
|
125
|
+
// Initialize with default configuration (uses PLAYAI_API_KEY environment variable and PLAYAI_USER_ID environment variable)
|
|
126
|
+
const voice = new PlayAIVoice();
|
|
127
|
+
|
|
128
|
+
// Initialize with default configuration
|
|
129
|
+
const voice = new PlayAIVoice({
|
|
130
|
+
speechModel: {
|
|
131
|
+
name: "PlayDialog",
|
|
132
|
+
apiKey: process.env.PLAYAI_API_KEY,
|
|
133
|
+
userId: process.env.PLAYAI_USER_ID,
|
|
134
|
+
},
|
|
135
|
+
speaker: "Angelo", // Default voice
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Convert text to speech with a specific voice
|
|
139
|
+
const audioStream = await voice.speak("Hello, world!", {
|
|
140
|
+
speaker:
|
|
141
|
+
"s3://voice-cloning-zero-shot/b27bc13e-996f-4841-b584-4d35801aea98/original/manifest.json", // Dexter voice
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Constructor Parameters
|
|
146
|
+
|
|
147
|
+
### PlayAIConfig
|
|
148
|
+
|
|
149
|
+
## Methods
|
|
150
|
+
|
|
151
|
+
### speak()
|
|
152
|
+
|
|
153
|
+
Converts text to speech using the configured speech model and voice.
|
|
154
|
+
|
|
155
|
+
Returns: `Promise<NodeJS.ReadableStream>`.
|
|
156
|
+
|
|
157
|
+
### getSpeakers()
|
|
158
|
+
|
|
159
|
+
Returns an array of available voice options, where each node contains:
|
|
160
|
+
|
|
161
|
+
### listen()
|
|
162
|
+
|
|
163
|
+
This method is not supported by PlayAI and will throw an error. PlayAI does not provide speech-to-text functionality.
|
|
164
|
+
|
|
165
|
+
## Notes
|
|
166
|
+
|
|
167
|
+
- PlayAI requires both an API key and a user ID for authentication
|
|
168
|
+
- The service offers two models: 'PlayDialog' and 'Play3.0-mini'
|
|
169
|
+
- Each voice has a unique S3 manifest ID that must be used when making API calls
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Reference: voice.listen()
|
|
174
|
+
|
|
175
|
+
> Documentation for the listen() method available in all Mastra voice providers, which converts speech to text.
|
|
176
|
+
|
|
177
|
+
The `listen()` method is a core function available in all Mastra voice providers that converts speech to text. It takes an audio stream as input and returns the transcribed text.
|
|
178
|
+
|
|
179
|
+
## Parameters
|
|
180
|
+
|
|
181
|
+
## Return Value
|
|
182
|
+
|
|
183
|
+
Returns one of the following:
|
|
184
|
+
|
|
185
|
+
- `Promise<string>`: A promise that resolves to the transcribed text
|
|
186
|
+
- `Promise<NodeJS.ReadableStream>`: A promise that resolves to a stream of transcribed text (for streaming transcription)
|
|
187
|
+
- `Promise<void>`: For real-time providers that emit 'writing' events instead of returning text directly
|
|
188
|
+
|
|
189
|
+
## Provider-Specific Options
|
|
190
|
+
|
|
191
|
+
Each voice provider may support additional options specific to their implementation. Here are some examples:
|
|
192
|
+
|
|
193
|
+
### OpenAI
|
|
194
|
+
|
|
195
|
+
### Google
|
|
196
|
+
|
|
197
|
+
### Deepgram
|
|
198
|
+
|
|
199
|
+
## Usage Example
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { OpenAIVoice } from "@mastra/voice-openai";
|
|
203
|
+
import { getMicrophoneStream } from "@mastra/node-audio";
|
|
204
|
+
import { createReadStream } from "fs";
|
|
205
|
+
import path from "path";
|
|
206
|
+
|
|
207
|
+
// Initialize a voice provider
|
|
208
|
+
const voice = new OpenAIVoice({
|
|
209
|
+
listeningModel: {
|
|
210
|
+
name: "whisper-1",
|
|
211
|
+
apiKey: process.env.OPENAI_API_KEY,
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Basic usage with a file stream
|
|
216
|
+
const audioFilePath = path.join(process.cwd(), "audio.mp3");
|
|
217
|
+
const audioStream = createReadStream(audioFilePath);
|
|
218
|
+
const transcript = await voice.listen(audioStream, {
|
|
219
|
+
filetype: "mp3",
|
|
220
|
+
});
|
|
221
|
+
console.log("Transcribed text:", transcript);
|
|
222
|
+
|
|
223
|
+
// Using a microphone stream
|
|
224
|
+
const microphoneStream = getMicrophoneStream(); // Assume this function gets audio input
|
|
225
|
+
const transcription = await voice.listen(microphoneStream);
|
|
226
|
+
|
|
227
|
+
// With provider-specific options
|
|
228
|
+
const transcriptWithOptions = await voice.listen(audioStream, {
|
|
229
|
+
language: "en",
|
|
230
|
+
prompt: "This is a conversation about artificial intelligence.",
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Using with CompositeVoice
|
|
235
|
+
|
|
236
|
+
When using `CompositeVoice`, the `listen()` method delegates to the configured listening provider:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
import { CompositeVoice } from "@mastra/core/voice";
|
|
240
|
+
import { OpenAIVoice } from "@mastra/voice-openai";
|
|
241
|
+
import { PlayAIVoice } from "@mastra/voice-playai";
|
|
242
|
+
|
|
243
|
+
const voice = new CompositeVoice({
|
|
244
|
+
input: new OpenAIVoice(),
|
|
245
|
+
output: new PlayAIVoice(),
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// This will use the OpenAIVoice provider
|
|
249
|
+
const transcript = await voice.listen(audioStream);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Using AI SDK Model Providers
|
|
253
|
+
|
|
254
|
+
You can also use AI SDK transcription models directly with `CompositeVoice`:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { CompositeVoice } from "@mastra/core/voice";
|
|
258
|
+
import { openai } from "@ai-sdk/openai";
|
|
259
|
+
import { groq } from "@ai-sdk/groq";
|
|
260
|
+
|
|
261
|
+
// Use AI SDK transcription models
|
|
262
|
+
const voice = new CompositeVoice({
|
|
263
|
+
input: openai.transcription('whisper-1'), // AI SDK model
|
|
264
|
+
output: new PlayAIVoice(), // Mastra provider
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Works the same way
|
|
268
|
+
const transcript = await voice.listen(audioStream);
|
|
269
|
+
|
|
270
|
+
// Provider-specific options can be passed through
|
|
271
|
+
const transcriptWithOptions = await voice.listen(audioStream, {
|
|
272
|
+
providerOptions: {
|
|
273
|
+
openai: {
|
|
274
|
+
language: 'en',
|
|
275
|
+
prompt: 'This is about AI',
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
See the [CompositeVoice reference](https://mastra.ai/reference/v1/voice/composite-voice) for more details on AI SDK integration.
|
|
282
|
+
|
|
283
|
+
## Realtime Voice Providers
|
|
284
|
+
|
|
285
|
+
When using realtime voice providers like `OpenAIRealtimeVoice`, the `listen()` method behaves differently:
|
|
286
|
+
|
|
287
|
+
- Instead of returning transcribed text, it emits 'writing' events with the transcribed text
|
|
288
|
+
- You need to register an event listener to receive the transcription
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { OpenAIRealtimeVoice } from "@mastra/voice-openai-realtime";
|
|
292
|
+
import { getMicrophoneStream } from "@mastra/node-audio";
|
|
293
|
+
|
|
294
|
+
const voice = new OpenAIRealtimeVoice();
|
|
295
|
+
await voice.connect();
|
|
296
|
+
|
|
297
|
+
// Register event listener for transcription
|
|
298
|
+
voice.on("writing", ({ text, role }) => {
|
|
299
|
+
console.log(`${role}: ${text}`);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// This will emit 'writing' events instead of returning text
|
|
303
|
+
const microphoneStream = getMicrophoneStream();
|
|
304
|
+
await voice.listen(microphoneStream);
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Notes
|
|
308
|
+
|
|
309
|
+
- Not all voice providers support speech-to-text functionality (e.g., PlayAI, Speechify)
|
|
310
|
+
- The behavior of `listen()` may vary slightly between providers, but all implementations follow the same basic interface
|
|
311
|
+
- When using a realtime voice provider, the method might not return text directly but instead emit a 'writing' event
|
|
312
|
+
- The audio format supported depends on the provider. Common formats include MP3, WAV, and M4A
|
|
313
|
+
- Some providers support streaming transcription, where text is returned as it's transcribed
|
|
314
|
+
- For best performance, consider closing or ending the audio stream when you're done with it
|
|
315
|
+
|
|
316
|
+
## Related Methods
|
|
317
|
+
|
|
318
|
+
- [voice.speak()](./voice.speak) - Converts text to speech
|
|
319
|
+
- [voice.send()](./voice.send) - Sends audio data to the voice provider in real-time
|
|
320
|
+
- [voice.on()](./voice.on) - Registers an event listener for voice events
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Reference: voice.speak()
|
|
325
|
+
|
|
326
|
+
> Documentation for the speak() method available in all Mastra voice providers, which converts text to speech.
|
|
327
|
+
|
|
328
|
+
The `speak()` method is a core function available in all Mastra voice providers that converts text to speech. It takes text input and returns an audio stream that can be played or saved.
|
|
329
|
+
|
|
330
|
+
## Parameters
|
|
331
|
+
|
|
332
|
+
## Return Value
|
|
333
|
+
|
|
334
|
+
Returns a `Promise<NodeJS.ReadableStream | void>` where:
|
|
335
|
+
|
|
336
|
+
- `NodeJS.ReadableStream`: A stream of audio data that can be played or saved
|
|
337
|
+
- `void`: When using a realtime voice provider that emits audio through events instead of returning it directly
|
|
338
|
+
|
|
339
|
+
## Provider-Specific Options
|
|
340
|
+
|
|
341
|
+
Each voice provider may support additional options specific to their implementation. Here are some examples:
|
|
342
|
+
|
|
343
|
+
### OpenAI
|
|
344
|
+
|
|
345
|
+
### ElevenLabs
|
|
346
|
+
|
|
347
|
+
### Google
|
|
348
|
+
|
|
349
|
+
### Murf
|
|
350
|
+
|
|
351
|
+
## Usage Example
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
import { OpenAIVoice } from "@mastra/voice-openai";
|
|
355
|
+
// Initialize a voice provider
|
|
356
|
+
const voice = new OpenAIVoice({
|
|
357
|
+
speaker: "alloy", // Default voice
|
|
358
|
+
});
|
|
359
|
+
// Basic usage with default settings
|
|
360
|
+
const audioStream = await voice.speak("Hello, world!");
|
|
361
|
+
// Using a different voice for this specific request
|
|
362
|
+
const audioStreamWithDifferentVoice = await voice.speak("Hello again!", {
|
|
363
|
+
speaker: "nova",
|
|
364
|
+
});
|
|
365
|
+
// Using provider-specific options
|
|
366
|
+
const audioStreamWithOptions = await voice.speak("Hello with options!", {
|
|
367
|
+
speaker: "echo",
|
|
368
|
+
speed: 1.2, // OpenAI-specific option
|
|
369
|
+
});
|
|
370
|
+
// Using a text stream as input
|
|
371
|
+
import { Readable } from "stream";
|
|
372
|
+
const textStream = Readable.from(["Hello", " from", " a", " stream!"]);
|
|
373
|
+
const audioStreamFromTextStream = await voice.speak(textStream);
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Using with CompositeVoice
|
|
377
|
+
|
|
378
|
+
When using `CompositeVoice`, the `speak()` method delegates to the configured speaking provider:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
import { CompositeVoice } from "@mastra/core/voice";
|
|
382
|
+
import { OpenAIVoice } from "@mastra/voice-openai";
|
|
383
|
+
import { PlayAIVoice } from "@mastra/voice-playai";
|
|
384
|
+
|
|
385
|
+
const voice = new CompositeVoice({
|
|
386
|
+
output: new PlayAIVoice(),
|
|
387
|
+
input: new OpenAIVoice(),
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// This will use the PlayAIVoice provider
|
|
391
|
+
const audioStream = await voice.speak("Hello, world!");
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Using AI SDK Model Providers
|
|
395
|
+
|
|
396
|
+
You can also use AI SDK speech models directly with `CompositeVoice`:
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
import { CompositeVoice } from "@mastra/core/voice";
|
|
400
|
+
import { openai } from "@ai-sdk/openai";
|
|
401
|
+
import { elevenlabs } from "@ai-sdk/elevenlabs";
|
|
402
|
+
|
|
403
|
+
// Use AI SDK speech models
|
|
404
|
+
const voice = new CompositeVoice({
|
|
405
|
+
output: elevenlabs.speech('eleven_turbo_v2'), // AI SDK model
|
|
406
|
+
input: openai.transcription('whisper-1'), // AI SDK model
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
// Works the same way
|
|
410
|
+
const audioStream = await voice.speak("Hello from AI SDK!");
|
|
411
|
+
|
|
412
|
+
// Provider-specific options can be passed through
|
|
413
|
+
const audioWithOptions = await voice.speak("Hello with options!", {
|
|
414
|
+
speaker: 'Rachel', // ElevenLabs voice
|
|
415
|
+
providerOptions: {
|
|
416
|
+
elevenlabs: {
|
|
417
|
+
stability: 0.5,
|
|
418
|
+
similarity_boost: 0.75,
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
See the [CompositeVoice reference](https://mastra.ai/reference/v1/voice/composite-voice) for more details on AI SDK integration.
|
|
425
|
+
|
|
426
|
+
## Realtime Voice Providers
|
|
427
|
+
|
|
428
|
+
When using realtime voice providers like `OpenAIRealtimeVoice`, the `speak()` method behaves differently:
|
|
429
|
+
|
|
430
|
+
- Instead of returning an audio stream, it emits a 'speaking' event with the audio data
|
|
431
|
+
- You need to register an event listener to receive the audio chunks
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
import { OpenAIRealtimeVoice } from "@mastra/voice-openai-realtime";
|
|
435
|
+
import Speaker from "@mastra/node-speaker";
|
|
436
|
+
|
|
437
|
+
const speaker = new Speaker({
|
|
438
|
+
sampleRate: 24100, // Audio sample rate in Hz - standard for high-quality audio on MacBook Pro
|
|
439
|
+
channels: 1, // Mono audio output (as opposed to stereo which would be 2)
|
|
440
|
+
bitDepth: 16, // Bit depth for audio quality - CD quality standard (16-bit resolution)
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
const voice = new OpenAIRealtimeVoice();
|
|
444
|
+
await voice.connect();
|
|
445
|
+
// Register event listener for audio chunks
|
|
446
|
+
voice.on("speaker", (stream) => {
|
|
447
|
+
// Handle audio chunk (e.g., play it or save it)
|
|
448
|
+
stream.pipe(speaker);
|
|
449
|
+
});
|
|
450
|
+
// This will emit 'speaking' events instead of returning a stream
|
|
451
|
+
await voice.speak("Hello, this is realtime speech!");
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## Notes
|
|
455
|
+
|
|
456
|
+
- The behavior of `speak()` may vary slightly between providers, but all implementations follow the same basic interface.
|
|
457
|
+
- When using a realtime voice provider, the method might not return an audio stream directly but instead emit a 'speaking' event.
|
|
458
|
+
- If a text stream is provided as input, the provider will typically convert it to a string before processing.
|
|
459
|
+
- The audio format of the returned stream depends on the provider. Common formats include MP3, WAV, and OGG.
|
|
460
|
+
- For best performance, consider closing or ending the audio stream when you're done with it.
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["MastraVoice","stream","PassThrough"],"mappings":"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","file":"index.cjs","sourcesContent":["import { PassThrough } from 'stream';\n\nimport { MastraVoice } from '@mastra/core/voice';\n\ninterface PlayAIVoiceInfo {\n name: string;\n accent: string;\n gender: 'M' | 'F';\n age: 'Young' | 'Middle' | 'Old';\n style: 'Conversational' | 'Narrative';\n id: string;\n}\n\nexport const PLAYAI_VOICES: PlayAIVoiceInfo[] = [\n {\n name: 'Angelo',\n accent: 'US',\n gender: 'M',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json',\n },\n {\n name: 'Arsenio',\n accent: 'US African American',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/65977f5e-a22a-4b36-861b-ecede19bdd65/original/manifest.json',\n },\n {\n name: 'Cillian',\n accent: 'Irish',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/1591b954-8760-41a9-bc58-9176a68c5726/original/manifest.json',\n },\n {\n name: 'Timo',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/677a4ae3-252f-476e-85ce-eeed68e85951/original/manifest.json',\n },\n {\n name: 'Dexter',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/b27bc13e-996f-4841-b584-4d35801aea98/original/manifest.json',\n },\n {\n name: 'Miles',\n accent: 'US African American',\n gender: 'M',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/29dd9a52-bd32-4a6e-bff1-bbb98dcc286a/original/manifest.json',\n },\n {\n name: 'Briggs',\n accent: 'US Southern (Oklahoma)',\n gender: 'M',\n age: 'Old',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/71cdb799-1e03-41c6-8a05-f7cd55134b0b/original/manifest.json',\n },\n {\n name: 'Deedee',\n accent: 'US African American',\n gender: 'F',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json',\n },\n {\n name: 'Nia',\n accent: 'US',\n gender: 'F',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/831bd330-85c6-4333-b2b4-10c476ea3491/original/manifest.json',\n },\n {\n name: 'Inara',\n accent: 'US African American',\n gender: 'F',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/adb83b67-8d75-48ff-ad4d-a0840d231ef1/original/manifest.json',\n },\n {\n name: 'Constanza',\n accent: 'US Latin American',\n gender: 'F',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/b0aca4d7-1738-4848-a80b-307ac44a7298/original/manifest.json',\n },\n {\n name: 'Gideon',\n accent: 'British',\n gender: 'M',\n age: 'Old',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/5a3a1168-7793-4b2c-8f90-aff2b5232131/original/manifest.json',\n },\n {\n name: 'Casper',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/1bbc6986-fadf-4bd8-98aa-b86fed0476e9/original/manifest.json',\n },\n {\n name: 'Mitch',\n accent: 'Australian',\n gender: 'M',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/c14e50f2-c5e3-47d1-8c45-fa4b67803d19/original/manifest.json',\n },\n {\n name: 'Ava',\n accent: 'Australian',\n gender: 'F',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/50381567-ff7b-46d2-bfdc-a9584a85e08d/original/manifest.json',\n },\n];\n\ninterface PlayAIConfig {\n name?: 'PlayDialog' | 'Play3.0-mini';\n apiKey?: string;\n userId?: string;\n}\n\nexport class PlayAIVoice extends MastraVoice {\n private baseUrl = 'https://api.play.ai/api/v1';\n private userId: string;\n\n constructor({ speechModel, speaker }: { speechModel?: PlayAIConfig; speaker?: string } = {}) {\n super({\n speechModel: {\n name: speechModel?.name ?? 'PlayDialog',\n apiKey: speechModel?.apiKey ?? process.env.PLAYAI_API_KEY,\n },\n speaker: speaker ?? PLAYAI_VOICES[0]?.id,\n });\n const userId = speechModel?.userId ?? process.env.PLAYAI_USER_ID;\n if (!userId) {\n throw new Error('userId is required');\n }\n\n this.userId = userId;\n }\n\n private async makeRequest(endpoint: string, payload?: any, method: 'GET' | 'POST' = 'POST') {\n const headers = new Headers({\n Authorization: `Bearer ${this.speechModel?.apiKey}`,\n 'Content-Type': 'application/json',\n 'X-USER-ID': this.userId,\n });\n\n const response = await fetch(`${this.baseUrl}${endpoint}`, {\n method,\n headers,\n body: payload ? JSON.stringify(payload) : undefined,\n });\n\n if (!response.ok) {\n const error = (await response.json()) as { message: string };\n\n throw new Error(`PlayAI API Error: ${error.message || response.statusText}`);\n }\n\n return response;\n }\n\n private async streamToString(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n return Buffer.concat(chunks).toString('utf-8');\n }\n\n async speak(input: string | NodeJS.ReadableStream, options?: { speaker?: string }): Promise<NodeJS.ReadableStream> {\n const text = typeof input === 'string' ? input : await this.streamToString(input);\n\n const payload = {\n text,\n voice: options?.speaker || this.speaker,\n model: this.speechModel?.name,\n };\n\n const response = await this.makeRequest('/tts/stream', payload);\n if (!response.body) {\n throw new Error('No response body received');\n }\n\n // Create a PassThrough stream for the audio\n const stream = new PassThrough();\n\n // Process the stream\n const reader = response.body.getReader();\n void (async () => {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n stream.end();\n break;\n }\n stream.write(value);\n }\n } catch (error) {\n stream.destroy(error as Error);\n }\n })();\n\n return stream;\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n return { enabled: false };\n }\n\n async listen(\n _input: NodeJS.ReadableStream,\n _options?: Record<string, unknown>,\n ): Promise<string | NodeJS.ReadableStream> {\n throw new Error('PlayAI does not support speech recognition');\n }\n\n async getSpeakers() {\n return Promise.resolve(\n PLAYAI_VOICES.map(voice => ({\n voiceId: voice.id,\n name: voice.name,\n accent: voice.accent,\n gender: voice.gender,\n age: voice.age,\n style: voice.style,\n })),\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["MastraVoice","stream","PassThrough"],"mappings":"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","file":"index.cjs","sourcesContent":["import { PassThrough } from 'node:stream';\n\nimport { MastraVoice } from '@mastra/core/voice';\n\ninterface PlayAIVoiceInfo {\n name: string;\n accent: string;\n gender: 'M' | 'F';\n age: 'Young' | 'Middle' | 'Old';\n style: 'Conversational' | 'Narrative';\n id: string;\n}\n\nexport const PLAYAI_VOICES: PlayAIVoiceInfo[] = [\n {\n name: 'Angelo',\n accent: 'US',\n gender: 'M',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json',\n },\n {\n name: 'Arsenio',\n accent: 'US African American',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/65977f5e-a22a-4b36-861b-ecede19bdd65/original/manifest.json',\n },\n {\n name: 'Cillian',\n accent: 'Irish',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/1591b954-8760-41a9-bc58-9176a68c5726/original/manifest.json',\n },\n {\n name: 'Timo',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/677a4ae3-252f-476e-85ce-eeed68e85951/original/manifest.json',\n },\n {\n name: 'Dexter',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/b27bc13e-996f-4841-b584-4d35801aea98/original/manifest.json',\n },\n {\n name: 'Miles',\n accent: 'US African American',\n gender: 'M',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/29dd9a52-bd32-4a6e-bff1-bbb98dcc286a/original/manifest.json',\n },\n {\n name: 'Briggs',\n accent: 'US Southern (Oklahoma)',\n gender: 'M',\n age: 'Old',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/71cdb799-1e03-41c6-8a05-f7cd55134b0b/original/manifest.json',\n },\n {\n name: 'Deedee',\n accent: 'US African American',\n gender: 'F',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json',\n },\n {\n name: 'Nia',\n accent: 'US',\n gender: 'F',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/831bd330-85c6-4333-b2b4-10c476ea3491/original/manifest.json',\n },\n {\n name: 'Inara',\n accent: 'US African American',\n gender: 'F',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/adb83b67-8d75-48ff-ad4d-a0840d231ef1/original/manifest.json',\n },\n {\n name: 'Constanza',\n accent: 'US Latin American',\n gender: 'F',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/b0aca4d7-1738-4848-a80b-307ac44a7298/original/manifest.json',\n },\n {\n name: 'Gideon',\n accent: 'British',\n gender: 'M',\n age: 'Old',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/5a3a1168-7793-4b2c-8f90-aff2b5232131/original/manifest.json',\n },\n {\n name: 'Casper',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/1bbc6986-fadf-4bd8-98aa-b86fed0476e9/original/manifest.json',\n },\n {\n name: 'Mitch',\n accent: 'Australian',\n gender: 'M',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/c14e50f2-c5e3-47d1-8c45-fa4b67803d19/original/manifest.json',\n },\n {\n name: 'Ava',\n accent: 'Australian',\n gender: 'F',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/50381567-ff7b-46d2-bfdc-a9584a85e08d/original/manifest.json',\n },\n];\n\ninterface PlayAIConfig {\n name?: 'PlayDialog' | 'Play3.0-mini';\n apiKey?: string;\n userId?: string;\n}\n\nexport class PlayAIVoice extends MastraVoice {\n private baseUrl = 'https://api.play.ai/api/v1';\n private userId: string;\n\n constructor({ speechModel, speaker }: { speechModel?: PlayAIConfig; speaker?: string } = {}) {\n super({\n speechModel: {\n name: speechModel?.name ?? 'PlayDialog',\n apiKey: speechModel?.apiKey ?? process.env.PLAYAI_API_KEY,\n },\n speaker: speaker ?? PLAYAI_VOICES[0]?.id,\n });\n const userId = speechModel?.userId ?? process.env.PLAYAI_USER_ID;\n if (!userId) {\n throw new Error('userId is required');\n }\n\n this.userId = userId;\n }\n\n private async makeRequest(endpoint: string, payload?: any, method: 'GET' | 'POST' = 'POST') {\n const headers = new Headers({\n Authorization: `Bearer ${this.speechModel?.apiKey}`,\n 'Content-Type': 'application/json',\n 'X-USER-ID': this.userId,\n });\n\n const response = await fetch(`${this.baseUrl}${endpoint}`, {\n method,\n headers,\n body: payload ? JSON.stringify(payload) : undefined,\n });\n\n if (!response.ok) {\n const error = (await response.json()) as { message: string };\n\n throw new Error(`PlayAI API Error: ${error.message || response.statusText}`);\n }\n\n return response;\n }\n\n private async streamToString(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n return Buffer.concat(chunks).toString('utf-8');\n }\n\n async speak(input: string | NodeJS.ReadableStream, options?: { speaker?: string }): Promise<NodeJS.ReadableStream> {\n const text = typeof input === 'string' ? input : await this.streamToString(input);\n\n const payload = {\n text,\n voice: options?.speaker || this.speaker,\n model: this.speechModel?.name,\n };\n\n const response = await this.makeRequest('/tts/stream', payload);\n if (!response.body) {\n throw new Error('No response body received');\n }\n\n // Create a PassThrough stream for the audio\n const stream = new PassThrough();\n\n // Process the stream\n const reader = response.body.getReader();\n void (async () => {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n stream.end();\n break;\n }\n stream.write(value);\n }\n } catch (error) {\n stream.destroy(error as Error);\n }\n })();\n\n return stream;\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n return { enabled: false };\n }\n\n async listen(\n _input: NodeJS.ReadableStream,\n _options?: Record<string, unknown>,\n ): Promise<string | NodeJS.ReadableStream> {\n throw new Error('PlayAI does not support speech recognition');\n }\n\n async getSpeakers() {\n return Promise.resolve(\n PLAYAI_VOICES.map(voice => ({\n voiceId: voice.id,\n name: voice.name,\n accent: voice.accent,\n gender: voice.gender,\n age: voice.age,\n style: voice.style,\n })),\n );\n }\n}\n"]}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { PassThrough } from 'stream';\n\nimport { MastraVoice } from '@mastra/core/voice';\n\ninterface PlayAIVoiceInfo {\n name: string;\n accent: string;\n gender: 'M' | 'F';\n age: 'Young' | 'Middle' | 'Old';\n style: 'Conversational' | 'Narrative';\n id: string;\n}\n\nexport const PLAYAI_VOICES: PlayAIVoiceInfo[] = [\n {\n name: 'Angelo',\n accent: 'US',\n gender: 'M',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json',\n },\n {\n name: 'Arsenio',\n accent: 'US African American',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/65977f5e-a22a-4b36-861b-ecede19bdd65/original/manifest.json',\n },\n {\n name: 'Cillian',\n accent: 'Irish',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/1591b954-8760-41a9-bc58-9176a68c5726/original/manifest.json',\n },\n {\n name: 'Timo',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/677a4ae3-252f-476e-85ce-eeed68e85951/original/manifest.json',\n },\n {\n name: 'Dexter',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/b27bc13e-996f-4841-b584-4d35801aea98/original/manifest.json',\n },\n {\n name: 'Miles',\n accent: 'US African American',\n gender: 'M',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/29dd9a52-bd32-4a6e-bff1-bbb98dcc286a/original/manifest.json',\n },\n {\n name: 'Briggs',\n accent: 'US Southern (Oklahoma)',\n gender: 'M',\n age: 'Old',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/71cdb799-1e03-41c6-8a05-f7cd55134b0b/original/manifest.json',\n },\n {\n name: 'Deedee',\n accent: 'US African American',\n gender: 'F',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json',\n },\n {\n name: 'Nia',\n accent: 'US',\n gender: 'F',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/831bd330-85c6-4333-b2b4-10c476ea3491/original/manifest.json',\n },\n {\n name: 'Inara',\n accent: 'US African American',\n gender: 'F',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/adb83b67-8d75-48ff-ad4d-a0840d231ef1/original/manifest.json',\n },\n {\n name: 'Constanza',\n accent: 'US Latin American',\n gender: 'F',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/b0aca4d7-1738-4848-a80b-307ac44a7298/original/manifest.json',\n },\n {\n name: 'Gideon',\n accent: 'British',\n gender: 'M',\n age: 'Old',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/5a3a1168-7793-4b2c-8f90-aff2b5232131/original/manifest.json',\n },\n {\n name: 'Casper',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/1bbc6986-fadf-4bd8-98aa-b86fed0476e9/original/manifest.json',\n },\n {\n name: 'Mitch',\n accent: 'Australian',\n gender: 'M',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/c14e50f2-c5e3-47d1-8c45-fa4b67803d19/original/manifest.json',\n },\n {\n name: 'Ava',\n accent: 'Australian',\n gender: 'F',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/50381567-ff7b-46d2-bfdc-a9584a85e08d/original/manifest.json',\n },\n];\n\ninterface PlayAIConfig {\n name?: 'PlayDialog' | 'Play3.0-mini';\n apiKey?: string;\n userId?: string;\n}\n\nexport class PlayAIVoice extends MastraVoice {\n private baseUrl = 'https://api.play.ai/api/v1';\n private userId: string;\n\n constructor({ speechModel, speaker }: { speechModel?: PlayAIConfig; speaker?: string } = {}) {\n super({\n speechModel: {\n name: speechModel?.name ?? 'PlayDialog',\n apiKey: speechModel?.apiKey ?? process.env.PLAYAI_API_KEY,\n },\n speaker: speaker ?? PLAYAI_VOICES[0]?.id,\n });\n const userId = speechModel?.userId ?? process.env.PLAYAI_USER_ID;\n if (!userId) {\n throw new Error('userId is required');\n }\n\n this.userId = userId;\n }\n\n private async makeRequest(endpoint: string, payload?: any, method: 'GET' | 'POST' = 'POST') {\n const headers = new Headers({\n Authorization: `Bearer ${this.speechModel?.apiKey}`,\n 'Content-Type': 'application/json',\n 'X-USER-ID': this.userId,\n });\n\n const response = await fetch(`${this.baseUrl}${endpoint}`, {\n method,\n headers,\n body: payload ? JSON.stringify(payload) : undefined,\n });\n\n if (!response.ok) {\n const error = (await response.json()) as { message: string };\n\n throw new Error(`PlayAI API Error: ${error.message || response.statusText}`);\n }\n\n return response;\n }\n\n private async streamToString(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n return Buffer.concat(chunks).toString('utf-8');\n }\n\n async speak(input: string | NodeJS.ReadableStream, options?: { speaker?: string }): Promise<NodeJS.ReadableStream> {\n const text = typeof input === 'string' ? input : await this.streamToString(input);\n\n const payload = {\n text,\n voice: options?.speaker || this.speaker,\n model: this.speechModel?.name,\n };\n\n const response = await this.makeRequest('/tts/stream', payload);\n if (!response.body) {\n throw new Error('No response body received');\n }\n\n // Create a PassThrough stream for the audio\n const stream = new PassThrough();\n\n // Process the stream\n const reader = response.body.getReader();\n void (async () => {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n stream.end();\n break;\n }\n stream.write(value);\n }\n } catch (error) {\n stream.destroy(error as Error);\n }\n })();\n\n return stream;\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n return { enabled: false };\n }\n\n async listen(\n _input: NodeJS.ReadableStream,\n _options?: Record<string, unknown>,\n ): Promise<string | NodeJS.ReadableStream> {\n throw new Error('PlayAI does not support speech recognition');\n }\n\n async getSpeakers() {\n return Promise.resolve(\n PLAYAI_VOICES.map(voice => ({\n voiceId: voice.id,\n name: voice.name,\n accent: voice.accent,\n gender: voice.gender,\n age: voice.age,\n style: voice.style,\n })),\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { PassThrough } from 'node:stream';\n\nimport { MastraVoice } from '@mastra/core/voice';\n\ninterface PlayAIVoiceInfo {\n name: string;\n accent: string;\n gender: 'M' | 'F';\n age: 'Young' | 'Middle' | 'Old';\n style: 'Conversational' | 'Narrative';\n id: string;\n}\n\nexport const PLAYAI_VOICES: PlayAIVoiceInfo[] = [\n {\n name: 'Angelo',\n accent: 'US',\n gender: 'M',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/baf1ef41-36b6-428c-9bdf-50ba54682bd8/original/manifest.json',\n },\n {\n name: 'Arsenio',\n accent: 'US African American',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/65977f5e-a22a-4b36-861b-ecede19bdd65/original/manifest.json',\n },\n {\n name: 'Cillian',\n accent: 'Irish',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/1591b954-8760-41a9-bc58-9176a68c5726/original/manifest.json',\n },\n {\n name: 'Timo',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/677a4ae3-252f-476e-85ce-eeed68e85951/original/manifest.json',\n },\n {\n name: 'Dexter',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/b27bc13e-996f-4841-b584-4d35801aea98/original/manifest.json',\n },\n {\n name: 'Miles',\n accent: 'US African American',\n gender: 'M',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/29dd9a52-bd32-4a6e-bff1-bbb98dcc286a/original/manifest.json',\n },\n {\n name: 'Briggs',\n accent: 'US Southern (Oklahoma)',\n gender: 'M',\n age: 'Old',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/71cdb799-1e03-41c6-8a05-f7cd55134b0b/original/manifest.json',\n },\n {\n name: 'Deedee',\n accent: 'US African American',\n gender: 'F',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/e040bd1b-f190-4bdb-83f0-75ef85b18f84/original/manifest.json',\n },\n {\n name: 'Nia',\n accent: 'US',\n gender: 'F',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/831bd330-85c6-4333-b2b4-10c476ea3491/original/manifest.json',\n },\n {\n name: 'Inara',\n accent: 'US African American',\n gender: 'F',\n age: 'Middle',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/adb83b67-8d75-48ff-ad4d-a0840d231ef1/original/manifest.json',\n },\n {\n name: 'Constanza',\n accent: 'US Latin American',\n gender: 'F',\n age: 'Young',\n style: 'Conversational',\n id: 's3://voice-cloning-zero-shot/b0aca4d7-1738-4848-a80b-307ac44a7298/original/manifest.json',\n },\n {\n name: 'Gideon',\n accent: 'British',\n gender: 'M',\n age: 'Old',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/5a3a1168-7793-4b2c-8f90-aff2b5232131/original/manifest.json',\n },\n {\n name: 'Casper',\n accent: 'US',\n gender: 'M',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/1bbc6986-fadf-4bd8-98aa-b86fed0476e9/original/manifest.json',\n },\n {\n name: 'Mitch',\n accent: 'Australian',\n gender: 'M',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/c14e50f2-c5e3-47d1-8c45-fa4b67803d19/original/manifest.json',\n },\n {\n name: 'Ava',\n accent: 'Australian',\n gender: 'F',\n age: 'Middle',\n style: 'Narrative',\n id: 's3://voice-cloning-zero-shot/50381567-ff7b-46d2-bfdc-a9584a85e08d/original/manifest.json',\n },\n];\n\ninterface PlayAIConfig {\n name?: 'PlayDialog' | 'Play3.0-mini';\n apiKey?: string;\n userId?: string;\n}\n\nexport class PlayAIVoice extends MastraVoice {\n private baseUrl = 'https://api.play.ai/api/v1';\n private userId: string;\n\n constructor({ speechModel, speaker }: { speechModel?: PlayAIConfig; speaker?: string } = {}) {\n super({\n speechModel: {\n name: speechModel?.name ?? 'PlayDialog',\n apiKey: speechModel?.apiKey ?? process.env.PLAYAI_API_KEY,\n },\n speaker: speaker ?? PLAYAI_VOICES[0]?.id,\n });\n const userId = speechModel?.userId ?? process.env.PLAYAI_USER_ID;\n if (!userId) {\n throw new Error('userId is required');\n }\n\n this.userId = userId;\n }\n\n private async makeRequest(endpoint: string, payload?: any, method: 'GET' | 'POST' = 'POST') {\n const headers = new Headers({\n Authorization: `Bearer ${this.speechModel?.apiKey}`,\n 'Content-Type': 'application/json',\n 'X-USER-ID': this.userId,\n });\n\n const response = await fetch(`${this.baseUrl}${endpoint}`, {\n method,\n headers,\n body: payload ? JSON.stringify(payload) : undefined,\n });\n\n if (!response.ok) {\n const error = (await response.json()) as { message: string };\n\n throw new Error(`PlayAI API Error: ${error.message || response.statusText}`);\n }\n\n return response;\n }\n\n private async streamToString(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n return Buffer.concat(chunks).toString('utf-8');\n }\n\n async speak(input: string | NodeJS.ReadableStream, options?: { speaker?: string }): Promise<NodeJS.ReadableStream> {\n const text = typeof input === 'string' ? input : await this.streamToString(input);\n\n const payload = {\n text,\n voice: options?.speaker || this.speaker,\n model: this.speechModel?.name,\n };\n\n const response = await this.makeRequest('/tts/stream', payload);\n if (!response.body) {\n throw new Error('No response body received');\n }\n\n // Create a PassThrough stream for the audio\n const stream = new PassThrough();\n\n // Process the stream\n const reader = response.body.getReader();\n void (async () => {\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n stream.end();\n break;\n }\n stream.write(value);\n }\n } catch (error) {\n stream.destroy(error as Error);\n }\n })();\n\n return stream;\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n return { enabled: false };\n }\n\n async listen(\n _input: NodeJS.ReadableStream,\n _options?: Record<string, unknown>,\n ): Promise<string | NodeJS.ReadableStream> {\n throw new Error('PlayAI does not support speech recognition');\n }\n\n async getSpeakers() {\n return Promise.resolve(\n PLAYAI_VOICES.map(voice => ({\n voiceId: voice.id,\n name: voice.name,\n accent: voice.accent,\n gender: voice.gender,\n age: voice.age,\n style: voice.style,\n })),\n );\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/voice-playai",
|
|
3
|
-
"version": "0.12.0
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Mastra PlayAI voice integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -23,17 +23,17 @@
|
|
|
23
23
|
"./package.json": "./package.json"
|
|
24
24
|
},
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
|
-
"dependencies": {},
|
|
27
26
|
"devDependencies": {
|
|
28
|
-
"@
|
|
29
|
-
"@
|
|
27
|
+
"@types/node": "22.13.17",
|
|
28
|
+
"@vitest/coverage-v8": "4.0.12",
|
|
29
|
+
"@vitest/ui": "4.0.12",
|
|
30
30
|
"eslint": "^9.37.0",
|
|
31
31
|
"tsup": "^8.5.0",
|
|
32
|
-
"typescript": "^5.
|
|
33
|
-
"vitest": "
|
|
34
|
-
"@internal/
|
|
35
|
-
"@
|
|
36
|
-
"@
|
|
32
|
+
"typescript": "^5.9.3",
|
|
33
|
+
"vitest": "4.0.16",
|
|
34
|
+
"@internal/types-builder": "0.0.29",
|
|
35
|
+
"@mastra/core": "1.0.0",
|
|
36
|
+
"@internal/lint": "0.0.54"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@mastra/core": ">=1.0.0-0 <2.0.0-0",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "tsup --silent --config tsup.config.ts",
|
|
56
|
+
"postbuild": "pnpx tsx ../../scripts/generate-package-docs.ts voice/playai",
|
|
56
57
|
"build:watch": "tsup --watch --silent --config tsup.config.ts",
|
|
57
58
|
"test": "vitest run",
|
|
58
59
|
"lint": "eslint ."
|