@jambonz/speech-utils 0.0.42 → 0.0.44
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/lib/synth-audio.js +16 -18
- package/package.json +1 -1
- package/test/synth.js +51 -1
package/lib/synth-audio.js
CHANGED
|
@@ -77,7 +77,7 @@ const trimTrailingSilence = (buffer) => {
|
|
|
77
77
|
*/
|
|
78
78
|
async function synthAudio(client, logger, stats, { account_sid,
|
|
79
79
|
vendor, language, voice, gender, text, engine, salt, model, credentials, deploymentId,
|
|
80
|
-
disableTtsCache, renderForCaching, options
|
|
80
|
+
disableTtsCache, renderForCaching, disableTtsStreaming, options
|
|
81
81
|
}) {
|
|
82
82
|
let audioBuffer;
|
|
83
83
|
let servedFromCache = false;
|
|
@@ -200,21 +200,14 @@ async function synthAudio(client, logger, stats, { account_sid,
|
|
|
200
200
|
break;
|
|
201
201
|
case 'elevenlabs':
|
|
202
202
|
audioBuffer = await synthElevenlabs(logger, {
|
|
203
|
-
credentials, options, stats, language, voice, text, renderForCaching, filePath
|
|
203
|
+
credentials, options, stats, language, voice, text, renderForCaching, disableTtsStreaming, filePath
|
|
204
204
|
});
|
|
205
|
-
if (
|
|
206
|
-
return audioBuffer;
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
audioBuffer = await synthElevenlabs(logger, {credentials, options, stats, language, voice, text, filePath});
|
|
210
|
-
}
|
|
205
|
+
if (audioBuffer?.filePath) return audioBuffer;
|
|
211
206
|
break;
|
|
212
207
|
case 'whisper':
|
|
213
|
-
audioBuffer = await synthWhisper(logger, {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
audioBuffer = await synthWhisper(logger, {credentials, stats, voice, text});
|
|
208
|
+
audioBuffer = await synthWhisper(logger, {
|
|
209
|
+
credentials, stats, voice, text, renderForCaching, disableTtsStreaming});
|
|
210
|
+
if (audioBuffer?.filePath) return audioBuffer;
|
|
218
211
|
break;
|
|
219
212
|
case 'deepgram':
|
|
220
213
|
audioBuffer = await synthDeepgram(logger, {credentials, stats, model, text});
|
|
@@ -611,14 +604,18 @@ const synthCustomVendor = async(logger, {credentials, stats, language, voice, te
|
|
|
611
604
|
}
|
|
612
605
|
};
|
|
613
606
|
|
|
614
|
-
const synthElevenlabs = async(logger, {
|
|
607
|
+
const synthElevenlabs = async(logger, {
|
|
608
|
+
credentials, options, stats, voice, text, renderForCaching, disableTtsStreaming
|
|
609
|
+
}) => {
|
|
615
610
|
const {api_key, model_id, options: credOpts} = credentials;
|
|
616
611
|
const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
|
|
617
612
|
|
|
618
613
|
/* default to using the streaming interface, unless disabled by env var OR we want just a cache file */
|
|
619
|
-
if (!process.env.JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching) {
|
|
614
|
+
if (!process.env.JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
|
|
620
615
|
let params = '';
|
|
621
616
|
params += `{api_key=${api_key}`;
|
|
617
|
+
params += ',vendor=elevenlabs';
|
|
618
|
+
params += `,voice=${voice}`;
|
|
622
619
|
params += `,model_id=${model_id}`;
|
|
623
620
|
params += `,optimize_streaming_latency=${opts.optimize_streaming_latency || 2}`;
|
|
624
621
|
params += ',write_cache_file=1';
|
|
@@ -660,13 +657,14 @@ const synthElevenlabs = async(logger, {credentials, options, stats, language, vo
|
|
|
660
657
|
}
|
|
661
658
|
};
|
|
662
659
|
|
|
663
|
-
const synthWhisper = async(logger, {credentials, stats, voice, text, renderForCaching}) => {
|
|
660
|
+
const synthWhisper = async(logger, {credentials, stats, voice, text, renderForCaching, disableTtsStreaming}) => {
|
|
664
661
|
const {api_key, model_id, baseURL, timeout, speed} = credentials;
|
|
665
662
|
/* if the env is set to stream then bag out, unless we are specifically rendering to generate a cache file */
|
|
666
|
-
if (!process.env.JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching) {
|
|
663
|
+
if (!process.env.JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
|
|
667
664
|
let params = '';
|
|
668
665
|
params += `{api_key=${api_key}`;
|
|
669
666
|
params += `,model_id=${model_id}`;
|
|
667
|
+
params += ',vendor=whisper';
|
|
670
668
|
params += `,voice=${voice}`;
|
|
671
669
|
params += ',write_cache_file=1';
|
|
672
670
|
if (speed) params += `,speed=${speed}`;
|
|
@@ -702,7 +700,7 @@ const synthWhisper = async(logger, {credentials, stats, voice, text, renderForCa
|
|
|
702
700
|
const synthDeepgram = async(logger, {credentials, stats, model, text}) => {
|
|
703
701
|
const {api_key} = credentials;
|
|
704
702
|
try {
|
|
705
|
-
const post = bent('https://api.
|
|
703
|
+
const post = bent('https://api.deepgram.com', 'POST', 'buffer', {
|
|
706
704
|
'Authorization': `Token ${api_key}`,
|
|
707
705
|
'Accept': 'audio/mpeg',
|
|
708
706
|
'Content-Type': 'application/json'
|
package/package.json
CHANGED
package/test/synth.js
CHANGED
|
@@ -212,6 +212,56 @@ test('Azure speech synth tests', async(t) => {
|
|
|
212
212
|
client.quit();
|
|
213
213
|
});
|
|
214
214
|
|
|
215
|
+
test('Azure SSML tests', async(t) => {
|
|
216
|
+
const fn = require('..');
|
|
217
|
+
const {synthAudio, client} = fn(opts, logger);
|
|
218
|
+
|
|
219
|
+
if (!process.env.MICROSOFT_API_KEY || !process.env.MICROSOFT_REGION) {
|
|
220
|
+
t.pass('skipping Microsoft speech synth tests since MICROSOFT_API_KEY or MICROSOFT_REGION not provided');
|
|
221
|
+
return t.end();
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
const text = `<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="en-US">
|
|
225
|
+
<voice name="en-US-JennyMultilingualNeural">
|
|
226
|
+
<mstts:express-as style="cheerful" styledegree="2">That'd be just amazing!
|
|
227
|
+
</mstts:express-as>
|
|
228
|
+
</voice>
|
|
229
|
+
</speak>`;
|
|
230
|
+
|
|
231
|
+
let opts = await synthAudio(stats, {
|
|
232
|
+
vendor: 'microsoft',
|
|
233
|
+
credentials: {
|
|
234
|
+
api_key: process.env.MICROSOFT_API_KEY,
|
|
235
|
+
region: process.env.MICROSOFT_REGION,
|
|
236
|
+
},
|
|
237
|
+
language: 'en-US',
|
|
238
|
+
voice: 'en-US-ChristopherNeural',
|
|
239
|
+
text,
|
|
240
|
+
});
|
|
241
|
+
t.ok(!opts.servedFromCache, `successfully synthesized microsoft audio to ${opts.filePath}`);
|
|
242
|
+
if (process.env.JAMBONES_HTTP_PROXY_IP && process.env.JAMBONES_HTTP_PROXY_PORT) {
|
|
243
|
+
t.pass('successfully used proxy to reach microsoft tts service');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
opts = await synthAudio(stats, {
|
|
247
|
+
vendor: 'microsoft',
|
|
248
|
+
credentials: {
|
|
249
|
+
api_key: process.env.MICROSOFT_API_KEY,
|
|
250
|
+
region: process.env.MICROSOFT_REGION,
|
|
251
|
+
},
|
|
252
|
+
language: 'en-US',
|
|
253
|
+
voice: 'en-US-ChristopherNeural',
|
|
254
|
+
text,
|
|
255
|
+
});
|
|
256
|
+
t.ok(opts.servedFromCache, `successfully retrieved microsoft audio from cache ${opts.filePath}`);
|
|
257
|
+
} catch (err) {
|
|
258
|
+
console.error(err);
|
|
259
|
+
t.end(err);
|
|
260
|
+
}
|
|
261
|
+
client.quit();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
|
|
215
265
|
test('Azure custom voice speech synth tests', async(t) => {
|
|
216
266
|
const fn = require('..');
|
|
217
267
|
const {synthAudio, client} = fn(opts, logger);
|
|
@@ -537,7 +587,7 @@ test('Deepgram speech synth tests', async(t) => {
|
|
|
537
587
|
credentials: {
|
|
538
588
|
api_key: process.env.DEEPGRAM_API_KEY
|
|
539
589
|
},
|
|
540
|
-
model: '
|
|
590
|
+
model: 'aura-asteria-en',
|
|
541
591
|
text,
|
|
542
592
|
});
|
|
543
593
|
t.ok(!opts.servedFromCache, `successfully synthesized deepgram audio to ${opts.filePath}`);
|