@jambonz/speech-utils 0.2.23 → 0.2.25

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.
@@ -210,13 +210,14 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
210
210
  case 'polly':
211
211
  vendorLabel = 'aws';
212
212
  audioData = await synthPolly(createHash, retrieveHash, logger,
213
- {credentials, stats, language, voice, key, text, engine, renderForCaching, disableTtsStreaming});
213
+ {credentials, stats, language, voice, key, text, engine, renderForCaching, disableTtsStreaming,
214
+ disableTtsCache});
214
215
  break;
215
216
  case 'azure':
216
217
  case 'microsoft':
217
218
  vendorLabel = 'microsoft';
218
219
  audioData = await synthMicrosoft(logger, {credentials, stats, language, voice, key, text, deploymentId,
219
- renderForCaching, disableTtsStreaming});
220
+ renderForCaching, disableTtsStreaming, disableTtsCache});
220
221
  break;
221
222
  case 'nuance':
222
223
  model = model || 'enhanced';
@@ -224,7 +225,7 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
224
225
  break;
225
226
  case 'nvidia':
226
227
  audioData = await synthNvidia(client, logger, {credentials, stats, language, voice, model, key, text,
227
- renderForCaching, disableTtsStreaming});
228
+ renderForCaching, disableTtsStreaming, disableTtsCache});
228
229
  break;
229
230
  case 'ibm':
230
231
  audioData = await synthIbm(logger, {credentials, stats, voice, key, text});
@@ -234,44 +235,50 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
234
235
  break;
235
236
  case 'elevenlabs':
236
237
  audioData = await synthElevenlabs(logger, {
237
- credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming});
238
+ credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming,
239
+ disableTtsCache});
238
240
  break;
239
241
  case 'playht':
240
242
  audioData = await synthPlayHT(client, logger, {
241
- credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming});
243
+ credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming,
244
+ disableTtsCache});
242
245
  break;
243
246
  case 'cartesia':
244
247
  audioData = await synthCartesia(logger, {
245
- credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming});
248
+ credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming,
249
+ disableTtsCache});
246
250
  break;
247
251
  case 'inworld':
248
252
  audioData = await synthInworld(logger, {
249
- credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming});
253
+ credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming,
254
+ disableTtsCache});
250
255
  break;
251
256
  case 'rimelabs':
252
257
  audioData = await synthRimelabs(logger, {
253
- credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming});
258
+ credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming,
259
+ disableTtsCache});
254
260
  break;
255
261
  case 'whisper':
256
262
  audioData = await synthWhisper(logger, {
257
- credentials, stats, voice, key, text, instructions, renderForCaching, disableTtsStreaming});
263
+ credentials, stats, voice, key, text, instructions, renderForCaching, disableTtsStreaming,
264
+ disableTtsCache});
258
265
  break;
259
266
  case 'verbio':
260
267
  audioData = await synthVerbio(client, logger, {
261
- credentials, stats, voice, key, text, renderForCaching, disableTtsStreaming});
268
+ credentials, stats, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache});
262
269
  if (audioData?.filePath) return audioData;
263
270
  break;
264
271
  case 'deepgram':
265
272
  audioData = await synthDeepgram(logger, {credentials, stats, model, key, text,
266
- renderForCaching, disableTtsStreaming});
273
+ renderForCaching, disableTtsStreaming, disableTtsCache});
267
274
  break;
268
275
  case 'resemble':
269
276
  audioData = await synthResemble(logger, {
270
- credentials, stats, voice, key, text, options, renderForCaching, disableTtsStreaming});
277
+ credentials, stats, voice, key, text, options, renderForCaching, disableTtsStreaming, disableTtsCache});
271
278
  break;
272
279
  case vendor.startsWith('custom') ? vendor : 'cant_match_value':
273
280
  audioData = await synthCustomVendor(logger,
274
- {credentials, stats, language, voice, key, text});
281
+ {credentials, stats, language, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache});
275
282
  break;
