@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.
@@ -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 (typeof audioBuffer === 'object' && audioBuffer.filePath) {
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, {credentials, stats, voice, text, renderForCaching});
214
- if (typeof audioBuffer === 'object' && audioBuffer.filePath) {
215
- return audioBuffer;
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, {credentials, options, stats, language, voice, text, renderForCaching}) => {
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.beta.deepgram.com', 'POST', 'buffer', {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jambonz/speech-utils",
3
- "version": "0.0.42",
3
+ "version": "0.0.44",
4
4
  "description": "TTS-related speech utilities for jambonz",
5
5
  "main": "index.js",
6
6
  "author": "Dave Horton",
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: 'alpha-asteria-en-v2',
590
+ model: 'aura-asteria-en',
541
591
  text,
542
592
  });
543
593
  t.ok(!opts.servedFromCache, `successfully synthesized deepgram audio to ${opts.filePath}`);