@mastra/voice-openai 0.11.12 → 0.12.0-beta.1

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 CHANGED
@@ -1,31 +1,28 @@
1
1
  # @mastra/voice-openai
2
2
 
3
- ## 0.11.12
3
+ ## 0.12.0-beta.1
4
4
 
5
5
  ### Patch Changes
6
6
 
7
- - update peerdeps ([`5ca1cca`](https://github.com/mastra-ai/mastra/commit/5ca1ccac61ffa7141e6d9fa8f22d3ad4d03bf5dc))
7
+ - feat(voice): Add configurable options support for OpenAI. ([#8063](https://github.com/mastra-ai/mastra/pull/8063))
8
8
 
9
- - Updated dependencies [[`5ca1cca`](https://github.com/mastra-ai/mastra/commit/5ca1ccac61ffa7141e6d9fa8f22d3ad4d03bf5dc), [`6d7e90d`](https://github.com/mastra-ai/mastra/commit/6d7e90db09713e6250f4d6c3d3cff1b4740e50f9), [`f78b908`](https://github.com/mastra-ai/mastra/commit/f78b9080e11af765969b36b4a619761056030840), [`23c2614`](https://github.com/mastra-ai/mastra/commit/23c26140fdbf04b8c59e8d7d52106d67dad962ec), [`e365eda`](https://github.com/mastra-ai/mastra/commit/e365eda45795b43707310531cac1e2ce4e5a0712)]:
10
- - @mastra/core@0.24.0
9
+ - Updated dependencies [[`2319326`](https://github.com/mastra-ai/mastra/commit/2319326f8c64e503a09bbcf14be2dd65405445e0), [`d629361`](https://github.com/mastra-ai/mastra/commit/d629361a60f6565b5bfb11976fdaf7308af858e2), [`08c31c1`](https://github.com/mastra-ai/mastra/commit/08c31c188ebccd598acaf55e888b6397d01f7eae), [`fd3d338`](https://github.com/mastra-ai/mastra/commit/fd3d338a2c362174ed5b383f1f011ad9fb0302aa), [`c30400a`](https://github.com/mastra-ai/mastra/commit/c30400a49b994b1b97256fe785eb6c906fc2b232), [`69e0a87`](https://github.com/mastra-ai/mastra/commit/69e0a878896a2da9494945d86e056a5f8f05b851), [`01f8878`](https://github.com/mastra-ai/mastra/commit/01f88783de25e4de048c1c8aace43e26373c6ea5), [`4c77209`](https://github.com/mastra-ai/mastra/commit/4c77209e6c11678808b365d545845918c40045c8), [`d827d08`](https://github.com/mastra-ai/mastra/commit/d827d0808ffe1f3553a84e975806cc989b9735dd), [`23c10a1`](https://github.com/mastra-ai/mastra/commit/23c10a1efdd9a693c405511ab2dc8a1236603162), [`676ccc7`](https://github.com/mastra-ai/mastra/commit/676ccc7fe92468d2d45d39c31a87825c89fd1ea0), [`c10398d`](https://github.com/mastra-ai/mastra/commit/c10398d5b88f1d4af556f4267ff06f1d11e89179), [`00c2387`](https://github.com/mastra-ai/mastra/commit/00c2387f5f04a365316f851e58666ac43f8c4edf), [`ad6250d`](https://github.com/mastra-ai/mastra/commit/ad6250dbdaad927e29f74a27b83f6c468b50a705), [`3a73998`](https://github.com/mastra-ai/mastra/commit/3a73998fa4ebeb7f3dc9301afe78095fc63e7999), [`e16d553`](https://github.com/mastra-ai/mastra/commit/e16d55338403c7553531cc568125c63d53653dff), [`4d59f58`](https://github.com/mastra-ai/mastra/commit/4d59f58de2d90d6e2810a19d4518e38ddddb9038), [`e1bb9c9`](https://github.com/mastra-ai/mastra/commit/e1bb9c94b4eb68b019ae275981be3feb769b5365), [`351a11f`](https://github.com/mastra-ai/mastra/commit/351a11fcaf2ed1008977fa9b9a489fc422e51cd4)]:
10
+ - @mastra/core@1.0.0-beta.3
11
11
 
12
- ## 0.11.12-alpha.0
12
+ ## 0.12.0-beta.0
13
13
 
14
- ### Patch Changes
14
+ ### Minor Changes
15
15
 
16
- - update peerdeps ([`5ca1cca`](https://github.com/mastra-ai/mastra/commit/5ca1ccac61ffa7141e6d9fa8f22d3ad4d03bf5dc))
16
+ - Update peer dependencies to match core package version bump (1.0.0) ([#9237](https://github.com/mastra-ai/mastra/pull/9237))
17
17
 
18
- - Updated dependencies [[`5ca1cca`](https://github.com/mastra-ai/mastra/commit/5ca1ccac61ffa7141e6d9fa8f22d3ad4d03bf5dc), [`6d7e90d`](https://github.com/mastra-ai/mastra/commit/6d7e90db09713e6250f4d6c3d3cff1b4740e50f9), [`f78b908`](https://github.com/mastra-ai/mastra/commit/f78b9080e11af765969b36b4a619761056030840), [`23c2614`](https://github.com/mastra-ai/mastra/commit/23c26140fdbf04b8c59e8d7d52106d67dad962ec), [`e365eda`](https://github.com/mastra-ai/mastra/commit/e365eda45795b43707310531cac1e2ce4e5a0712)]:
19
- - @mastra/core@0.24.0-alpha.0
18
+ - Bump minimum required Node.js version to 22.13.0 ([#9706](https://github.com/mastra-ai/mastra/pull/9706))
20
19
 
21
- ## 0.11.11
20
+ - Removed old tracing code based on OpenTelemetry ([#9237](https://github.com/mastra-ai/mastra/pull/9237))
22
21
 
23
22
  ### Patch Changes
24
23
 
25
- - Fix peerdependencies ([`eb7c1c8`](https://github.com/mastra-ai/mastra/commit/eb7c1c8c592d8fb16dfd250e337d9cdc73c8d5de))
26
-
27
- - Updated dependencies []:
28
- - @mastra/core@0.23.1
24
+ - Updated dependencies [[`39c9743`](https://github.com/mastra-ai/mastra/commit/39c97432d084294f8ba85fbf3ef28098ff21459e), [`f743dbb`](https://github.com/mastra-ai/mastra/commit/f743dbb8b40d1627b5c10c0e6fc154f4ebb6e394), [`fec5129`](https://github.com/mastra-ai/mastra/commit/fec5129de7fc64423ea03661a56cef31dc747a0d), [`0491e7c`](https://github.com/mastra-ai/mastra/commit/0491e7c9b714cb0ba22187ee062147ec2dd7c712), [`f6f4903`](https://github.com/mastra-ai/mastra/commit/f6f4903397314f73362061dc5a3e8e7c61ea34aa), [`0e8ed46`](https://github.com/mastra-ai/mastra/commit/0e8ed467c54d6901a6a365f270ec15d6faadb36c), [`6c049d9`](https://github.com/mastra-ai/mastra/commit/6c049d94063fdcbd5b81c4912a2bf82a92c9cc0b), [`2f897df`](https://github.com/mastra-ai/mastra/commit/2f897df208508f46f51b7625e5dd20c37f93e0e3), [`3443770`](https://github.com/mastra-ai/mastra/commit/3443770662df8eb24c9df3589b2792d78cfcb811), [`f0a07e0`](https://github.com/mastra-ai/mastra/commit/f0a07e0111b3307c5fabfa4094c5c2cfb734fbe6), [`aaa40e7`](https://github.com/mastra-ai/mastra/commit/aaa40e788628b319baa8e889407d11ad626547fa), [`1521d71`](https://github.com/mastra-ai/mastra/commit/1521d716e5daedc74690c983fbd961123c56756b), [`9e1911d`](https://github.com/mastra-ai/mastra/commit/9e1911db2b4db85e0e768c3f15e0d61e319869f6), [`ebac155`](https://github.com/mastra-ai/mastra/commit/ebac15564a590117db7078233f927a7e28a85106), [`dd1c38d`](https://github.com/mastra-ai/mastra/commit/dd1c38d1b75f1b695c27b40d8d9d6ed00d5e0f6f), [`5948e6a`](https://github.com/mastra-ai/mastra/commit/5948e6a5146c83666ba3f294b2be576c82a513fb), [`8940859`](https://github.com/mastra-ai/mastra/commit/89408593658199b4ad67f7b65e888f344e64a442), [`e629310`](https://github.com/mastra-ai/mastra/commit/e629310f1a73fa236d49ec7a1d1cceb6229dc7cc), [`4c6b492`](https://github.com/mastra-ai/mastra/commit/4c6b492c4dd591c6a592520c1f6855d6e936d71f), [`dff01d8`](https://github.com/mastra-ai/mastra/commit/dff01d81ce1f4e4087cfac20fa868e6db138dd14), [`9d819d5`](https://github.com/mastra-ai/mastra/commit/9d819d54b61481639f4008e4694791bddf187edd), [`71c8d6c`](https://github.com/mastra-ai/mastra/commit/71c8d6c161253207b2b9588bdadb7eed604f7253), [`6179a9b`](https://github.com/mastra-ai/mastra/commit/6179a9ba36ffac326de3cc3c43cdc8028d37c251), [`00f4921`](https://github.com/mastra-ai/mastra/commit/00f4921dd2c91a1e5446799599ef7116a8214a1a), [`ca8041c`](https://github.com/mastra-ai/mastra/commit/ca8041cce0379fda22ed293a565bcb5b6ddca68a), [`7051bf3`](https://github.com/mastra-ai/mastra/commit/7051bf38b3b122a069008f861f7bfc004a6d9f6e), [`a8f1494`](https://github.com/mastra-ai/mastra/commit/a8f1494f4bbdc2770bcf327d4c7d869e332183f1), [`0793497`](https://github.com/mastra-ai/mastra/commit/079349753620c40246ffd673e3f9d7d9820beff3), [`5df9cce`](https://github.com/mastra-ai/mastra/commit/5df9cce1a753438413f64c11eeef8f845745c2a8), [`a854ede`](https://github.com/mastra-ai/mastra/commit/a854ede62bf5ac0945a624ac48913dd69c73aabf), [`c576fc0`](https://github.com/mastra-ai/mastra/commit/c576fc0b100b2085afded91a37c97a0ea0ec09c7), [`3defc80`](https://github.com/mastra-ai/mastra/commit/3defc80cf2b88a1b7fc1cc4ddcb91e982a614609), [`16153fe`](https://github.com/mastra-ai/mastra/commit/16153fe7eb13c99401f48e6ca32707c965ee28b9), [`9f4a683`](https://github.com/mastra-ai/mastra/commit/9f4a6833e88b52574665c028fd5508ad5c2f6004), [`bc94344`](https://github.com/mastra-ai/mastra/commit/bc943444a1342d8a662151b7bce1df7dae32f59c), [`57d157f`](https://github.com/mastra-ai/mastra/commit/57d157f0b163a95c3e6c9eae31bdb11d1bfc64f9), [`903f67d`](https://github.com/mastra-ai/mastra/commit/903f67d184504a273893818c02b961f5423a79ad), [`2a90c55`](https://github.com/mastra-ai/mastra/commit/2a90c55a86a9210697d5adaab5ee94584b079adc), [`eb09742`](https://github.com/mastra-ai/mastra/commit/eb09742197f66c4c38154c3beec78313e69760b2), [`96d35f6`](https://github.com/mastra-ai/mastra/commit/96d35f61376bc2b1bf148648a2c1985bd51bef55), [`5cbe88a`](https://github.com/mastra-ai/mastra/commit/5cbe88aefbd9f933bca669fd371ea36bf939ac6d), [`a1bd7b8`](https://github.com/mastra-ai/mastra/commit/a1bd7b8571db16b94eb01588f451a74758c96d65), [`d78b38d`](https://github.com/mastra-ai/mastra/commit/d78b38d898fce285260d3bbb4befade54331617f), [`0633100`](https://github.com/mastra-ai/mastra/commit/0633100a911ad22f5256471bdf753da21c104742), [`c710c16`](https://github.com/mastra-ai/mastra/commit/c710c1652dccfdc4111c8412bca7a6bb1d48b441), [`354ad0b`](https://github.com/mastra-ai/mastra/commit/354ad0b7b1b8183ac567f236a884fc7ede6d7138), [`cfae733`](https://github.com/mastra-ai/mastra/commit/cfae73394f4920635e6c919c8e95ff9a0788e2e5), [`e3dfda7`](https://github.com/mastra-ai/mastra/commit/e3dfda7b11bf3b8c4bb55637028befb5f387fc74), [`844ea5d`](https://github.com/mastra-ai/mastra/commit/844ea5dc0c248961e7bf73629ae7dcff503e853c), [`398fde3`](https://github.com/mastra-ai/mastra/commit/398fde3f39e707cda79372cdae8f9870e3b57c8d), [`f0f8f12`](https://github.com/mastra-ai/mastra/commit/f0f8f125c308f2d0fd36942ef652fd852df7522f), [`0d7618b`](https://github.com/mastra-ai/mastra/commit/0d7618bc650bf2800934b243eca5648f4aeed9c2), [`7b763e5`](https://github.com/mastra-ai/mastra/commit/7b763e52fc3eaf699c2a99f2adf418dd46e4e9a5), [`d36cfbb`](https://github.com/mastra-ai/mastra/commit/d36cfbbb6565ba5f827883cc9bb648eb14befdc1), [`3697853`](https://github.com/mastra-ai/mastra/commit/3697853deeb72017d90e0f38a93c1e29221aeca0), [`b2e45ec`](https://github.com/mastra-ai/mastra/commit/b2e45eca727a8db01a81ba93f1a5219c7183c839), [`d6d49f7`](https://github.com/mastra-ai/mastra/commit/d6d49f7b8714fa19a52ff9c7cf7fb7e73751901e), [`a534e95`](https://github.com/mastra-ai/mastra/commit/a534e9591f83b3cc1ebff99c67edf4cda7bf81d3), [`9d0e7fe`](https://github.com/mastra-ai/mastra/commit/9d0e7feca8ed98de959f53476ee1456073673348), [`53d927c`](https://github.com/mastra-ai/mastra/commit/53d927cc6f03bff33655b7e2b788da445a08731d), [`3f2faf2`](https://github.com/mastra-ai/mastra/commit/3f2faf2e2d685d6c053cc5af1bf9fedf267b2ce5), [`22f64bc`](https://github.com/mastra-ai/mastra/commit/22f64bc1d37149480b58bf2fefe35b79a1e3e7d5), [`83d5942`](https://github.com/mastra-ai/mastra/commit/83d5942669ce7bba4a6ca4fd4da697a10eb5ebdc), [`b7959e6`](https://github.com/mastra-ai/mastra/commit/b7959e6e25a46b480f9ea2217c4c6c588c423791), [`bda6370`](https://github.com/mastra-ai/mastra/commit/bda637009360649aaf579919e7873e33553c273e), [`d7acd8e`](https://github.com/mastra-ai/mastra/commit/d7acd8e987b5d7eff4fd98b0906c17c06a2e83d5), [`c7f1f7d`](https://github.com/mastra-ai/mastra/commit/c7f1f7d24f61f247f018cc2d1f33bf63212959a7), [`0bddc6d`](https://github.com/mastra-ai/mastra/commit/0bddc6d8dbd6f6008c0cba2e4960a2da75a55af1), [`735d8c1`](https://github.com/mastra-ai/mastra/commit/735d8c1c0d19fbc09e6f8b66cf41bc7655993838), [`acf322e`](https://github.com/mastra-ai/mastra/commit/acf322e0f1fd0189684cf529d91c694bea918a45), [`c942802`](https://github.com/mastra-ai/mastra/commit/c942802a477a925b01859a7b8688d4355715caaa), [`a0c8c1b`](https://github.com/mastra-ai/mastra/commit/a0c8c1b87d4fee252aebda73e8637fbe01d761c9), [`cc34739`](https://github.com/mastra-ai/mastra/commit/cc34739c34b6266a91bea561119240a7acf47887), [`c218bd3`](https://github.com/mastra-ai/mastra/commit/c218bd3759e32423735b04843a09404572631014), [`2c4438b`](https://github.com/mastra-ai/mastra/commit/2c4438b87817ab7eed818c7990fef010475af1a3), [`2b8893c`](https://github.com/mastra-ai/mastra/commit/2b8893cb108ef9acb72ee7835cd625610d2c1a4a), [`8e5c75b`](https://github.com/mastra-ai/mastra/commit/8e5c75bdb1d08a42d45309a4c72def4b6890230f), [`e59e0d3`](https://github.com/mastra-ai/mastra/commit/e59e0d32afb5fcf2c9f3c00c8f81f6c21d3a63fa), [`fa8409b`](https://github.com/mastra-ai/mastra/commit/fa8409bc39cfd8ba6643b9db5269b90b22e2a2f7), [`173c535`](https://github.com/mastra-ai/mastra/commit/173c535c0645b0da404fe09f003778f0b0d4e019)]:
25
+ - @mastra/core@1.0.0-beta.0
29
26
 
30
27
  ## 0.11.10
31
28
 
package/dist/index.cjs CHANGED
@@ -50,12 +50,18 @@ var OpenAIVoice = class extends voice.MastraVoice {
50
50
  if (!speechApiKey) {
51
51
  throw new Error("No API key provided for speech model");
52
52
  }
53
- this.speechClient = new OpenAI__default.default({ apiKey: speechApiKey });
53
+ this.speechClient = new OpenAI__default.default({
54
+ apiKey: speechApiKey,
55
+ ...speechModel?.options
56
+ });
54
57
  const listeningApiKey = listeningModel?.apiKey || defaultApiKey;
55
58
  if (!listeningApiKey) {
56
59
  throw new Error("No API key provided for listening model");
57
60
  }
58
- this.listeningClient = new OpenAI__default.default({ apiKey: listeningApiKey });
61
+ this.listeningClient = new OpenAI__default.default({
62
+ apiKey: listeningApiKey,
63
+ ...listeningModel?.options
64
+ });
59
65
  if (!this.speechClient && !this.listeningClient) {
60
66
  throw new Error("At least one of OPENAI_API_KEY, speechModel.apiKey, or listeningModel.apiKey must be set");
61
67
  }
@@ -112,21 +118,18 @@ var OpenAIVoice = class extends voice.MastraVoice {
112
118
  throw new Error("Input text is empty");
113
119
  }
114
120
  const { speaker, responseFormat, speed, ...otherOptions } = options || {};
115
- const audio = await this.traced(async () => {
116
- const response = await this.speechClient.audio.speech.create({
117
- model: this.speechModel?.name ?? "tts-1",
118
- voice: speaker ?? this.speaker,
119
- response_format: responseFormat ?? "mp3",
120
- input,
121
- speed: speed || 1,
122
- ...otherOptions
123
- });
124
- const passThrough = new stream.PassThrough();
125
- const buffer = Buffer.from(await response.arrayBuffer());
126
- passThrough.end(buffer);
127
- return passThrough;
128
- }, "voice.openai.speak")();
129
- return audio;
121
+ const response = await this.speechClient.audio.speech.create({
122
+ model: this.speechModel?.name ?? "tts-1",
123
+ voice: speaker ?? this.speaker,
124
+ response_format: responseFormat ?? "mp3",
125
+ input,
126
+ speed: speed || 1,
127
+ ...otherOptions
128
+ });
129
+ const passThrough = new stream.PassThrough();
130
+ const buffer = Buffer.from(await response.arrayBuffer());
131
+ passThrough.end(buffer);
132
+ return passThrough;
130
133
  }
131
134
  /**
132
135
  * Checks if listening capabilities are enabled.
@@ -162,17 +165,14 @@ var OpenAIVoice = class extends voice.MastraVoice {
162
165
  }
163
166
  }
164
167
  const audioBuffer = Buffer.concat(chunks);
165
- const text = await this.traced(async () => {
166
- const { filetype, ...otherOptions } = options || {};
167
- const file = new File([audioBuffer], `audio.${filetype || "mp3"}`);
168
- const response = await this.listeningClient.audio.transcriptions.create({
169
- model: this.listeningModel?.name || "whisper-1",
170
- file,
171
- ...otherOptions
172
- });
173
- return response.text;
174
- }, "voice.openai.listen")();
175
- return text;
168
+ const { filetype, ...otherOptions } = options || {};
169
+ const file = new File([audioBuffer], `audio.${filetype || "mp3"}`);
170
+ const response = await this.listeningClient.audio.transcriptions.create({
171
+ model: this.listeningModel?.name || "whisper-1",
172
+ file,
173
+ ...otherOptions
174
+ });
175
+ return response.text;
176
176
  }
177
177
  };
178
178
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["MastraVoice","OpenAI","PassThrough"],"mappings":"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","file":"index.cjs","sourcesContent":["import { PassThrough } from 'stream';\n\nimport { MastraVoice } from '@mastra/core/voice';\nimport OpenAI from 'openai';\n\ntype OpenAIVoiceId = 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer' | 'ash' | 'coral' | 'sage';\ntype OpenAIModel = 'tts-1' | 'tts-1-hd' | 'whisper-1';\n\nexport interface OpenAIConfig {\n name?: OpenAIModel;\n apiKey?: string;\n}\n\nexport interface OpenAIVoiceConfig {\n speech?: {\n model: 'tts-1' | 'tts-1-hd';\n apiKey?: string;\n speaker?: OpenAIVoiceId;\n };\n listening?: {\n model: 'whisper-1';\n apiKey?: string;\n };\n}\n\nexport class OpenAIVoice extends MastraVoice {\n speechClient?: OpenAI;\n listeningClient?: OpenAI;\n\n /**\n * Constructs an instance of OpenAIVoice with optional configurations for speech and listening models.\n *\n * @param {Object} [config] - Configuration options for the OpenAIVoice instance.\n * @param {OpenAIConfig} [config.listeningModel] - Configuration for the listening model, including model name and API key.\n * @param {OpenAIConfig} [config.speechModel] - Configuration for the speech model, including model name and API key.\n * @param {string} [config.speaker] - The default speaker's voice to use for speech synthesis.\n * @throws {Error} - Throws an error if no API key is provided for either the speech or listening model.\n */\n constructor({\n listeningModel,\n speechModel,\n speaker,\n }: {\n listeningModel?: OpenAIConfig;\n speechModel?: OpenAIConfig;\n speaker?: string;\n } = {}) {\n const defaultApiKey = process.env.OPENAI_API_KEY;\n const defaultSpeechModel = {\n name: 'tts-1',\n apiKey: defaultApiKey,\n };\n const defaultListeningModel = {\n name: 'whisper-1',\n apiKey: defaultApiKey,\n };\n\n super({\n speechModel: {\n name: speechModel?.name ?? defaultSpeechModel.name,\n apiKey: speechModel?.apiKey ?? defaultSpeechModel.apiKey,\n },\n listeningModel: {\n name: listeningModel?.name ?? defaultListeningModel.name,\n apiKey: listeningModel?.apiKey ?? defaultListeningModel.apiKey,\n },\n speaker: speaker ?? 'alloy',\n });\n\n const speechApiKey = speechModel?.apiKey || defaultApiKey;\n if (!speechApiKey) {\n throw new Error('No API key provided for speech model');\n }\n this.speechClient = new OpenAI({ apiKey: speechApiKey });\n\n const listeningApiKey = listeningModel?.apiKey || defaultApiKey;\n if (!listeningApiKey) {\n throw new Error('No API key provided for listening model');\n }\n this.listeningClient = new OpenAI({ apiKey: listeningApiKey });\n\n if (!this.speechClient && !this.listeningClient) {\n throw new Error('At least one of OPENAI_API_KEY, speechModel.apiKey, or listeningModel.apiKey must be set');\n }\n }\n\n /**\n * Retrieves a list of available speakers for the speech model.\n *\n * @returns {Promise<Array<{ voiceId: OpenAIVoiceId }>>} - A promise that resolves to an array of objects,\n * each containing a `voiceId` representing an available speaker.\n * @throws {Error} - Throws an error if the speech model is not configured.\n */\n async getSpeakers(): Promise<Array<{ voiceId: OpenAIVoiceId }>> {\n if (!this.speechModel) {\n throw new Error('Speech model not configured');\n }\n\n return [\n { voiceId: 'alloy' },\n { voiceId: 'echo' },\n { voiceId: 'fable' },\n { voiceId: 'onyx' },\n { voiceId: 'nova' },\n { voiceId: 'shimmer' },\n { voiceId: 'ash' },\n { voiceId: 'coral' },\n { voiceId: 'sage' },\n ];\n }\n\n /**\n * Converts text or audio input into speech using the configured speech model.\n *\n * @param {string | NodeJS.ReadableStream} input - The text or audio stream to be converted into speech.\n * @param {Object} [options] - Optional parameters for the speech synthesis.\n * @param {string} [options.speaker] - The speaker's voice to use for the speech synthesis.\n * @param {number} [options.speed] - The speed at which the speech should be synthesized.\n * @returns {Promise<NodeJS.ReadableStream>} - A promise that resolves to a readable stream of the synthesized audio.\n * @throws {Error} - Throws an error if the speech model is not configured or if the input text is empty.\n */\n async speak(\n input: string | NodeJS.ReadableStream,\n options?: {\n speaker?: string;\n speed?: number;\n [key: string]: any;\n },\n ): Promise<NodeJS.ReadableStream> {\n if (!this.speechClient) {\n throw new Error('Speech model not configured');\n }\n\n if (typeof input !== 'string') {\n const chunks: Buffer[] = [];\n for await (const chunk of input) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n input = Buffer.concat(chunks).toString('utf-8');\n }\n\n if (input.trim().length === 0) {\n throw new Error('Input text is empty');\n }\n\n const { speaker, responseFormat, speed, ...otherOptions } = options || {};\n\n const audio = await this.traced(async () => {\n const response = await this.speechClient!.audio.speech.create({\n model: this.speechModel?.name ?? 'tts-1',\n voice: (speaker ?? this.speaker) as OpenAIVoiceId,\n response_format: responseFormat ?? 'mp3',\n input,\n speed: speed || 1.0,\n ...otherOptions,\n });\n\n const passThrough = new PassThrough();\n const buffer = Buffer.from(await response.arrayBuffer());\n passThrough.end(buffer);\n return passThrough;\n }, 'voice.openai.speak')();\n\n return audio;\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n if (!this.listeningClient) {\n return { enabled: false };\n }\n return { enabled: true };\n }\n\n /**\n * Transcribes audio from a given stream using the configured listening model.\n *\n * @param {NodeJS.ReadableStream} audioStream - The audio stream to be transcribed.\n * @param {Object} [options] - Optional parameters for the transcription.\n * @param {string} [options.filetype] - The file type of the audio stream.\n * Supported types include 'mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm'.\n * @returns {Promise<string>} - A promise that resolves to the transcribed text.\n * @throws {Error} - Throws an error if the listening model is not configured.\n */\n async listen(\n audioStream: NodeJS.ReadableStream,\n options?: {\n filetype?: 'mp3' | 'mp4' | 'mpeg' | 'mpga' | 'm4a' | 'wav' | 'webm';\n [key: string]: any;\n },\n ): Promise<string> {\n if (!this.listeningClient) {\n throw new Error('Listening model not configured');\n }\n\n const chunks: Buffer[] = [];\n for await (const chunk of audioStream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n const audioBuffer = Buffer.concat(chunks);\n\n const text = await this.traced(async () => {\n const { filetype, ...otherOptions } = options || {};\n const file = new File([audioBuffer], `audio.${filetype || 'mp3'}`);\n\n const response = await this.listeningClient!.audio.transcriptions.create({\n model: this.listeningModel?.name || 'whisper-1',\n file: file as any,\n ...otherOptions,\n });\n\n return response.text;\n }, 'voice.openai.listen')();\n\n return text;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["MastraVoice","OpenAI","PassThrough"],"mappings":"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","file":"index.cjs","sourcesContent":["import { PassThrough } from 'stream';\n\nimport { MastraVoice } from '@mastra/core/voice';\nimport OpenAI from 'openai';\nimport type { ClientOptions } from 'openai';\n\ntype OpenAIVoiceId = 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer' | 'ash' | 'coral' | 'sage';\ntype OpenAIModel = 'tts-1' | 'tts-1-hd' | 'whisper-1';\n\nexport interface OpenAIConfig {\n name?: OpenAIModel;\n apiKey?: string;\n options?: Omit<ClientOptions, 'apiKey'>;\n}\n\nexport interface OpenAIVoiceConfig {\n speech?: {\n model: 'tts-1' | 'tts-1-hd';\n apiKey?: string;\n speaker?: OpenAIVoiceId;\n options?: Omit<ClientOptions, 'apiKey'>;\n };\n listening?: {\n model: 'whisper-1';\n apiKey?: string;\n options?: Omit<ClientOptions, 'apiKey'>;\n };\n}\n\nexport class OpenAIVoice extends MastraVoice {\n speechClient?: OpenAI;\n listeningClient?: OpenAI;\n\n /**\n * Constructs an instance of OpenAIVoice with optional configurations for speech and listening models.\n *\n * @param {Object} [config] - Configuration options for the OpenAIVoice instance.\n * @param {OpenAIConfig} [config.listeningModel] - Configuration for the listening model, including model name and API key.\n * @param {OpenAIConfig} [config.speechModel] - Configuration for the speech model, including model name and API key.\n * @param {string} [config.speaker] - The default speaker's voice to use for speech synthesis.\n * @throws {Error} - Throws an error if no API key is provided for either the speech or listening model.\n */\n constructor({\n listeningModel,\n speechModel,\n speaker,\n }: {\n listeningModel?: OpenAIConfig;\n speechModel?: OpenAIConfig;\n speaker?: string;\n } = {}) {\n const defaultApiKey = process.env.OPENAI_API_KEY;\n const defaultSpeechModel = {\n name: 'tts-1',\n apiKey: defaultApiKey,\n };\n const defaultListeningModel = {\n name: 'whisper-1',\n apiKey: defaultApiKey,\n };\n\n super({\n speechModel: {\n name: speechModel?.name ?? defaultSpeechModel.name,\n apiKey: speechModel?.apiKey ?? defaultSpeechModel.apiKey,\n },\n listeningModel: {\n name: listeningModel?.name ?? defaultListeningModel.name,\n apiKey: listeningModel?.apiKey ?? defaultListeningModel.apiKey,\n },\n speaker: speaker ?? 'alloy',\n });\n\n const speechApiKey = speechModel?.apiKey || defaultApiKey;\n if (!speechApiKey) {\n throw new Error('No API key provided for speech model');\n }\n this.speechClient = new OpenAI({\n apiKey: speechApiKey,\n ...speechModel?.options,\n });\n\n const listeningApiKey = listeningModel?.apiKey || defaultApiKey;\n if (!listeningApiKey) {\n throw new Error('No API key provided for listening model');\n }\n this.listeningClient = new OpenAI({\n apiKey: listeningApiKey,\n ...listeningModel?.options,\n });\n\n if (!this.speechClient && !this.listeningClient) {\n throw new Error('At least one of OPENAI_API_KEY, speechModel.apiKey, or listeningModel.apiKey must be set');\n }\n }\n\n /**\n * Retrieves a list of available speakers for the speech model.\n *\n * @returns {Promise<Array<{ voiceId: OpenAIVoiceId }>>} - A promise that resolves to an array of objects,\n * each containing a `voiceId` representing an available speaker.\n * @throws {Error} - Throws an error if the speech model is not configured.\n */\n async getSpeakers(): Promise<Array<{ voiceId: OpenAIVoiceId }>> {\n if (!this.speechModel) {\n throw new Error('Speech model not configured');\n }\n\n return [\n { voiceId: 'alloy' },\n { voiceId: 'echo' },\n { voiceId: 'fable' },\n { voiceId: 'onyx' },\n { voiceId: 'nova' },\n { voiceId: 'shimmer' },\n { voiceId: 'ash' },\n { voiceId: 'coral' },\n { voiceId: 'sage' },\n ];\n }\n\n /**\n * Converts text or audio input into speech using the configured speech model.\n *\n * @param {string | NodeJS.ReadableStream} input - The text or audio stream to be converted into speech.\n * @param {Object} [options] - Optional parameters for the speech synthesis.\n * @param {string} [options.speaker] - The speaker's voice to use for the speech synthesis.\n * @param {number} [options.speed] - The speed at which the speech should be synthesized.\n * @returns {Promise<NodeJS.ReadableStream>} - A promise that resolves to a readable stream of the synthesized audio.\n * @throws {Error} - Throws an error if the speech model is not configured or if the input text is empty.\n */\n async speak(\n input: string | NodeJS.ReadableStream,\n options?: {\n speaker?: string;\n speed?: number;\n [key: string]: any;\n },\n ): Promise<NodeJS.ReadableStream> {\n if (!this.speechClient) {\n throw new Error('Speech model not configured');\n }\n\n if (typeof input !== 'string') {\n const chunks: Buffer[] = [];\n for await (const chunk of input) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n input = Buffer.concat(chunks).toString('utf-8');\n }\n\n if (input.trim().length === 0) {\n throw new Error('Input text is empty');\n }\n\n const { speaker, responseFormat, speed, ...otherOptions } = options || {};\n\n const response = await this.speechClient!.audio.speech.create({\n model: this.speechModel?.name ?? 'tts-1',\n voice: (speaker ?? this.speaker) as OpenAIVoiceId,\n response_format: responseFormat ?? 'mp3',\n input,\n speed: speed || 1.0,\n ...otherOptions,\n });\n\n const passThrough = new PassThrough();\n const buffer = Buffer.from(await response.arrayBuffer());\n passThrough.end(buffer);\n return passThrough;\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n if (!this.listeningClient) {\n return { enabled: false };\n }\n return { enabled: true };\n }\n\n /**\n * Transcribes audio from a given stream using the configured listening model.\n *\n * @param {NodeJS.ReadableStream} audioStream - The audio stream to be transcribed.\n * @param {Object} [options] - Optional parameters for the transcription.\n * @param {string} [options.filetype] - The file type of the audio stream.\n * Supported types include 'mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm'.\n * @returns {Promise<string>} - A promise that resolves to the transcribed text.\n * @throws {Error} - Throws an error if the listening model is not configured.\n */\n async listen(\n audioStream: NodeJS.ReadableStream,\n options?: {\n filetype?: 'mp3' | 'mp4' | 'mpeg' | 'mpga' | 'm4a' | 'wav' | 'webm';\n [key: string]: any;\n },\n ): Promise<string> {\n if (!this.listeningClient) {\n throw new Error('Listening model not configured');\n }\n\n const chunks: Buffer[] = [];\n for await (const chunk of audioStream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n const audioBuffer = Buffer.concat(chunks);\n\n const { filetype, ...otherOptions } = options || {};\n const file = new File([audioBuffer], `audio.${filetype || 'mp3'}`);\n\n const response = await this.listeningClient!.audio.transcriptions.create({\n model: this.listeningModel?.name || 'whisper-1',\n file: file as any,\n ...otherOptions,\n });\n\n return response.text;\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,20 +1,24 @@
1
1
  import { MastraVoice } from '@mastra/core/voice';
2
2
  import OpenAI from 'openai';
3
+ import type { ClientOptions } from 'openai';
3
4
  type OpenAIVoiceId = 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer' | 'ash' | 'coral' | 'sage';
4
5
  type OpenAIModel = 'tts-1' | 'tts-1-hd' | 'whisper-1';
5
6
  export interface OpenAIConfig {
6
7
  name?: OpenAIModel;
7
8
  apiKey?: string;
9
+ options?: Omit<ClientOptions, 'apiKey'>;
8
10
  }
9
11
  export interface OpenAIVoiceConfig {
10
12
  speech?: {
11
13
  model: 'tts-1' | 'tts-1-hd';
12
14
  apiKey?: string;
13
15
  speaker?: OpenAIVoiceId;
16
+ options?: Omit<ClientOptions, 'apiKey'>;
14
17
  };
15
18
  listening?: {
16
19
  model: 'whisper-1';
17
20
  apiKey?: string;
21
+ options?: Omit<ClientOptions, 'apiKey'>;
18
22
  };
19
23
  }
20
24
  export declare class OpenAIVoice extends MastraVoice {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,KAAK,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;AACzG,KAAK,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,OAAO,GAAG,UAAU,CAAC;QAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,aAAa,CAAC;KACzB,CAAC;IACF,SAAS,CAAC,EAAE;QACV,KAAK,EAAE,WAAW,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,qBAAa,WAAY,SAAQ,WAAW;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;;;;;OAQG;gBACS,EACV,cAAc,EACd,WAAW,EACX,OAAO,GACR,GAAE;QACD,cAAc,CAAC,EAAE,YAAY,CAAC;QAC9B,WAAW,CAAC,EAAE,YAAY,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;KACb;IAwCN;;;;;;OAMG;IACG,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAkB/D;;;;;;;;;OASG;IACG,KAAK,CACT,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,cAAc,EACrC,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,GACA,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;IA0CjC;;;;OAIG;IACG,WAAW;;;IAOjB;;;;;;;;;OASG;IACG,MAAM,CACV,WAAW,EAAE,MAAM,CAAC,cAAc,EAClC,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;QACpE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,GACA,OAAO,CAAC,MAAM,CAAC;CA8BnB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,KAAK,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;AACzG,KAAK,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,CAAC;AAEtD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,OAAO,GAAG,UAAU,CAAC;QAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,aAAa,CAAC;QACxB,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;KACzC,CAAC;IACF,SAAS,CAAC,EAAE;QACV,KAAK,EAAE,WAAW,CAAC;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;KACzC,CAAC;CACH;AAED,qBAAa,WAAY,SAAQ,WAAW;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;;;;;OAQG;gBACS,EACV,cAAc,EACd,WAAW,EACX,OAAO,GACR,GAAE;QACD,cAAc,CAAC,EAAE,YAAY,CAAC;QAC9B,WAAW,CAAC,EAAE,YAAY,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;KACb;IA8CN;;;;;;OAMG;IACG,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAkB/D;;;;;;;;;OASG;IACG,KAAK,CACT,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,cAAc,EACrC,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,GACA,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC;IAsCjC;;;;OAIG;IACG,WAAW;;;IAOjB;;;;;;;;;OASG;IACG,MAAM,CACV,WAAW,EAAE,MAAM,CAAC,cAAc,EAClC,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;QACpE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,GACA,OAAO,CAAC,MAAM,CAAC;CA0BnB"}
package/dist/index.js CHANGED
@@ -44,12 +44,18 @@ var OpenAIVoice = class extends MastraVoice {
44
44
  if (!speechApiKey) {
45
45
  throw new Error("No API key provided for speech model");
46
46
  }
47
- this.speechClient = new OpenAI({ apiKey: speechApiKey });
47
+ this.speechClient = new OpenAI({
48
+ apiKey: speechApiKey,
49
+ ...speechModel?.options
50
+ });
48
51
  const listeningApiKey = listeningModel?.apiKey || defaultApiKey;
49
52
  if (!listeningApiKey) {
50
53
  throw new Error("No API key provided for listening model");
51
54
  }
52
- this.listeningClient = new OpenAI({ apiKey: listeningApiKey });
55
+ this.listeningClient = new OpenAI({
56
+ apiKey: listeningApiKey,
57
+ ...listeningModel?.options
58
+ });
53
59
  if (!this.speechClient && !this.listeningClient) {
54
60
  throw new Error("At least one of OPENAI_API_KEY, speechModel.apiKey, or listeningModel.apiKey must be set");
55
61
  }
@@ -106,21 +112,18 @@ var OpenAIVoice = class extends MastraVoice {
106
112
  throw new Error("Input text is empty");
107
113
  }
108
114
  const { speaker, responseFormat, speed, ...otherOptions } = options || {};
109
- const audio = await this.traced(async () => {
110
- const response = await this.speechClient.audio.speech.create({
111
- model: this.speechModel?.name ?? "tts-1",
112
- voice: speaker ?? this.speaker,
113
- response_format: responseFormat ?? "mp3",
114
- input,
115
- speed: speed || 1,
116
- ...otherOptions
117
- });
118
- const passThrough = new PassThrough();
119
- const buffer = Buffer.from(await response.arrayBuffer());
120
- passThrough.end(buffer);
121
- return passThrough;
122
- }, "voice.openai.speak")();
123
- return audio;
115
+ const response = await this.speechClient.audio.speech.create({
116
+ model: this.speechModel?.name ?? "tts-1",
117
+ voice: speaker ?? this.speaker,
118
+ response_format: responseFormat ?? "mp3",
119
+ input,
120
+ speed: speed || 1,
121
+ ...otherOptions
122
+ });
123
+ const passThrough = new PassThrough();
124
+ const buffer = Buffer.from(await response.arrayBuffer());
125
+ passThrough.end(buffer);
126
+ return passThrough;
124
127
  }
125
128
  /**
126
129
  * Checks if listening capabilities are enabled.
@@ -156,17 +159,14 @@ var OpenAIVoice = class extends MastraVoice {
156
159
  }
157
160
  }
158
161
  const audioBuffer = Buffer.concat(chunks);
159
- const text = await this.traced(async () => {
160
- const { filetype, ...otherOptions } = options || {};
161
- const file = new File([audioBuffer], `audio.${filetype || "mp3"}`);
162
- const response = await this.listeningClient.audio.transcriptions.create({
163
- model: this.listeningModel?.name || "whisper-1",
164
- file,
165
- ...otherOptions
166
- });
167
- return response.text;
168
- }, "voice.openai.listen")();
169
- return text;
162
+ const { filetype, ...otherOptions } = options || {};
163
+ const file = new File([audioBuffer], `audio.${filetype || "mp3"}`);
164
+ const response = await this.listeningClient.audio.transcriptions.create({
165
+ model: this.listeningModel?.name || "whisper-1",
166
+ file,
167
+ ...otherOptions
168
+ });
169
+ return response.text;
170
170
  }
171
171
  };
172
172
 
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';\nimport OpenAI from 'openai';\n\ntype OpenAIVoiceId = 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer' | 'ash' | 'coral' | 'sage';\ntype OpenAIModel = 'tts-1' | 'tts-1-hd' | 'whisper-1';\n\nexport interface OpenAIConfig {\n name?: OpenAIModel;\n apiKey?: string;\n}\n\nexport interface OpenAIVoiceConfig {\n speech?: {\n model: 'tts-1' | 'tts-1-hd';\n apiKey?: string;\n speaker?: OpenAIVoiceId;\n };\n listening?: {\n model: 'whisper-1';\n apiKey?: string;\n };\n}\n\nexport class OpenAIVoice extends MastraVoice {\n speechClient?: OpenAI;\n listeningClient?: OpenAI;\n\n /**\n * Constructs an instance of OpenAIVoice with optional configurations for speech and listening models.\n *\n * @param {Object} [config] - Configuration options for the OpenAIVoice instance.\n * @param {OpenAIConfig} [config.listeningModel] - Configuration for the listening model, including model name and API key.\n * @param {OpenAIConfig} [config.speechModel] - Configuration for the speech model, including model name and API key.\n * @param {string} [config.speaker] - The default speaker's voice to use for speech synthesis.\n * @throws {Error} - Throws an error if no API key is provided for either the speech or listening model.\n */\n constructor({\n listeningModel,\n speechModel,\n speaker,\n }: {\n listeningModel?: OpenAIConfig;\n speechModel?: OpenAIConfig;\n speaker?: string;\n } = {}) {\n const defaultApiKey = process.env.OPENAI_API_KEY;\n const defaultSpeechModel = {\n name: 'tts-1',\n apiKey: defaultApiKey,\n };\n const defaultListeningModel = {\n name: 'whisper-1',\n apiKey: defaultApiKey,\n };\n\n super({\n speechModel: {\n name: speechModel?.name ?? defaultSpeechModel.name,\n apiKey: speechModel?.apiKey ?? defaultSpeechModel.apiKey,\n },\n listeningModel: {\n name: listeningModel?.name ?? defaultListeningModel.name,\n apiKey: listeningModel?.apiKey ?? defaultListeningModel.apiKey,\n },\n speaker: speaker ?? 'alloy',\n });\n\n const speechApiKey = speechModel?.apiKey || defaultApiKey;\n if (!speechApiKey) {\n throw new Error('No API key provided for speech model');\n }\n this.speechClient = new OpenAI({ apiKey: speechApiKey });\n\n const listeningApiKey = listeningModel?.apiKey || defaultApiKey;\n if (!listeningApiKey) {\n throw new Error('No API key provided for listening model');\n }\n this.listeningClient = new OpenAI({ apiKey: listeningApiKey });\n\n if (!this.speechClient && !this.listeningClient) {\n throw new Error('At least one of OPENAI_API_KEY, speechModel.apiKey, or listeningModel.apiKey must be set');\n }\n }\n\n /**\n * Retrieves a list of available speakers for the speech model.\n *\n * @returns {Promise<Array<{ voiceId: OpenAIVoiceId }>>} - A promise that resolves to an array of objects,\n * each containing a `voiceId` representing an available speaker.\n * @throws {Error} - Throws an error if the speech model is not configured.\n */\n async getSpeakers(): Promise<Array<{ voiceId: OpenAIVoiceId }>> {\n if (!this.speechModel) {\n throw new Error('Speech model not configured');\n }\n\n return [\n { voiceId: 'alloy' },\n { voiceId: 'echo' },\n { voiceId: 'fable' },\n { voiceId: 'onyx' },\n { voiceId: 'nova' },\n { voiceId: 'shimmer' },\n { voiceId: 'ash' },\n { voiceId: 'coral' },\n { voiceId: 'sage' },\n ];\n }\n\n /**\n * Converts text or audio input into speech using the configured speech model.\n *\n * @param {string | NodeJS.ReadableStream} input - The text or audio stream to be converted into speech.\n * @param {Object} [options] - Optional parameters for the speech synthesis.\n * @param {string} [options.speaker] - The speaker's voice to use for the speech synthesis.\n * @param {number} [options.speed] - The speed at which the speech should be synthesized.\n * @returns {Promise<NodeJS.ReadableStream>} - A promise that resolves to a readable stream of the synthesized audio.\n * @throws {Error} - Throws an error if the speech model is not configured or if the input text is empty.\n */\n async speak(\n input: string | NodeJS.ReadableStream,\n options?: {\n speaker?: string;\n speed?: number;\n [key: string]: any;\n },\n ): Promise<NodeJS.ReadableStream> {\n if (!this.speechClient) {\n throw new Error('Speech model not configured');\n }\n\n if (typeof input !== 'string') {\n const chunks: Buffer[] = [];\n for await (const chunk of input) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n input = Buffer.concat(chunks).toString('utf-8');\n }\n\n if (input.trim().length === 0) {\n throw new Error('Input text is empty');\n }\n\n const { speaker, responseFormat, speed, ...otherOptions } = options || {};\n\n const audio = await this.traced(async () => {\n const response = await this.speechClient!.audio.speech.create({\n model: this.speechModel?.name ?? 'tts-1',\n voice: (speaker ?? this.speaker) as OpenAIVoiceId,\n response_format: responseFormat ?? 'mp3',\n input,\n speed: speed || 1.0,\n ...otherOptions,\n });\n\n const passThrough = new PassThrough();\n const buffer = Buffer.from(await response.arrayBuffer());\n passThrough.end(buffer);\n return passThrough;\n }, 'voice.openai.speak')();\n\n return audio;\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n if (!this.listeningClient) {\n return { enabled: false };\n }\n return { enabled: true };\n }\n\n /**\n * Transcribes audio from a given stream using the configured listening model.\n *\n * @param {NodeJS.ReadableStream} audioStream - The audio stream to be transcribed.\n * @param {Object} [options] - Optional parameters for the transcription.\n * @param {string} [options.filetype] - The file type of the audio stream.\n * Supported types include 'mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm'.\n * @returns {Promise<string>} - A promise that resolves to the transcribed text.\n * @throws {Error} - Throws an error if the listening model is not configured.\n */\n async listen(\n audioStream: NodeJS.ReadableStream,\n options?: {\n filetype?: 'mp3' | 'mp4' | 'mpeg' | 'mpga' | 'm4a' | 'wav' | 'webm';\n [key: string]: any;\n },\n ): Promise<string> {\n if (!this.listeningClient) {\n throw new Error('Listening model not configured');\n }\n\n const chunks: Buffer[] = [];\n for await (const chunk of audioStream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n const audioBuffer = Buffer.concat(chunks);\n\n const text = await this.traced(async () => {\n const { filetype, ...otherOptions } = options || {};\n const file = new File([audioBuffer], `audio.${filetype || 'mp3'}`);\n\n const response = await this.listeningClient!.audio.transcriptions.create({\n model: this.listeningModel?.name || 'whisper-1',\n file: file as any,\n ...otherOptions,\n });\n\n return response.text;\n }, 'voice.openai.listen')();\n\n return text;\n }\n}\n"]}
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';\nimport OpenAI from 'openai';\nimport type { ClientOptions } from 'openai';\n\ntype OpenAIVoiceId = 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer' | 'ash' | 'coral' | 'sage';\ntype OpenAIModel = 'tts-1' | 'tts-1-hd' | 'whisper-1';\n\nexport interface OpenAIConfig {\n name?: OpenAIModel;\n apiKey?: string;\n options?: Omit<ClientOptions, 'apiKey'>;\n}\n\nexport interface OpenAIVoiceConfig {\n speech?: {\n model: 'tts-1' | 'tts-1-hd';\n apiKey?: string;\n speaker?: OpenAIVoiceId;\n options?: Omit<ClientOptions, 'apiKey'>;\n };\n listening?: {\n model: 'whisper-1';\n apiKey?: string;\n options?: Omit<ClientOptions, 'apiKey'>;\n };\n}\n\nexport class OpenAIVoice extends MastraVoice {\n speechClient?: OpenAI;\n listeningClient?: OpenAI;\n\n /**\n * Constructs an instance of OpenAIVoice with optional configurations for speech and listening models.\n *\n * @param {Object} [config] - Configuration options for the OpenAIVoice instance.\n * @param {OpenAIConfig} [config.listeningModel] - Configuration for the listening model, including model name and API key.\n * @param {OpenAIConfig} [config.speechModel] - Configuration for the speech model, including model name and API key.\n * @param {string} [config.speaker] - The default speaker's voice to use for speech synthesis.\n * @throws {Error} - Throws an error if no API key is provided for either the speech or listening model.\n */\n constructor({\n listeningModel,\n speechModel,\n speaker,\n }: {\n listeningModel?: OpenAIConfig;\n speechModel?: OpenAIConfig;\n speaker?: string;\n } = {}) {\n const defaultApiKey = process.env.OPENAI_API_KEY;\n const defaultSpeechModel = {\n name: 'tts-1',\n apiKey: defaultApiKey,\n };\n const defaultListeningModel = {\n name: 'whisper-1',\n apiKey: defaultApiKey,\n };\n\n super({\n speechModel: {\n name: speechModel?.name ?? defaultSpeechModel.name,\n apiKey: speechModel?.apiKey ?? defaultSpeechModel.apiKey,\n },\n listeningModel: {\n name: listeningModel?.name ?? defaultListeningModel.name,\n apiKey: listeningModel?.apiKey ?? defaultListeningModel.apiKey,\n },\n speaker: speaker ?? 'alloy',\n });\n\n const speechApiKey = speechModel?.apiKey || defaultApiKey;\n if (!speechApiKey) {\n throw new Error('No API key provided for speech model');\n }\n this.speechClient = new OpenAI({\n apiKey: speechApiKey,\n ...speechModel?.options,\n });\n\n const listeningApiKey = listeningModel?.apiKey || defaultApiKey;\n if (!listeningApiKey) {\n throw new Error('No API key provided for listening model');\n }\n this.listeningClient = new OpenAI({\n apiKey: listeningApiKey,\n ...listeningModel?.options,\n });\n\n if (!this.speechClient && !this.listeningClient) {\n throw new Error('At least one of OPENAI_API_KEY, speechModel.apiKey, or listeningModel.apiKey must be set');\n }\n }\n\n /**\n * Retrieves a list of available speakers for the speech model.\n *\n * @returns {Promise<Array<{ voiceId: OpenAIVoiceId }>>} - A promise that resolves to an array of objects,\n * each containing a `voiceId` representing an available speaker.\n * @throws {Error} - Throws an error if the speech model is not configured.\n */\n async getSpeakers(): Promise<Array<{ voiceId: OpenAIVoiceId }>> {\n if (!this.speechModel) {\n throw new Error('Speech model not configured');\n }\n\n return [\n { voiceId: 'alloy' },\n { voiceId: 'echo' },\n { voiceId: 'fable' },\n { voiceId: 'onyx' },\n { voiceId: 'nova' },\n { voiceId: 'shimmer' },\n { voiceId: 'ash' },\n { voiceId: 'coral' },\n { voiceId: 'sage' },\n ];\n }\n\n /**\n * Converts text or audio input into speech using the configured speech model.\n *\n * @param {string | NodeJS.ReadableStream} input - The text or audio stream to be converted into speech.\n * @param {Object} [options] - Optional parameters for the speech synthesis.\n * @param {string} [options.speaker] - The speaker's voice to use for the speech synthesis.\n * @param {number} [options.speed] - The speed at which the speech should be synthesized.\n * @returns {Promise<NodeJS.ReadableStream>} - A promise that resolves to a readable stream of the synthesized audio.\n * @throws {Error} - Throws an error if the speech model is not configured or if the input text is empty.\n */\n async speak(\n input: string | NodeJS.ReadableStream,\n options?: {\n speaker?: string;\n speed?: number;\n [key: string]: any;\n },\n ): Promise<NodeJS.ReadableStream> {\n if (!this.speechClient) {\n throw new Error('Speech model not configured');\n }\n\n if (typeof input !== 'string') {\n const chunks: Buffer[] = [];\n for await (const chunk of input) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n input = Buffer.concat(chunks).toString('utf-8');\n }\n\n if (input.trim().length === 0) {\n throw new Error('Input text is empty');\n }\n\n const { speaker, responseFormat, speed, ...otherOptions } = options || {};\n\n const response = await this.speechClient!.audio.speech.create({\n model: this.speechModel?.name ?? 'tts-1',\n voice: (speaker ?? this.speaker) as OpenAIVoiceId,\n response_format: responseFormat ?? 'mp3',\n input,\n speed: speed || 1.0,\n ...otherOptions,\n });\n\n const passThrough = new PassThrough();\n const buffer = Buffer.from(await response.arrayBuffer());\n passThrough.end(buffer);\n return passThrough;\n }\n\n /**\n * Checks if listening capabilities are enabled.\n *\n * @returns {Promise<{ enabled: boolean }>}\n */\n async getListener() {\n if (!this.listeningClient) {\n return { enabled: false };\n }\n return { enabled: true };\n }\n\n /**\n * Transcribes audio from a given stream using the configured listening model.\n *\n * @param {NodeJS.ReadableStream} audioStream - The audio stream to be transcribed.\n * @param {Object} [options] - Optional parameters for the transcription.\n * @param {string} [options.filetype] - The file type of the audio stream.\n * Supported types include 'mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm'.\n * @returns {Promise<string>} - A promise that resolves to the transcribed text.\n * @throws {Error} - Throws an error if the listening model is not configured.\n */\n async listen(\n audioStream: NodeJS.ReadableStream,\n options?: {\n filetype?: 'mp3' | 'mp4' | 'mpeg' | 'mpga' | 'm4a' | 'wav' | 'webm';\n [key: string]: any;\n },\n ): Promise<string> {\n if (!this.listeningClient) {\n throw new Error('Listening model not configured');\n }\n\n const chunks: Buffer[] = [];\n for await (const chunk of audioStream) {\n if (typeof chunk === 'string') {\n chunks.push(Buffer.from(chunk));\n } else {\n chunks.push(chunk);\n }\n }\n const audioBuffer = Buffer.concat(chunks);\n\n const { filetype, ...otherOptions } = options || {};\n const file = new File([audioBuffer], `audio.${filetype || 'mp3'}`);\n\n const response = await this.listeningClient!.audio.transcriptions.create({\n model: this.listeningModel?.name || 'whisper-1',\n file: file as any,\n ...otherOptions,\n });\n\n return response.text;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/voice-openai",
3
- "version": "0.11.12",
3
+ "version": "0.12.0-beta.1",
4
4
  "description": "Mastra OpenAI speech integration",
5
5
  "type": "module",
6
6
  "files": [
@@ -28,17 +28,19 @@
28
28
  },
29
29
  "devDependencies": {
30
30
  "@microsoft/api-extractor": "^7.52.8",
31
- "@types/node": "^20.19.0",
31
+ "@types/node": "22.13.17",
32
+ "@vitest/coverage-v8": "4.0.8",
33
+ "@vitest/ui": "4.0.8",
32
34
  "eslint": "^9.37.0",
33
35
  "tsup": "^8.5.0",
34
36
  "typescript": "^5.8.3",
35
- "vitest": "^3.2.4",
36
- "@internal/lint": "0.0.58",
37
- "@mastra/core": "0.24.0",
38
- "@internal/types-builder": "0.0.33"
37
+ "vitest": "^4.0.8",
38
+ "@internal/lint": "0.0.53",
39
+ "@internal/types-builder": "0.0.28",
40
+ "@mastra/core": "1.0.0-beta.3"
39
41
  },
40
42
  "peerDependencies": {
41
- "@mastra/core": ">=0.18.1-0 <0.25.0-0",
43
+ "@mastra/core": ">=1.0.0-0 <2.0.0-0",
42
44
  "zod": "^3.25.0 || ^4.0.0"
43
45
  },
44
46
  "homepage": "https://mastra.ai",
@@ -50,12 +52,8 @@
50
52
  "bugs": {
51
53
  "url": "https://github.com/mastra-ai/mastra/issues"
52
54
  },
53
- "publishConfig": {
54
- "access": "public",
55
- "publish-branch": [
56
- "main",
57
- "0.x"
58
- ]
55
+ "engines": {
56
+ "node": ">=22.13.0"
59
57
  },
60
58
  "scripts": {
61
59
  "build": "tsup --silent --config tsup.config.ts",