n8n-nodes-audexum 0.1.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/credentials/AudexumApi.credentials.ts +19 -0
- package/dist/credentials/AudexumApi.credentials.d.ts +8 -0
- package/dist/credentials/AudexumApi.credentials.d.ts.map +1 -0
- package/dist/credentials/AudexumApi.credentials.js +23 -0
- package/dist/credentials/AudexumApi.credentials.js.map +1 -0
- package/dist/nodes/AudexumTts/AudexumTts.node.d.ts +6 -0
- package/dist/nodes/AudexumTts/AudexumTts.node.d.ts.map +1 -0
- package/dist/nodes/AudexumTts/AudexumTts.node.js +208 -0
- package/dist/nodes/AudexumTts/AudexumTts.node.js.map +1 -0
- package/dist/nodes/AudexumTts/audexum.svg +9 -0
- package/nodes/AudexumTts/AudexumTts.node.ts +221 -0
- package/nodes/AudexumTts/audexum.svg +9 -0
- package/package.json +46 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
|
|
3
|
+
export class AudexumApi implements ICredentialType {
|
|
4
|
+
name = 'audexumApi';
|
|
5
|
+
displayName = 'Audexum API';
|
|
6
|
+
documentationUrl = 'https://audexum.com/docs';
|
|
7
|
+
properties: INodeProperties[] = [
|
|
8
|
+
{
|
|
9
|
+
displayName: 'API Key',
|
|
10
|
+
name: 'apiKey',
|
|
11
|
+
type: 'string',
|
|
12
|
+
typeOptions: { password: true },
|
|
13
|
+
default: '',
|
|
14
|
+
placeholder: 'sk_live_...',
|
|
15
|
+
description:
|
|
16
|
+
'Your Audexum API key. Create one at audexum.com/dashboard under "API Keys".',
|
|
17
|
+
},
|
|
18
|
+
];
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare class AudexumApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
properties: INodeProperties[];
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=AudexumApi.credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudexumApi.credentials.d.ts","sourceRoot":"","sources":["../../credentials/AudexumApi.credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEhE,qBAAa,UAAW,YAAW,eAAe;IAChD,IAAI,SAAgB;IACpB,WAAW,SAAiB;IAC5B,gBAAgB,SAA8B;IAC9C,UAAU,EAAE,eAAe,EAAE,CAW3B;CACH"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AudexumApi = void 0;
|
|
4
|
+
class AudexumApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'audexumApi';
|
|
7
|
+
this.displayName = 'Audexum API';
|
|
8
|
+
this.documentationUrl = 'https://audexum.com/docs';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'API Key',
|
|
12
|
+
name: 'apiKey',
|
|
13
|
+
type: 'string',
|
|
14
|
+
typeOptions: { password: true },
|
|
15
|
+
default: '',
|
|
16
|
+
placeholder: 'sk_live_...',
|
|
17
|
+
description: 'Your Audexum API key. Create one at audexum.com/dashboard under "API Keys".',
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.AudexumApi = AudexumApi;
|
|
23
|
+
//# sourceMappingURL=AudexumApi.credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudexumApi.credentials.js","sourceRoot":"","sources":["../../credentials/AudexumApi.credentials.ts"],"names":[],"mappings":";;;AAEA,MAAa,UAAU;IAAvB;QACE,SAAI,GAAG,YAAY,CAAC;QACpB,gBAAW,GAAG,aAAa,CAAC;QAC5B,qBAAgB,GAAG,0BAA0B,CAAC;QAC9C,eAAU,GAAsB;YAC9B;gBACE,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC/B,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,aAAa;gBAC1B,WAAW,EACT,6EAA6E;aAChF;SACF,CAAC;IACJ,CAAC;CAAA;AAhBD,gCAgBC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
2
|
+
export declare class AudexumTts implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=AudexumTts.node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudexumTts.node.d.ts","sourceRoot":"","sources":["../../../nodes/AudexumTts/AudexumTts.node.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAEpB,MAAM,cAAc,CAAC;AAItB,qBAAa,UAAW,YAAW,SAAS;IAC3C,WAAW,EAAE,oBAAoB,CA+G/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAgGvE"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AudexumTts = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const BASE_URL = 'https://audexum.com/api';
|
|
6
|
+
class AudexumTts {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.description = {
|
|
9
|
+
displayName: 'Audexum TTS',
|
|
10
|
+
name: 'audexumTts',
|
|
11
|
+
icon: 'file:audexum.svg',
|
|
12
|
+
group: ['transform'],
|
|
13
|
+
version: 1,
|
|
14
|
+
subtitle: '={{$parameter["operation"]}}',
|
|
15
|
+
description: 'Convert text to speech using Audexum — 43 voices, 33 languages, from €4/month',
|
|
16
|
+
defaults: {
|
|
17
|
+
name: 'Audexum TTS',
|
|
18
|
+
},
|
|
19
|
+
inputs: ['main'],
|
|
20
|
+
outputs: ['main'],
|
|
21
|
+
credentials: [
|
|
22
|
+
{
|
|
23
|
+
name: 'audexumApi',
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
properties: [
|
|
28
|
+
{
|
|
29
|
+
displayName: 'Operation',
|
|
30
|
+
name: 'operation',
|
|
31
|
+
type: 'options',
|
|
32
|
+
noDataExpression: true,
|
|
33
|
+
options: [
|
|
34
|
+
{
|
|
35
|
+
name: 'Synthesize Text',
|
|
36
|
+
value: 'synthesize',
|
|
37
|
+
description: 'Convert text to speech and return audio as binary',
|
|
38
|
+
action: 'Synthesize text to speech',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'List Voices',
|
|
42
|
+
value: 'listVoices',
|
|
43
|
+
description: 'Get all available voice IDs',
|
|
44
|
+
action: 'List available voices',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Get Usage',
|
|
48
|
+
value: 'getUsage',
|
|
49
|
+
description: 'Get current character usage for the authenticated key',
|
|
50
|
+
action: 'Get usage stats',
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
default: 'synthesize',
|
|
54
|
+
},
|
|
55
|
+
// --- Synthesize options ---
|
|
56
|
+
{
|
|
57
|
+
displayName: 'Text',
|
|
58
|
+
name: 'text',
|
|
59
|
+
type: 'string',
|
|
60
|
+
typeOptions: { rows: 4 },
|
|
61
|
+
displayOptions: {
|
|
62
|
+
show: { operation: ['synthesize'] },
|
|
63
|
+
},
|
|
64
|
+
default: '',
|
|
65
|
+
required: true,
|
|
66
|
+
description: 'The text to convert to speech',
|
|
67
|
+
placeholder: 'Enter text here…',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
displayName: 'Voice',
|
|
71
|
+
name: 'voice',
|
|
72
|
+
type: 'string',
|
|
73
|
+
displayOptions: {
|
|
74
|
+
show: { operation: ['synthesize'] },
|
|
75
|
+
},
|
|
76
|
+
default: 'af_heart',
|
|
77
|
+
required: true,
|
|
78
|
+
description: 'Voice ID to use. Get the full list via the "List Voices" operation or at audexum.com/docs.',
|
|
79
|
+
placeholder: 'af_heart',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
displayName: 'Audio Format',
|
|
83
|
+
name: 'format',
|
|
84
|
+
type: 'options',
|
|
85
|
+
displayOptions: {
|
|
86
|
+
show: { operation: ['synthesize'] },
|
|
87
|
+
},
|
|
88
|
+
options: [
|
|
89
|
+
{ name: 'MP3', value: 'mp3' },
|
|
90
|
+
{ name: 'WAV', value: 'wav' },
|
|
91
|
+
],
|
|
92
|
+
default: 'mp3',
|
|
93
|
+
description: 'Output audio format',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
displayName: 'Speed',
|
|
97
|
+
name: 'speed',
|
|
98
|
+
type: 'number',
|
|
99
|
+
typeOptions: { minValue: 0.5, maxValue: 2.0, numberStepSize: 0.05 },
|
|
100
|
+
displayOptions: {
|
|
101
|
+
show: { operation: ['synthesize'] },
|
|
102
|
+
},
|
|
103
|
+
default: 1.0,
|
|
104
|
+
description: 'Playback speed multiplier (0.5–2.0, default 1.0)',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
displayName: 'Put Output In Field',
|
|
108
|
+
name: 'binaryPropertyName',
|
|
109
|
+
type: 'string',
|
|
110
|
+
displayOptions: {
|
|
111
|
+
show: { operation: ['synthesize'] },
|
|
112
|
+
},
|
|
113
|
+
default: 'data',
|
|
114
|
+
description: 'Name of the binary field the audio file will be stored in',
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
async execute() {
|
|
120
|
+
const items = this.getInputData();
|
|
121
|
+
const returnData = [];
|
|
122
|
+
const credentials = await this.getCredentials('audexumApi');
|
|
123
|
+
const apiKey = credentials.apiKey;
|
|
124
|
+
for (let i = 0; i < items.length; i++) {
|
|
125
|
+
const operation = this.getNodeParameter('operation', i);
|
|
126
|
+
try {
|
|
127
|
+
if (operation === 'synthesize') {
|
|
128
|
+
const text = this.getNodeParameter('text', i);
|
|
129
|
+
const voice = this.getNodeParameter('voice', i);
|
|
130
|
+
const format = this.getNodeParameter('format', i);
|
|
131
|
+
const speed = this.getNodeParameter('speed', i);
|
|
132
|
+
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
|
|
133
|
+
const audioBuffer = await this.helpers.httpRequest({
|
|
134
|
+
method: 'POST',
|
|
135
|
+
url: `${BASE_URL}/synthesize`,
|
|
136
|
+
headers: {
|
|
137
|
+
Authorization: `Bearer ${apiKey}`,
|
|
138
|
+
'Content-Type': 'application/json',
|
|
139
|
+
},
|
|
140
|
+
body: {
|
|
141
|
+
text,
|
|
142
|
+
voice,
|
|
143
|
+
format,
|
|
144
|
+
...(speed !== 1.0 ? { speed } : {}),
|
|
145
|
+
},
|
|
146
|
+
encoding: 'arraybuffer',
|
|
147
|
+
});
|
|
148
|
+
const mimeType = format === 'wav' ? 'audio/wav' : 'audio/mpeg';
|
|
149
|
+
const fileName = `speech.${format}`;
|
|
150
|
+
const binaryData = await this.helpers.prepareBinaryData(Buffer.from(audioBuffer), fileName, mimeType);
|
|
151
|
+
returnData.push({
|
|
152
|
+
json: {
|
|
153
|
+
voice,
|
|
154
|
+
format,
|
|
155
|
+
speed,
|
|
156
|
+
textLength: text.length,
|
|
157
|
+
fileName,
|
|
158
|
+
},
|
|
159
|
+
binary: {
|
|
160
|
+
[binaryPropertyName]: binaryData,
|
|
161
|
+
},
|
|
162
|
+
pairedItem: { item: i },
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
else if (operation === 'listVoices') {
|
|
166
|
+
const voices = await this.helpers.httpRequest({
|
|
167
|
+
method: 'GET',
|
|
168
|
+
url: `${BASE_URL}/voices`,
|
|
169
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
170
|
+
});
|
|
171
|
+
const voiceList = Array.isArray(voices) ? voices : Object.values(voices);
|
|
172
|
+
for (const voiceId of voiceList) {
|
|
173
|
+
returnData.push({
|
|
174
|
+
json: { voice_id: voiceId },
|
|
175
|
+
pairedItem: { item: i },
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else if (operation === 'getUsage') {
|
|
180
|
+
const usage = await this.helpers.httpRequest({
|
|
181
|
+
method: 'GET',
|
|
182
|
+
url: `${BASE_URL}/usage`,
|
|
183
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
184
|
+
});
|
|
185
|
+
returnData.push({
|
|
186
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
187
|
+
json: usage,
|
|
188
|
+
pairedItem: { item: i },
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
if (this.continueOnFail()) {
|
|
194
|
+
returnData.push({
|
|
195
|
+
json: { error: error.message },
|
|
196
|
+
pairedItem: { item: i },
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i });
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return [returnData];
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
exports.AudexumTts = AudexumTts;
|
|
208
|
+
//# sourceMappingURL=AudexumTts.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudexumTts.node.js","sourceRoot":"","sources":["../../../nodes/AudexumTts/AudexumTts.node.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" fill="none">
|
|
2
|
+
<circle cx="30" cy="30" r="30" fill="#0ea5e9"/>
|
|
3
|
+
<rect x="9" y="25" width="4" height="10" rx="2" fill="white"/>
|
|
4
|
+
<rect x="16" y="19" width="4" height="22" rx="2" fill="white"/>
|
|
5
|
+
<rect x="23" y="22" width="4" height="16" rx="2" fill="white"/>
|
|
6
|
+
<rect x="30" y="14" width="4" height="32" rx="2" fill="white"/>
|
|
7
|
+
<rect x="37" y="21" width="4" height="18" rx="2" fill="white"/>
|
|
8
|
+
<rect x="44" y="25" width="4" height="10" rx="2" fill="white"/>
|
|
9
|
+
</svg>
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IExecuteFunctions,
|
|
3
|
+
INodeExecutionData,
|
|
4
|
+
INodeType,
|
|
5
|
+
INodeTypeDescription,
|
|
6
|
+
NodeOperationError,
|
|
7
|
+
} from 'n8n-workflow';
|
|
8
|
+
|
|
9
|
+
const BASE_URL = 'https://audexum.com/api';
|
|
10
|
+
|
|
11
|
+
export class AudexumTts implements INodeType {
|
|
12
|
+
description: INodeTypeDescription = {
|
|
13
|
+
displayName: 'Audexum TTS',
|
|
14
|
+
name: 'audexumTts',
|
|
15
|
+
icon: 'file:audexum.svg',
|
|
16
|
+
group: ['transform'],
|
|
17
|
+
version: 1,
|
|
18
|
+
subtitle: '={{$parameter["operation"]}}',
|
|
19
|
+
description: 'Convert text to speech using Audexum — 43 voices, 33 languages, from €4/month',
|
|
20
|
+
defaults: {
|
|
21
|
+
name: 'Audexum TTS',
|
|
22
|
+
},
|
|
23
|
+
inputs: ['main'],
|
|
24
|
+
outputs: ['main'],
|
|
25
|
+
credentials: [
|
|
26
|
+
{
|
|
27
|
+
name: 'audexumApi',
|
|
28
|
+
required: true,
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
properties: [
|
|
32
|
+
{
|
|
33
|
+
displayName: 'Operation',
|
|
34
|
+
name: 'operation',
|
|
35
|
+
type: 'options',
|
|
36
|
+
noDataExpression: true,
|
|
37
|
+
options: [
|
|
38
|
+
{
|
|
39
|
+
name: 'Synthesize Text',
|
|
40
|
+
value: 'synthesize',
|
|
41
|
+
description: 'Convert text to speech and return audio as binary',
|
|
42
|
+
action: 'Synthesize text to speech',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'List Voices',
|
|
46
|
+
value: 'listVoices',
|
|
47
|
+
description: 'Get all available voice IDs',
|
|
48
|
+
action: 'List available voices',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'Get Usage',
|
|
52
|
+
value: 'getUsage',
|
|
53
|
+
description: 'Get current character usage for the authenticated key',
|
|
54
|
+
action: 'Get usage stats',
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
default: 'synthesize',
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
// --- Synthesize options ---
|
|
61
|
+
{
|
|
62
|
+
displayName: 'Text',
|
|
63
|
+
name: 'text',
|
|
64
|
+
type: 'string',
|
|
65
|
+
typeOptions: { rows: 4 },
|
|
66
|
+
displayOptions: {
|
|
67
|
+
show: { operation: ['synthesize'] },
|
|
68
|
+
},
|
|
69
|
+
default: '',
|
|
70
|
+
required: true,
|
|
71
|
+
description: 'The text to convert to speech',
|
|
72
|
+
placeholder: 'Enter text here…',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
displayName: 'Voice',
|
|
76
|
+
name: 'voice',
|
|
77
|
+
type: 'string',
|
|
78
|
+
displayOptions: {
|
|
79
|
+
show: { operation: ['synthesize'] },
|
|
80
|
+
},
|
|
81
|
+
default: 'af_heart',
|
|
82
|
+
required: true,
|
|
83
|
+
description:
|
|
84
|
+
'Voice ID to use. Get the full list via the "List Voices" operation or at audexum.com/docs.',
|
|
85
|
+
placeholder: 'af_heart',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
displayName: 'Audio Format',
|
|
89
|
+
name: 'format',
|
|
90
|
+
type: 'options',
|
|
91
|
+
displayOptions: {
|
|
92
|
+
show: { operation: ['synthesize'] },
|
|
93
|
+
},
|
|
94
|
+
options: [
|
|
95
|
+
{ name: 'MP3', value: 'mp3' },
|
|
96
|
+
{ name: 'WAV', value: 'wav' },
|
|
97
|
+
],
|
|
98
|
+
default: 'mp3',
|
|
99
|
+
description: 'Output audio format',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
displayName: 'Speed',
|
|
103
|
+
name: 'speed',
|
|
104
|
+
type: 'number',
|
|
105
|
+
typeOptions: { minValue: 0.5, maxValue: 2.0, numberStepSize: 0.05 },
|
|
106
|
+
displayOptions: {
|
|
107
|
+
show: { operation: ['synthesize'] },
|
|
108
|
+
},
|
|
109
|
+
default: 1.0,
|
|
110
|
+
description: 'Playback speed multiplier (0.5–2.0, default 1.0)',
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
displayName: 'Put Output In Field',
|
|
114
|
+
name: 'binaryPropertyName',
|
|
115
|
+
type: 'string',
|
|
116
|
+
displayOptions: {
|
|
117
|
+
show: { operation: ['synthesize'] },
|
|
118
|
+
},
|
|
119
|
+
default: 'data',
|
|
120
|
+
description: 'Name of the binary field the audio file will be stored in',
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
126
|
+
const items = this.getInputData();
|
|
127
|
+
const returnData: INodeExecutionData[] = [];
|
|
128
|
+
const credentials = await this.getCredentials('audexumApi');
|
|
129
|
+
const apiKey = credentials.apiKey as string;
|
|
130
|
+
|
|
131
|
+
for (let i = 0; i < items.length; i++) {
|
|
132
|
+
const operation = this.getNodeParameter('operation', i) as string;
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
if (operation === 'synthesize') {
|
|
136
|
+
const text = this.getNodeParameter('text', i) as string;
|
|
137
|
+
const voice = this.getNodeParameter('voice', i) as string;
|
|
138
|
+
const format = this.getNodeParameter('format', i) as string;
|
|
139
|
+
const speed = this.getNodeParameter('speed', i) as number;
|
|
140
|
+
const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string;
|
|
141
|
+
|
|
142
|
+
const audioBuffer = await this.helpers.httpRequest({
|
|
143
|
+
method: 'POST',
|
|
144
|
+
url: `${BASE_URL}/synthesize`,
|
|
145
|
+
headers: {
|
|
146
|
+
Authorization: `Bearer ${apiKey}`,
|
|
147
|
+
'Content-Type': 'application/json',
|
|
148
|
+
},
|
|
149
|
+
body: {
|
|
150
|
+
text,
|
|
151
|
+
voice,
|
|
152
|
+
format,
|
|
153
|
+
...(speed !== 1.0 ? { speed } : {}),
|
|
154
|
+
},
|
|
155
|
+
encoding: 'arraybuffer',
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const mimeType = format === 'wav' ? 'audio/wav' : 'audio/mpeg';
|
|
159
|
+
const fileName = `speech.${format}`;
|
|
160
|
+
|
|
161
|
+
const binaryData = await this.helpers.prepareBinaryData(
|
|
162
|
+
Buffer.from(audioBuffer as unknown as ArrayBuffer),
|
|
163
|
+
fileName,
|
|
164
|
+
mimeType,
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
returnData.push({
|
|
168
|
+
json: {
|
|
169
|
+
voice,
|
|
170
|
+
format,
|
|
171
|
+
speed,
|
|
172
|
+
textLength: text.length,
|
|
173
|
+
fileName,
|
|
174
|
+
},
|
|
175
|
+
binary: {
|
|
176
|
+
[binaryPropertyName]: binaryData,
|
|
177
|
+
},
|
|
178
|
+
pairedItem: { item: i },
|
|
179
|
+
});
|
|
180
|
+
} else if (operation === 'listVoices') {
|
|
181
|
+
const voices = await this.helpers.httpRequest({
|
|
182
|
+
method: 'GET',
|
|
183
|
+
url: `${BASE_URL}/voices`,
|
|
184
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const voiceList = Array.isArray(voices) ? voices : Object.values(voices);
|
|
188
|
+
for (const voiceId of voiceList) {
|
|
189
|
+
returnData.push({
|
|
190
|
+
json: { voice_id: voiceId },
|
|
191
|
+
pairedItem: { item: i },
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
} else if (operation === 'getUsage') {
|
|
195
|
+
const usage = await this.helpers.httpRequest({
|
|
196
|
+
method: 'GET',
|
|
197
|
+
url: `${BASE_URL}/usage`,
|
|
198
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
returnData.push({
|
|
202
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
203
|
+
json: usage as any,
|
|
204
|
+
pairedItem: { item: i },
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
} catch (error) {
|
|
208
|
+
if (this.continueOnFail()) {
|
|
209
|
+
returnData.push({
|
|
210
|
+
json: { error: (error as Error).message },
|
|
211
|
+
pairedItem: { item: i },
|
|
212
|
+
});
|
|
213
|
+
} else {
|
|
214
|
+
throw new NodeOperationError(this.getNode(), error as Error, { itemIndex: i });
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return [returnData];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 60" fill="none">
|
|
2
|
+
<circle cx="30" cy="30" r="30" fill="#0ea5e9"/>
|
|
3
|
+
<rect x="9" y="25" width="4" height="10" rx="2" fill="white"/>
|
|
4
|
+
<rect x="16" y="19" width="4" height="22" rx="2" fill="white"/>
|
|
5
|
+
<rect x="23" y="22" width="4" height="16" rx="2" fill="white"/>
|
|
6
|
+
<rect x="30" y="14" width="4" height="32" rx="2" fill="white"/>
|
|
7
|
+
<rect x="37" y="21" width="4" height="18" rx="2" fill="white"/>
|
|
8
|
+
<rect x="44" y="25" width="4" height="10" rx="2" fill="white"/>
|
|
9
|
+
</svg>
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "n8n-nodes-audexum",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "n8n community node for Audexum TTS API. Convert text to speech with 43 voices and 33 languages.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"n8n-community-node-package",
|
|
7
|
+
"tts",
|
|
8
|
+
"text-to-speech",
|
|
9
|
+
"audio",
|
|
10
|
+
"voice",
|
|
11
|
+
"ai"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"homepage": "https://audexum.com",
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "Petar",
|
|
17
|
+
"email": "hello@audexum.com"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/audexum/n8n-nodes-audexum.git"
|
|
22
|
+
},
|
|
23
|
+
"main": "index.js",
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc && cp nodes/AudexumTts/audexum.svg dist/nodes/AudexumTts/",
|
|
26
|
+
"dev": "tsc --watch",
|
|
27
|
+
"prepublishOnly": "npm run build"
|
|
28
|
+
},
|
|
29
|
+
"n8n": {
|
|
30
|
+
"n8nNodesApiVersion": 1,
|
|
31
|
+
"credentials": [
|
|
32
|
+
"dist/credentials/AudexumApi.credentials.js"
|
|
33
|
+
],
|
|
34
|
+
"nodes": [
|
|
35
|
+
"dist/nodes/AudexumTts/AudexumTts.node.js"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^18.16.0",
|
|
40
|
+
"n8n-workflow": "^1.28.0",
|
|
41
|
+
"typescript": "^5.1.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"n8n-workflow": "*"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2019",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2019"],
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"rootDir": ".",
|
|
8
|
+
"strict": false,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"moduleResolution": "node",
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["credentials/**/*.ts", "nodes/**/*.ts"],
|
|
17
|
+
"exclude": ["node_modules", "dist"]
|
|
18
|
+
}
|