@elizaos/plugin-elevenlabs 1.0.0-beta.5 → 1.0.0-beta.51
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/LICENSE +1 -1
- package/README.md +60 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +27 -52
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025 Shaw Walters
|
|
3
|
+
Copyright (c) 2025 Shaw Walters and elizaOS Contributors
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# ElevenLabs Plugin
|
|
2
|
+
|
|
3
|
+
This plugin provides integration with ElevenLabs text-to-speech services through the ElizaOS platform.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
Add the plugin to your character configuration:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
"plugins": ["@elizaos-plugins/plugin-elevenlabs"]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
The plugin requires these environment variables (can be set in .env file or character settings):
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
"settings": {
|
|
19
|
+
"ELEVENLABS_API_KEY": "your_elevenlabs_api_key",
|
|
20
|
+
"ELEVENLABS_VOICE_ID": "EXAVITQu4vr4xnSDxMaL",
|
|
21
|
+
"ELEVENLABS_MODEL_ID": "eleven_monolingual_v1",
|
|
22
|
+
"ELEVENLABS_VOICE_STABILITY": "0.5",
|
|
23
|
+
"ELEVENLABS_OPTIMIZE_STREAMING_LATENCY": "0",
|
|
24
|
+
"ELEVENLABS_OUTPUT_FORMAT": "pcm_16000",
|
|
25
|
+
"ELEVENLABS_VOICE_SIMILARITY_BOOST": "0.75",
|
|
26
|
+
"ELEVENLABS_VOICE_STYLE": "0",
|
|
27
|
+
"ELEVENLABS_VOICE_USE_SPEAKER_BOOST": "true"
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or in `.env` file:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
ELEVENLABS_API_KEY=your_elevenlabs_api_key
|
|
35
|
+
# Optional overrides:
|
|
36
|
+
ELEVENLABS_VOICE_ID=EXAVITQu4vr4xnSDxMaL
|
|
37
|
+
ELEVENLABS_MODEL_ID=eleven_monolingual_v1
|
|
38
|
+
ELEVENLABS_VOICE_STABILITY=0.5
|
|
39
|
+
ELEVENLABS_OPTIMIZE_STREAMING_LATENCY=0
|
|
40
|
+
ELEVENLABS_OUTPUT_FORMAT=pcm_16000
|
|
41
|
+
ELEVENLABS_VOICE_SIMILARITY_BOOST=0.75
|
|
42
|
+
ELEVENLABS_VOICE_STYLE=0
|
|
43
|
+
ELEVENLABS_VOICE_USE_SPEAKER_BOOST=true
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Configuration Options
|
|
47
|
+
|
|
48
|
+
- `ELEVENLABS_API_KEY` (required): Your ElevenLabs API credentials.
|
|
49
|
+
- `ELEVENLABS_VOICE_ID`: Optional. Voice selection ID. Defaults to `EXAVITQu4vr4xnSDxMaL`.
|
|
50
|
+
- `ELEVENLABS_MODEL_ID`: Optional. Speech model ID. Defaults to `eleven_monolingual_v1`.
|
|
51
|
+
- `ELEVENLABS_VOICE_STABILITY`: Optional. Controls voice stability. Defaults to `0.5`.
|
|
52
|
+
- `ELEVENLABS_OPTIMIZE_STREAMING_LATENCY`: Optional. Adjusts streaming latency. Defaults to `0`.
|
|
53
|
+
- `ELEVENLABS_OUTPUT_FORMAT`: Optional. Output format (e.g., pcm_16000). Defaults to `pcm_16000`.
|
|
54
|
+
- `ELEVENLABS_VOICE_SIMILARITY_BOOST`: Optional. Adjusts similarity to the reference voice (0-1). Defaults to `0.75`.
|
|
55
|
+
- `ELEVENLABS_VOICE_STYLE`: Optional. Controls voice style intensity (0-1). Defaults to `0`.
|
|
56
|
+
- `ELEVENLABS_VOICE_USE_SPEAKER_BOOST`: Optional. Enhances speaker presence (true/false). Defaults to `true`.
|
|
57
|
+
|
|
58
|
+
The plugin provides the following model type:
|
|
59
|
+
|
|
60
|
+
- `TEXT_TO_SPEECH`: Converts text into spoken audio.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Plugin } from '@elizaos/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents the ElevenLabs plugin.
|
|
5
|
+
* This plugin provides functionality related to ElevenLabs API, including text to speech conversion.
|
|
6
|
+
* @type {Plugin}
|
|
7
|
+
*/
|
|
8
|
+
declare const elevenLabsPlugin: Plugin;
|
|
9
|
+
|
|
10
|
+
export { elevenLabsPlugin as default, elevenLabsPlugin };
|
package/dist/index.js
CHANGED
|
@@ -1,44 +1,11 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
+
import {
|
|
3
|
+
ModelType,
|
|
4
|
+
logger,
|
|
5
|
+
prependWavHeader,
|
|
6
|
+
parseBooleanFromText
|
|
7
|
+
} from "@elizaos/core";
|
|
2
8
|
import { Readable } from "node:stream";
|
|
3
|
-
import { ModelType, logger } from "@elizaos/core";
|
|
4
|
-
|
|
5
|
-
// src/utils.ts
|
|
6
|
-
import { PassThrough } from "node:stream";
|
|
7
|
-
function getWavHeader(audioLength, sampleRate, channelCount = 1, bitsPerSample = 16) {
|
|
8
|
-
const wavHeader = Buffer.alloc(44);
|
|
9
|
-
wavHeader.write("RIFF", 0);
|
|
10
|
-
wavHeader.writeUInt32LE(36 + audioLength, 4);
|
|
11
|
-
wavHeader.write("WAVE", 8);
|
|
12
|
-
wavHeader.write("fmt ", 12);
|
|
13
|
-
wavHeader.writeUInt32LE(16, 16);
|
|
14
|
-
wavHeader.writeUInt16LE(1, 20);
|
|
15
|
-
wavHeader.writeUInt16LE(channelCount, 22);
|
|
16
|
-
wavHeader.writeUInt32LE(sampleRate, 24);
|
|
17
|
-
wavHeader.writeUInt32LE(sampleRate * bitsPerSample * channelCount / 8, 28);
|
|
18
|
-
wavHeader.writeUInt16LE(bitsPerSample * channelCount / 8, 32);
|
|
19
|
-
wavHeader.writeUInt16LE(bitsPerSample, 34);
|
|
20
|
-
wavHeader.write("data", 36);
|
|
21
|
-
wavHeader.writeUInt32LE(audioLength, 40);
|
|
22
|
-
return wavHeader;
|
|
23
|
-
}
|
|
24
|
-
function prependWavHeader(readable, audioLength, sampleRate, channelCount = 1, bitsPerSample = 16) {
|
|
25
|
-
const wavHeader = getWavHeader(audioLength, sampleRate, channelCount, bitsPerSample);
|
|
26
|
-
let pushedHeader = false;
|
|
27
|
-
const passThrough = new PassThrough();
|
|
28
|
-
readable.on("data", (data) => {
|
|
29
|
-
if (!pushedHeader) {
|
|
30
|
-
passThrough.push(wavHeader);
|
|
31
|
-
pushedHeader = true;
|
|
32
|
-
}
|
|
33
|
-
passThrough.push(data);
|
|
34
|
-
});
|
|
35
|
-
readable.on("end", () => {
|
|
36
|
-
passThrough.end();
|
|
37
|
-
});
|
|
38
|
-
return passThrough;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// src/index.ts
|
|
42
9
|
function getVoiceSettings(runtime) {
|
|
43
10
|
const getSetting = (key, fallback = "") => process.env[key] || runtime.getSetting(key) || fallback;
|
|
44
11
|
return {
|
|
@@ -50,7 +17,9 @@ function getVoiceSettings(runtime) {
|
|
|
50
17
|
outputFormat: getSetting("ELEVENLABS_OUTPUT_FORMAT", "pcm_16000"),
|
|
51
18
|
similarity: getSetting("ELEVENLABS_VOICE_SIMILARITY_BOOST", "0.75"),
|
|
52
19
|
style: getSetting("ELEVENLABS_VOICE_STYLE", "0"),
|
|
53
|
-
speakerBoost:
|
|
20
|
+
speakerBoost: parseBooleanFromText(
|
|
21
|
+
getSetting("ELEVENLABS_VOICE_USE_SPEAKER_BOOST", "true")
|
|
22
|
+
)
|
|
54
23
|
};
|
|
55
24
|
}
|
|
56
25
|
async function fetchSpeech(runtime, text) {
|
|
@@ -81,15 +50,19 @@ async function fetchSpeech(runtime, text) {
|
|
|
81
50
|
const errorBody = JSON.parse(errorBodyString);
|
|
82
51
|
if (response.status === 401 && errorBody.detail?.status === "quota_exceeded") {
|
|
83
52
|
logger.log("ElevenLabs quota exceeded");
|
|
84
|
-
throw
|
|
53
|
+
throw logger.error("QUOTA_EXCEEDED");
|
|
85
54
|
}
|
|
86
|
-
throw
|
|
55
|
+
throw logger.error(
|
|
87
56
|
`Received status ${response.status} from Eleven Labs API: ${JSON.stringify(errorBody)}`
|
|
88
57
|
);
|
|
89
58
|
}
|
|
59
|
+
if (!response.body) {
|
|
60
|
+
throw logger.error("Empty response body from Eleven Labs API");
|
|
61
|
+
}
|
|
90
62
|
return Readable.fromWeb(response.body);
|
|
91
63
|
} catch (error) {
|
|
92
|
-
|
|
64
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
65
|
+
throw logger.error(msg);
|
|
93
66
|
}
|
|
94
67
|
}
|
|
95
68
|
var elevenLabsPlugin = {
|
|
@@ -97,19 +70,20 @@ var elevenLabsPlugin = {
|
|
|
97
70
|
description: "ElevenLabs plugin",
|
|
98
71
|
models: {
|
|
99
72
|
[ModelType.TEXT_TO_SPEECH]: async (runtime, text) => {
|
|
73
|
+
const settings = getVoiceSettings(runtime);
|
|
74
|
+
logger.log(`[ElevenLabs] Using TEXT_TO_SPEECH model: ${settings.model}`);
|
|
100
75
|
try {
|
|
101
76
|
const stream = await fetchSpeech(runtime, text);
|
|
102
|
-
return
|
|
77
|
+
return settings.outputFormat.startsWith("pcm_") ? prependWavHeader(
|
|
103
78
|
stream,
|
|
104
79
|
1024 * 1024 * 100,
|
|
105
|
-
Number.parseInt(
|
|
80
|
+
Number.parseInt(settings.outputFormat.slice(4)),
|
|
106
81
|
1,
|
|
107
82
|
16
|
|
108
83
|
) : stream;
|
|
109
84
|
} catch (error) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
);
|
|
85
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
86
|
+
throw logger.error(msg);
|
|
113
87
|
}
|
|
114
88
|
}
|
|
115
89
|
},
|
|
@@ -121,7 +95,9 @@ var elevenLabsPlugin = {
|
|
|
121
95
|
name: "Eleven Labs API key validation",
|
|
122
96
|
fn: async (runtime) => {
|
|
123
97
|
if (!getVoiceSettings(runtime).apiKey) {
|
|
124
|
-
throw new Error(
|
|
98
|
+
throw new Error(
|
|
99
|
+
"Missing API key: Please provide a valid Eleven Labs API key."
|
|
100
|
+
);
|
|
125
101
|
}
|
|
126
102
|
}
|
|
127
103
|
},
|
|
@@ -131,9 +107,8 @@ var elevenLabsPlugin = {
|
|
|
131
107
|
try {
|
|
132
108
|
await fetchSpeech(runtime, "test");
|
|
133
109
|
} catch (error) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
);
|
|
110
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
111
|
+
throw logger.error(msg);
|
|
137
112
|
}
|
|
138
113
|
}
|
|
139
114
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils.ts"],"sourcesContent":["import { Readable } from 'node:stream';\nimport { type IAgentRuntime, ModelType, type Plugin, logger } from '@elizaos/core';\nimport { prependWavHeader } from './utils';\n\n/**\n * Function to retrieve voice settings based on runtime and environment variables.\n * @param {IAgentRuntime} runtime - The agent runtime object.\n * @returns {Object} - Object containing various voice settings.\n */\nfunction getVoiceSettings(runtime: IAgentRuntime) {\n const getSetting = (key: string, fallback = '') =>\n process.env[key] || runtime.getSetting(key) || fallback;\n\n return {\n apiKey: getSetting('ELEVENLABS_API_KEY') || getSetting('ELEVENLABS_XI_API_KEY'),\n voiceId: getSetting('ELEVENLABS_VOICE_ID', 'EXAVITQu4vr4xnSDxMaL'),\n model: getSetting('ELEVENLABS_MODEL_ID', 'eleven_monolingual_v1'),\n stability: getSetting('ELEVENLABS_VOICE_STABILITY', '0.5'),\n latency: getSetting('ELEVENLABS_OPTIMIZE_STREAMING_LATENCY', '0'),\n outputFormat: getSetting('ELEVENLABS_OUTPUT_FORMAT', 'pcm_16000'),\n similarity: getSetting('ELEVENLABS_VOICE_SIMILARITY_BOOST', '0.75'),\n style: getSetting('ELEVENLABS_VOICE_STYLE', '0'),\n speakerBoost: getSetting('ELEVENLABS_VOICE_USE_SPEAKER_BOOST', 'true'),\n };\n}\n\n/**\n * Fetch speech from Eleven Labs API using given text and runtime settings.\n * @param {IAgentRuntime} runtime - The runtime interface containing necessary data for the API call.\n * @param {string} text - The text to be converted into speech.\n * @returns {Promise<Readable>} A promise resolving to a readable stream of the fetched speech.\n */\nasync function fetchSpeech(runtime: IAgentRuntime, text: string) {\n const settings = getVoiceSettings(runtime);\n try {\n const response = await fetch(\n `https://api.elevenlabs.io/v1/text-to-speech/${settings.voiceId}/stream?optimize_streaming_latency=${settings.latency}&output_format=${settings.outputFormat}`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'xi-api-key': settings.apiKey,\n },\n body: JSON.stringify({\n model_id: settings.model,\n text,\n voice_settings: {\n similarity_boost: settings.similarity,\n stability: settings.stability,\n style: settings.style,\n use_speaker_boost: settings.speakerBoost,\n },\n }),\n }\n );\n if (response.status !== 200) {\n const errorBodyString = await response.text();\n const errorBody = JSON.parse(errorBodyString);\n\n if (response.status === 401 && errorBody.detail?.status === 'quota_exceeded') {\n logger.log('ElevenLabs quota exceeded');\n throw new Error('QUOTA_EXCEEDED');\n }\n throw new Error(\n `Received status ${response.status} from Eleven Labs API: ${JSON.stringify(errorBody)}`\n );\n }\n return Readable.fromWeb(response.body);\n } catch (error) {\n throw new Error(error);\n }\n}\n\n/**\n * Represents the ElevenLabs plugin.\n * This plugin provides functionality related to ElevenLabs API, including text to speech conversion.\n * @type {Plugin}\n */\nexport const elevenLabsPlugin: Plugin = {\n name: 'elevenLabs',\n description: 'ElevenLabs plugin',\n models: {\n [ModelType.TEXT_TO_SPEECH]: async (runtime, text) => {\n try {\n const stream = await fetchSpeech(runtime, text);\n return getVoiceSettings(runtime).outputFormat.startsWith('pcm_')\n ? prependWavHeader(\n stream,\n 1024 * 1024 * 100,\n Number.parseInt(getVoiceSettings(runtime).outputFormat.slice(4)),\n 1,\n 16\n )\n : stream;\n } catch (error) {\n throw new Error(\n `Failed to fetch speech from Eleven Labs API: ${error.message || 'Unknown error occurred'}`\n );\n }\n },\n },\n tests: [\n {\n name: 'test eleven labs',\n tests: [\n {\n name: 'Eleven Labs API key validation',\n fn: async (runtime: IAgentRuntime) => {\n if (!getVoiceSettings(runtime).apiKey) {\n throw new Error('Missing API key: Please provide a valid Eleven Labs API key.');\n }\n },\n },\n {\n name: 'Eleven Labs API response',\n fn: async (runtime: IAgentRuntime) => {\n try {\n await fetchSpeech(runtime, 'test');\n } catch (error) {\n throw new Error(\n `Failed to fetch speech from Eleven Labs API: ${error.message || 'Unknown error occurred'}`\n );\n }\n },\n },\n ],\n },\n ],\n};\nexport default elevenLabsPlugin;\n","import { PassThrough } from 'node:stream';\nimport type { Readable } from 'node:stream';\n\n/**\n * Generates a WAV file header based on the provided audio parameters.\n * @param {number} audioLength - The length of the audio data in bytes.\n * @param {number} sampleRate - The sample rate of the audio.\n * @param {number} [channelCount=1] - The number of channels (default is 1).\n * @param {number} [bitsPerSample=16] - The number of bits per sample (default is 16).\n * @returns {Buffer} The WAV file header as a Buffer object.\n */\nexport function getWavHeader(\n audioLength: number,\n sampleRate: number,\n channelCount = 1,\n bitsPerSample = 16\n): Buffer {\n const wavHeader = Buffer.alloc(44);\n wavHeader.write('RIFF', 0);\n wavHeader.writeUInt32LE(36 + audioLength, 4); // Length of entire file in bytes minus 8\n wavHeader.write('WAVE', 8);\n wavHeader.write('fmt ', 12);\n wavHeader.writeUInt32LE(16, 16); // Length of format data\n wavHeader.writeUInt16LE(1, 20); // Type of format (1 is PCM)\n wavHeader.writeUInt16LE(channelCount, 22); // Number of channels\n wavHeader.writeUInt32LE(sampleRate, 24); // Sample rate\n wavHeader.writeUInt32LE((sampleRate * bitsPerSample * channelCount) / 8, 28); // Byte rate\n wavHeader.writeUInt16LE((bitsPerSample * channelCount) / 8, 32); // Block align ((BitsPerSample * Channels) / 8)\n wavHeader.writeUInt16LE(bitsPerSample, 34); // Bits per sample\n wavHeader.write('data', 36); // Data chunk header\n wavHeader.writeUInt32LE(audioLength, 40); // Data chunk size\n return wavHeader;\n}\n\n/**\n * Prepends a WAV header to a readable stream of audio data.\n *\n * @param {Readable} readable - The readable stream containing the audio data.\n * @param {number} audioLength - The length of the audio data in seconds.\n * @param {number} sampleRate - The sample rate of the audio data.\n * @param {number} [channelCount=1] - The number of channels in the audio data (default is 1).\n * @param {number} [bitsPerSample=16] - The number of bits per sample in the audio data (default is 16).\n * @returns {Readable} A new readable stream with the WAV header prepended to the audio data.\n */\nexport function prependWavHeader(\n readable: Readable,\n audioLength: number,\n sampleRate: number,\n channelCount = 1,\n bitsPerSample = 16\n): Readable {\n const wavHeader = getWavHeader(audioLength, sampleRate, channelCount, bitsPerSample);\n let pushedHeader = false;\n const passThrough = new PassThrough();\n readable.on('data', (data) => {\n if (!pushedHeader) {\n passThrough.push(wavHeader);\n pushedHeader = true;\n }\n passThrough.push(data);\n });\n readable.on('end', () => {\n passThrough.end();\n });\n return passThrough;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {\n type IAgentRuntime,\n ModelType,\n type Plugin,\n logger,\n prependWavHeader,\n parseBooleanFromText,\n} from \"@elizaos/core\";\nimport { Readable } from \"node:stream\";\n\n/**\n * Function to retrieve voice settings based on runtime and environment variables.\n * @param {IAgentRuntime} runtime - The agent runtime object.\n * @returns {Object} - Object containing various voice settings.\n */\nfunction getVoiceSettings(runtime: IAgentRuntime) {\n const getSetting = (key: string, fallback = \"\") =>\n process.env[key] || runtime.getSetting(key) || fallback;\n\n return {\n apiKey:\n getSetting(\"ELEVENLABS_API_KEY\") || getSetting(\"ELEVENLABS_XI_API_KEY\"),\n voiceId: getSetting(\"ELEVENLABS_VOICE_ID\", \"EXAVITQu4vr4xnSDxMaL\"),\n model: getSetting(\"ELEVENLABS_MODEL_ID\", \"eleven_monolingual_v1\"),\n stability: getSetting(\"ELEVENLABS_VOICE_STABILITY\", \"0.5\"),\n latency: getSetting(\"ELEVENLABS_OPTIMIZE_STREAMING_LATENCY\", \"0\"),\n outputFormat: getSetting(\"ELEVENLABS_OUTPUT_FORMAT\", \"pcm_16000\"),\n similarity: getSetting(\"ELEVENLABS_VOICE_SIMILARITY_BOOST\", \"0.75\"),\n style: getSetting(\"ELEVENLABS_VOICE_STYLE\", \"0\"),\n speakerBoost: parseBooleanFromText(\n getSetting(\"ELEVENLABS_VOICE_USE_SPEAKER_BOOST\", \"true\")\n ),\n };\n}\n\n/**\n * Fetch speech from Eleven Labs API using given text and runtime settings.\n * @param {IAgentRuntime} runtime - The runtime interface containing necessary data for the API call.\n * @param {string} text - The text to be converted into speech.\n * @returns {Promise<Readable>} A promise resolving to a readable stream of the fetched speech.\n */\nasync function fetchSpeech(runtime: IAgentRuntime, text: string) {\n const settings = getVoiceSettings(runtime);\n try {\n const response = await fetch(\n `https://api.elevenlabs.io/v1/text-to-speech/${settings.voiceId}/stream?optimize_streaming_latency=${settings.latency}&output_format=${settings.outputFormat}`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"xi-api-key\": settings.apiKey,\n },\n body: JSON.stringify({\n model_id: settings.model,\n text,\n voice_settings: {\n similarity_boost: settings.similarity,\n stability: settings.stability,\n style: settings.style,\n use_speaker_boost: settings.speakerBoost,\n },\n }),\n }\n );\n if (response.status !== 200) {\n const errorBodyString = await response.text();\n const errorBody = JSON.parse(errorBodyString);\n\n if (\n response.status === 401 &&\n errorBody.detail?.status === \"quota_exceeded\"\n ) {\n logger.log(\"ElevenLabs quota exceeded\");\n throw logger.error(\"QUOTA_EXCEEDED\");\n }\n throw logger.error(\n `Received status ${response.status} from Eleven Labs API: ${JSON.stringify(errorBody)}`\n );\n }\n\n if (!response.body) {\n throw logger.error(\"Empty response body from Eleven Labs API\");\n }\n\n return Readable.fromWeb(response.body);\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n throw logger.error(msg);\n }\n}\n\n/**\n * Represents the ElevenLabs plugin.\n * This plugin provides functionality related to ElevenLabs API, including text to speech conversion.\n * @type {Plugin}\n */\nexport const elevenLabsPlugin: Plugin = {\n name: \"elevenLabs\",\n description: \"ElevenLabs plugin\",\n models: {\n [ModelType.TEXT_TO_SPEECH]: async (runtime, text) => {\n const settings = getVoiceSettings(runtime);\n logger.log(`[ElevenLabs] Using TEXT_TO_SPEECH model: ${settings.model}`);\n try {\n const stream = await fetchSpeech(runtime, text);\n return settings.outputFormat.startsWith(\"pcm_\")\n ? prependWavHeader(\n stream,\n 1024 * 1024 * 100,\n Number.parseInt(settings.outputFormat.slice(4)),\n 1,\n 16\n )\n : stream;\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n throw logger.error(msg);\n }\n },\n },\n tests: [\n {\n name: \"test eleven labs\",\n tests: [\n {\n name: \"Eleven Labs API key validation\",\n fn: async (runtime: IAgentRuntime) => {\n if (!getVoiceSettings(runtime).apiKey) {\n throw new Error(\n \"Missing API key: Please provide a valid Eleven Labs API key.\"\n );\n }\n },\n },\n {\n name: \"Eleven Labs API response\",\n fn: async (runtime: IAgentRuntime) => {\n try {\n await fetchSpeech(runtime, \"test\");\n } catch (error: unknown) {\n const msg =\n error instanceof Error ? error.message : String(error);\n throw logger.error(msg);\n }\n },\n },\n ],\n },\n ],\n};\nexport default elevenLabsPlugin;\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elizaos/plugin-elevenlabs",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.51",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dist"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@elizaos/core": "^1.0.0-beta.
|
|
25
|
+
"@elizaos/core": "^1.0.0-beta.51",
|
|
26
26
|
"tsup": "8.4.0"
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
@@ -77,8 +77,10 @@
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "646c632924826e2b75c2304a75ee56959fe4a460",
|
|
81
81
|
"devDependencies": {
|
|
82
|
-
"
|
|
82
|
+
"@types/node": "^22.15.18",
|
|
83
|
+
"prettier": "3.5.3",
|
|
84
|
+
"typescript": "^5.8.2"
|
|
83
85
|
}
|
|
84
86
|
}
|