@jambonz/speech-utils 0.2.22 → 0.2.24

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,7 +875,7 @@ 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
880
  const {api_key, model_id, options: credOpts} = credentials;
855
881
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
@@ -862,8 +888,10 @@ const synthElevenlabs = async(logger, {
862
888
  params += ',vendor=elevenlabs';
863
889
  params += `,voice=${voice}`;
864
890
  params += `,model_id=${model_id}`;
865
- params += `,optimize_streaming_latency=${opts.optimize_streaming_latency || 2}`;
866
- params += ',write_cache_file=1';
891
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
892
+ if (opts.optimize_streaming_latency !== null && opts.optimize_streaming_latency !== undefined) {
893
+ params += `,optimize_streaming_latency=${opts.optimize_streaming_latency}`;
894
+ }
867
895
  if (opts.voice_settings?.similarity_boost) params += `,similarity_boost=${opts.voice_settings.similarity_boost}`;
868
896
  if (opts.voice_settings?.stability) params += `,stability=${opts.voice_settings.stability}`;
869
897
  if (opts.voice_settings?.style) params += `,style=${opts.voice_settings.style}`;
@@ -913,7 +941,7 @@ const synthElevenlabs = async(logger, {
913
941
  };
914
942
 
915
943
  const synthPlayHT = async(client, logger, {
916
- credentials, options, stats, voice, language, key, text, renderForCaching, disableTtsStreaming
944
+ credentials, options, stats, voice, language, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
917
945
  }) => {
918
946
  const {api_key, user_id, voice_engine, playht_tts_uri, options: credOpts} = credentials;
919
947
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
@@ -955,7 +983,7 @@ const synthPlayHT = async(client, logger, {
955
983
  params += `,voice=${voice}`;
956
984
  params += `,voice_engine=${voice_engine}`;
957
985
  params += `,synthesize_url=${synthesizeUrl}`;
958
- params += ',write_cache_file=1';
986
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
959
987
  params += `,language=${language}`;
960
988
  if (opts.quality) params += `,quality=${opts.quality}`;
961
989
  if (opts.speed) params += `,speed=${opts.speed}`;
@@ -1008,7 +1036,7 @@ const synthPlayHT = async(client, logger, {
1008
1036
  };
1009
1037
 
1010
1038
  const synthInworld = async(logger, {
1011
- credentials, options, stats, voice, key, text, renderForCaching, disableTtsStreaming
1039
+ credentials, options, stats, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
1012
1040
  }) => {
1013
1041
  const {api_key, model_id, options: credOpts} = credentials;
1014
1042
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
@@ -1021,7 +1049,7 @@ const synthInworld = async(logger, {
1021
1049
  params += `,model_id=${model_id}`;
1022
1050
  params += ',vendor=inworld';
1023
1051
  params += `,voice=${voice}`;
1024
- params += ',write_cache_file=1';
1052
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1025
1053
  if (opts.temperature) params += `,temperature=${opts.temperature}`;
1026
1054
  if (opts.audioConfig?.pitch) params += `,pitch=${opts.pitch}`;
1027
1055
  if (opts.audioConfig?.speakingRate) params += `,speakingRate=${opts.speakingRate}`;
@@ -1073,7 +1101,7 @@ const synthInworld = async(logger, {
1073
1101
  };
1074
1102
 
1075
1103
  const synthRimelabs = async(logger, {
1076
- credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming
1104
+ credentials, options, stats, language, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
1077
1105
  }) => {
1078
1106
  const {api_key, model_id, options: credOpts} = credentials;
1079
1107
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
@@ -1087,7 +1115,7 @@ const synthRimelabs = async(logger, {
1087
1115
  params += ',vendor=rimelabs';
1088
1116
  params += `,language=${language}`;
1089
1117
  params += `,voice=${voice}`;
1090
- params += ',write_cache_file=1';
1118
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1091
1119
  if (opts.speedAlpha) params += `,speed_alpha=${opts.speedAlpha}`;
1092
1120
  if (opts.reduceLatency) params += `,reduce_latency=${opts.reduceLatency}`;
1093
1121
  // Arcana model parameters
@@ -1131,7 +1159,7 @@ const synthRimelabs = async(logger, {
1131
1159
  }
1132
1160
  };
1133
1161
  const synthVerbio = async(client, logger, {
1134
- credentials, stats, voice, key, text, renderForCaching, disableTtsStreaming
1162
+ credentials, stats, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
1135
1163
  }) => {
1136
1164
  //https://doc.speechcenter.verbio.com/#tag/Text-To-Speech-REST-API
1137
1165
  if (text.length > 2000) {
@@ -1144,7 +1172,7 @@ const synthVerbio = async(client, logger, {
1144
1172
  params += `,playback_id=${key}`;
1145
1173
  params += ',vendor=verbio';
1146
1174
  params += `,voice=${voice}`;
1147
- params += ',write_cache_file=1';
1175
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1148
1176
  params += '}';
1149
1177
 
1150
1178
  return {
@@ -1179,7 +1207,7 @@ const synthVerbio = async(client, logger, {
1179
1207
  };
1180
1208
 
1181
1209
  const synthWhisper = async(logger, {credentials, stats, voice, key, text, instructions,
1182
- renderForCaching, disableTtsStreaming}) => {
1210
+ renderForCaching, disableTtsStreaming, disableTtsCache}) => {
1183
1211
  const {api_key, model_id, baseURL, timeout, speed} = credentials;
1184
1212
  /* if the env is set to stream then bag out, unless we are specifically rendering to generate a cache file */
1185
1213
  if (!JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
@@ -1189,7 +1217,7 @@ const synthWhisper = async(logger, {credentials, stats, voice, key, text, instru
1189
1217
  params += `,model_id=${model_id}`;
1190
1218
  params += ',vendor=whisper';
1191
1219
  params += `,voice=${voice}`;
1192
- params += ',write_cache_file=1';
1220
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1193
1221
  if (speed) params += `,speed=${speed}`;
1194
1222
  // comma is used to separated parameters in freeswitch tts module
1195
1223
  if (instructions) params += `,instructions=${instructions.replace(/\n/g, ' ').replace(/,/g, ';')}`;
@@ -1227,7 +1255,8 @@ const synthWhisper = async(logger, {credentials, stats, voice, key, text, instru
1227
1255
  }
1228
1256
  };
1229
1257
 
1230
- const synthDeepgram = async(logger, {credentials, stats, model, key, text, renderForCaching, disableTtsStreaming}) => {
1258
+ const synthDeepgram = async(logger, {credentials, stats, model, key, text, renderForCaching,
1259
+ disableTtsStreaming, disableTtsCache}) => {
1231
1260
  const {api_key, deepgram_tts_uri} = credentials;
1232
1261
  if (!JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
1233
1262
  let params = '{';
@@ -1235,7 +1264,7 @@ const synthDeepgram = async(logger, {credentials, stats, model, key, text, rende
1235
1264
  params += `,playback_id=${key}`;
1236
1265
  params += ',vendor=deepgram';
1237
1266
  params += `,voice=${model}`;
1238
- params += ',write_cache_file=1';
1267
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1239
1268
  if (deepgram_tts_uri) params += `,endpoint=${deepgram_tts_uri}`;
1240
1269
  params += '}';
1241
1270
 
@@ -1268,7 +1297,7 @@ const synthDeepgram = async(logger, {credentials, stats, model, key, text, rende
1268
1297
  };
1269
1298
 
1270
1299
  const synthCartesia = async(logger, {
1271
- credentials, options, stats, voice, language, key, text, renderForCaching, disableTtsStreaming
1300
+ credentials, options, stats, voice, language, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
1272
1301
  }) => {
1273
1302
  const {api_key, model_id, embedding, options: credOpts} = credentials;
1274
1303
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
@@ -1280,7 +1309,7 @@ const synthCartesia = async(logger, {
1280
1309
  params += `,model_id=${model_id}`;
1281
1310
  params += ',vendor=cartesia';
1282
1311
  params += `,voice=${voice}`;
1283
- params += ',write_cache_file=1';
1312
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1284
1313
  params += `,language=${language}`;
1285
1314
  params += `,voice_mode=${embedding ? 'embedding' : 'id'}`;
1286
1315
  if (embedding) params += `,embedding=${embedding}`;
@@ -1339,7 +1368,7 @@ const synthCartesia = async(logger, {
1339
1368
  };
1340
1369
 
1341
1370
  const synthResemble = async(logger, {
1342
- credentials, options, stats, voice, key, text, renderForCaching, disableTtsStreaming
1371
+ credentials, options, stats, voice, key, text, renderForCaching, disableTtsStreaming, disableTtsCache
1343
1372
  }) => {
1344
1373
  const {api_key, resemble_tts_uri, resemble_tts_use_tls} = credentials;
1345
1374
  const {project_uuid, use_hd} = options || {};
@@ -1351,7 +1380,7 @@ const synthResemble = async(logger, {
1351
1380
  params += `,playback_id=${key}`;
1352
1381
  params += ',vendor=resemble';
1353
1382
  params += `,voice=${voice}`;
1354
- params += ',write_cache_file=1';
1383
+ params += `,write_cache_file=${disableTtsCache ? 0 : 1}`;
1355
1384
  if (project_uuid) params += `,project_uuid=${project_uuid}`;
1356
1385
  if (use_hd) params += `,use_hd=${use_hd}`;
1357
1386
  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.22",
3
+ "version": "0.2.24",
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`);