276
283
  default:
277
284
  assert(`synthAudio: unsupported speech vendor ${vendor}`);
@@ -306,14 +313,14 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
306
313
  }
307
314
 
308
315
  const synthPolly = async(createHash, retrieveHash, logger,
309
- {credentials, stats, language, voice, engine, key, text, renderForCaching, disableTtsStreaming}) => {
316
+ {credentials, stats, language, voice, engine, key, text, renderForCaching, disableTtsStreaming, disableTtsCache}) => {
310
317
  const {region, accessKeyId, secretAccessKey, roleArn} = credentials;
311
318
  if (!JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
312
319
 
313
320
  let params = '{';
314
321
  params += `language=${language}`;
315
322
  params += `,playback_id=${key}`;
316
- params += ',write_cache_file=1';
323
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
317
324
  params += ',vendor=aws';
318
325
  if (accessKeyId && secretAccessKey) {
319
326
  if (accessKeyId) params += `,accessKeyId=${accessKeyId}`;
@@ -563,7 +570,8 @@ const synthMicrosoft = async(logger, {
563
570
  key,
564
571
  text,
565
572
  renderForCaching,
566
- disableTtsStreaming
573
+ disableTtsStreaming,
574
+ disableTtsCache
567
575
  }) => {
568
576
  try {
569
577
  const {api_key: apiKey, region, use_custom_tts, custom_tts_endpoint, custom_tts_endpoint_url} = credentials;
@@ -596,7 +604,7 @@ const synthMicrosoft = async(logger, {
596
604
  params += `,language=${language}`;
597
605
  params += ',vendor=microsoft';
598
606
  params += `,voice=${voice}`;
599
- params += ',write_cache_file=1';
607
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
600
608
  if (region) params += `,region=${region}`;
601
609
  if (custom_tts_endpoint) params += `,endpointId=${custom_tts_endpoint}`;
602
610
  if (custom_tts_endpoint_url) params += `,endpoint=${custom_tts_endpoint_url}`;
@@ -769,7 +777,7 @@ const synthNuance = async(client, logger, {credentials, stats, voice, model, tex
769
777
  };
770
778
 
771
779
  const synthNvidia = async(client, logger, {
772
- credentials, stats, language, voice, model, key, text, renderForCaching, disableTtsStreaming
780
+ credentials, stats, language, voice, model, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
773
781
  }) => {
774
782
  const {riva_server_uri} = credentials;
775
783
  if (!JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
@@ -778,7 +786,7 @@ const synthNvidia = async(client, logger, {
778
786
  params += `,playback_id=${key}`;
779
787
  params += `,voice=${voice}`;
780
788
  params += `,language=${language}`;
781
- params += ',write_cache_file=1';
789
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
782
790
  params += '}';
783
791
 
784
792
  return {
@@ -818,9 +826,27 @@ const synthNvidia = async(client, logger, {
818
826
  };
819
827
 
820
828
 
821
- const synthCustomVendor = async(logger, {credentials, stats, language, voice, text, filePath}) => {
829
+ const synthCustomVendor = async(logger, {credentials, stats, language, voice,
830
+ text, filePath, renderForCaching, disableTtsStreaming, key, disableTtsCache}) => {
822
831
  const {vendor, auth_token, custom_tts_url} = credentials;
823
832
 
833
+ if (!JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
834
+ let params = '{';
835
+ params += `auth_token=${auth_token}`;
836
+ params += `,playback_id=${key}`;
837
+ params += `,custom_tts_url=${custom_tts_url}`;
838
+ params += ',vendor=custom';
839
+ params += `,voice=${voice}`;
840
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
841
+ params += '}';
842
+
843
+ return {
844
+ filePath: `say:${params}${text.replace(/\n/g, ' ').replace(/\r/g, ' ')}`,
845
+ servedFromCache: false,
846
+ rtt: 0
847
+ };
848
+ }
849
+
824
850
  try {
825
851
  const post = bent('POST', {
826
852
  'Authorization': `Bearer ${auth_token}`,
@@ -849,9 +875,9 @@ const synthCustomVendor = async(logger, {credentials, stats, language, voice, te
849
875
  };
850
876
 
851
877
  const synthElevenlabs = async(logger, {
852
- credentials, options, stats, voice, key, text, renderForCaching, disableTtsStreaming
878
+ credentials, options, stats, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
853
879
  }) => {
854
- const {api_key, model_id, options: credOpts} = credentials;
880
+ const {api_key, model_id, api_uri, options: credOpts} = credentials;
855
881
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
856
882
 
857
883
  /* default to using the streaming interface, unless disabled by env var OR we want just a cache file */
@@ -862,7 +888,8 @@ const synthElevenlabs = async(logger, {
862
888
  params += ',vendor=elevenlabs';
863
889
  params += `,voice=${voice}`;
864
890
  params += `,model_id=${model_id}`;
865
- params += ',write_cache_file=1';
891
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
892
+ if (api_uri) params += `,api_uri=${api_uri}`;
866
893
  if (opts.optimize_streaming_latency !== null && opts.optimize_streaming_latency !== undefined) {
867
894
  params += `,optimize_streaming_latency=${opts.optimize_streaming_latency}`;
868
895
  }
@@ -888,7 +915,7 @@ const synthElevenlabs = async(logger, {
888
915
  const optimize_streaming_latency = opts.optimize_streaming_latency ?
889
916
  `?optimize_streaming_latency=${opts.optimize_streaming_latency}` : '';
890
917
  try {
891
- const post = bent('https://api.elevenlabs.io', 'POST', 'buffer', {
918
+ const post = bent(`https://${api_uri}`, 'POST', 'buffer', {
892
919
  'xi-api-key': api_key,
893
920
  'Accept': 'audio/mpeg',
894
921
  'Content-Type': 'application/json'
@@ -915,7 +942,7 @@ const synthElevenlabs = async(logger, {
915
942
  };
916
943
 
917
944
  const synthPlayHT = async(client, logger, {
918
- credentials, options, stats, voice, language, key, text, renderForCaching, disableTtsStreaming
945
+ credentials, options, stats, voice, language, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
919
946
  }) => {
920
947
  const {api_key, user_id, voice_engine, playht_tts_uri, options: credOpts} = credentials;
921
948
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
@@ -957,7 +984,7 @@ const synthPlayHT = async(client, logger, {
957
984
  params += `,voice=${voice}`;
958
985
  params += `,voice_engine=${voice_engine}`;
959
986
  params += `,synthesize_url=${synthesizeUrl}`;
960
- params += ',write_cache_file=1';
987
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
961
988
  params += `,language=${language}`;
962
989
  if (opts.quality) params += `,quality=${opts.quality}`;
963
990
  if (opts.speed) params += `,speed=${opts.speed}`;
@@ -1010,7 +1037,7 @@ const synthPlayHT = async(client, logger, {
1010
1037
  };
1011
1038
 
1012
1039
  const synthInworld = async(logger, {
1013
- credentials, options, stats, voice, key, text, renderForCaching, disableTtsStreaming
1040
+ credentials, options, stats, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
1014
1041
  }) => {
1015
1042
  const {api_key, model_id, options: credOpts} = credentials;
1016
1043
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
@@ -1023,7 +1050,7 @@ const synthInworld = async(logger, {
1023
1050
  params += `,model_id=${model_id}`;
1024
1051
  params += ',vendor=inworld';
1025
1052
  params += `,voice=${voice}`;
1026
- params += ',write_cache_file=1';
1053
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1027
1054
  if (opts.temperature) params += `,temperature=${opts.temperature}`;
1028
1055
  if (opts.audioConfig?.pitch) params += `,pitch=${opts.pitch}`;
1029
1056
  if (opts.audioConfig?.speakingRate) params += `,speakingRate=${opts.speakingRate}`;
@@ -1075,7 +1102,7 @@ const synthInworld = async(logger, {
1075
1102
  };
1076
1103
 
1077
1104
  const synthRimelabs = async(logger, {
1078
- credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming
1105
+ credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
1079
1106
  }) => {
1080
1107
  const {api_key, model_id, options: credOpts} = credentials;
1081
1108
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
@@ -1089,7 +1116,7 @@ const synthRimelabs = async(logger, {
1089
1116
  params += ',vendor=rimelabs';
1090
1117
  params += `,language=${language}`;
1091
1118
  params += `,voice=${voice}`;
1092
- params += ',write_cache_file=1';
1119
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1093
1120
  if (opts.speedAlpha) params += `,speed_alpha=${opts.speedAlpha}`;
1094
1121
  if (opts.reduceLatency) params += `,reduce_latency=${opts.reduceLatency}`;
1095
1122
  // Arcana model parameters
@@ -1133,7 +1160,7 @@ const synthRimelabs = async(logger, {
1133
1160
  }
1134
1161
  };
1135
1162
  const synthVerbio = async(client, logger, {
1136
- credentials, stats, voice, key, text, renderForCaching, disableTtsStreaming
1163
+ credentials, stats, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
1137
1164
  }) => {
1138
1165
  //https://doc.speechcenter.verbio.com/#tag/Text-To-Speech-REST-API
1139
1166
  if (text.length > 2000) {
@@ -1146,7 +1173,7 @@ const synthVerbio = async(client, logger, {
1146
1173
  params += `,playback_id=${key}`;
1147
1174
  params += ',vendor=verbio';
1148
1175
  params += `,voice=${voice}`;
1149
- params += ',write_cache_file=1';
1176
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1150
1177
  params += '}';
1151
1178
 
1152
1179
  return {
@@ -1181,7 +1208,7 @@ const synthVerbio = async(client, logger, {
1181
1208
  };
1182
1209
 
1183
1210
  const synthWhisper = async(logger, {credentials, stats, voice, key, text, instructions,
1184
- renderForCaching, disableTtsStreaming}) => {
1211
+ renderForCaching, disableTtsStreaming, disableTtsCache}) => {
1185
1212
  const {api_key, model_id, baseURL, timeout, speed} = credentials;
1186
1213
  /* if the env is set to stream then bag out, unless we are specifically rendering to generate a cache file */
1187
1214
  if (!JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
@@ -1191,7 +1218,7 @@ const synthWhisper = async(logger, {credentials, stats, voice, key, text, instru
1191
1218
  params += `,model_id=${model_id}`;
1192
1219
  params += ',vendor=whisper';
1193
1220
  params += `,voice=${voice}`;
1194
- params += ',write_cache_file=1';
1221
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1195
1222
  if (speed) params += `,speed=${speed}`;
1196
1223
  // comma is used to separated parameters in freeswitch tts module
1197
1224
  if (instructions) params += `,instructions=${instructions.replace(/\n/g, ' ').replace(/,/g, ';')}`;
@@ -1229,7 +1256,8 @@ const synthWhisper = async(logger, {credentials, stats, voice, key, text, instru
1229
1256
  }
1230
1257
  };
1231
1258
 
1232
- const synthDeepgram = async(logger, {credentials, stats, model, key, text, renderForCaching, disableTtsStreaming}) => {
1259
+ const synthDeepgram = async(logger, {credentials, stats, model, key, text, renderForCaching,
1260
+ disableTtsStreaming, disableTtsCache}) => {
1233
1261
  const {api_key, deepgram_tts_uri} = credentials;
1234
1262
  if (!JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
1235
1263
  let params = '{';
@@ -1237,7 +1265,7 @@ const synthDeepgram = async(logger, {credentials, stats, model, key, text, rende
1237
1265
  params += `,playback_id=${key}`;
1238
1266
  params += ',vendor=deepgram';
1239
1267
  params += `,voice=${model}`;
1240
- params += ',write_cache_file=1';
1268
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1241
1269
  if (deepgram_tts_uri) params += `,endpoint=${deepgram_tts_uri}`;
1242
1270
  params += '}';
1243
1271
 
@@ -1270,7 +1298,7 @@ const synthDeepgram = async(logger, {credentials, stats, model, key, text, rende
1270
1298
  };
1271
1299
 
1272
1300
  const synthCartesia = async(logger, {
1273
- credentials, options, stats, voice, language, key, text, renderForCaching, disableTtsStreaming
1301
+ credentials, options, stats, voice, language, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
1274
1302
  }) => {
1275
1303
  const {api_key, model_id, embedding, options: credOpts} = credentials;
1276
1304
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
@@ -1282,7 +1310,7 @@ const synthCartesia = async(logger, {
1282
1310
  params += `,model_id=${model_id}`;
1283
1311
  params += ',vendor=cartesia';
1284
1312
  params += `,voice=${voice}`;
1285
- params += ',write_cache_file=1';
1313
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1286
1314
  params += `,language=${language}`;
1287
1315
  params += `,voice_mode=${embedding ? 'embedding' : 'id'}`;
1288
1316
  if (embedding) params += `,embedding=${embedding}`;
@@ -1341,7 +1369,7 @@ const synthCartesia = async(logger, {
1341
1369
  };
1342
1370
 
1343
1371
  const synthResemble = async(logger, {
1344
- credentials, options, stats, voice, key, text, renderForCaching, disableTtsStreaming
1372
+ credentials, options, stats, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
1345
1373
  }) => {
1346
1374
  const {api_key, resemble_tts_uri, resemble_tts_use_tls} = credentials;
1347
1375
  const {project_uuid, use_hd} = options || {};
@@ -1353,7 +1381,7 @@ const synthResemble = async(logger, {
1353
1381
  params += `,playback_id=${key}`;
1354
1382
  params += ',vendor=resemble';
1355
1383
  params += `,voice=${voice}`;
1356
- params += ',write_cache_file=1';
1384
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1357
1385
  if (project_uuid) params += `,project_uuid=${project_uuid}`;
1358
1386
  if (use_hd) params += `,use_hd=${use_hd}`;
1359
1387
  if (resemble_tts_uri) params += `,endpoint=${resemble_tts_uri}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jambonz/speech-utils",
3
- "version": "0.2.23",
3
+ "version": "0.2.25",
4
4
  "description": "TTS-related speech utilities for jambonz",
5
5
  "main": "index.js",
6
6
  "author": "Dave Horton",
package/test/synth.js CHANGED
@@ -554,6 +554,7 @@ test('Custom Vendor speech synth tests', async(t) => {
554
554
  language: 'en-US',
555
555
  voice: 'English-US.Female-1',
556
556
  text: 'This is a test. This is only a test',
557
+ renderForCaching: true
557
558
  });
558
559
  t.ok(!opts.servedFromCache, `successfully synthesized custom vendor audio to ${opts.filePath}`);
559
560
  t.ok(opts.filePath.endsWith('wav'), 'audio is cached as wav file');
@@ -575,6 +576,7 @@ test('Custom Vendor speech synth tests', async(t) => {
575
576
  language: 'en-US',
576
577
  voice: 'English-US.Female-1',
577
578
  text: 'This is a test. This is only a test',
579
+ renderForCaching: true
578
580
  });
579
581
  t.ok(opts.servedFromCache, `successfully get custom vendor cached audio to ${opts.filePath}`);
580
582
  t.ok(opts.filePath.endsWith('wav'), 'audio is cached as wav file');
@@ -589,6 +591,7 @@ test('Custom Vendor speech synth tests', async(t) => {
589
591
  language: 'en-US',
590
592
  voice: 'English-US.Female-1',
591
593
  text: '<speak>This is a test. This is only a test</speak>',
594
+ renderForCaching: true
592
595
  });
593
596
  t.ok(!opts.servedFromCache, `successfully synthesized Custom Vendor audio to ${opts.filePath}`);
594
597
  obj = await getJSON(`http://127.0.0.1:3100/lastRequest/somethingnew2`);