@jambonz/speech-utils 0.2.8 → 0.2.9

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.
@@ -25,7 +25,7 @@ function getExtensionAndSampleRate(path) {
25
25
  }
26
26
 
27
27
  async function addFileToCache(client, logger, path,
28
- {account_sid, vendor, language, voice, deploymentId, engine, model, text}) {
28
+ {account_sid, vendor, language, voice, deploymentId, engine, model, text, instructions}) {
29
29
  let key;
30
30
  logger = logger || noopLogger;
31
31
 
@@ -38,6 +38,7 @@ async function addFileToCache(client, logger, path,
38
38
  engine,
39
39
  model,
40
40
  text,
41
+ instructions
41
42
  });
42
43
  const [extension, sampleRate] = getExtensionAndSampleRate(path);
43
44
  const audioBuffer = await fs.readFile(path);
@@ -12,7 +12,7 @@ const debug = require('debug')('jambonz:realtimedb-helpers');
12
12
  * @returns {object} result - {error, purgedCount}
13
13
  */
14
14
  async function purgeTtsCache(client, logger, {all, account_sid, vendor,
15
- language, voice, deploymentId, engine, model, text} = {all: true}) {
15
+ language, voice, deploymentId, engine, model, text, instructions} = {all: true}) {
16
16
  logger = logger || noopLogger;
17
17
 
18
18
  let purgedCount = 0, error;
@@ -35,6 +35,7 @@ async function purgeTtsCache(client, logger, {all, account_sid, vendor,
35
35
  engine,
36
36
  model,
37
37
  text,
38
+ instructions
38
39
  });
39
40
  purgedCount = await client.del(key);
40
41
  if (purgedCount === 0) error = 'Specified item not found';
@@ -89,7 +89,7 @@ const trimTrailingSilence = (buffer) => {
89
89
  */
90
90
  async function synthAudio(client, createHash, retrieveHash, logger, stats, { account_sid,
91
91
  vendor, language, voice, gender, text, engine, salt, model, credentials, deploymentId,
92
- disableTtsCache, renderForCaching = false, disableTtsStreaming, options
92
+ disableTtsCache, renderForCaching = false, disableTtsStreaming, options, instructions
93
93
  }) {
94
94
  let audioData;
95
95
  let servedFromCache = false;
@@ -171,7 +171,8 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
171
171
  engine,
172
172
  // model or model_id is used to identify the tts cache.
173
173
  model: model || credentials.model_id,
174
- text
174
+ text,
175
+ instructions
175
176
  });
176
177
 
177
178
  debug(`synth key is ${key}`);
@@ -242,7 +243,7 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
242
243
  break;
243
244
  case 'whisper':
244
245
  audioData = await synthWhisper(logger, {
245
- credentials, stats, voice, text, renderForCaching, disableTtsStreaming});
246
+ credentials, stats, voice, text, instructions, renderForCaching, disableTtsStreaming});
246
247
  break;
247
248
  case 'verbio':
248
249
  audioData = await synthVerbio(client, logger, {
@@ -1048,7 +1049,8 @@ const synthVerbio = async(client, logger, {credentials, stats, voice, text, rend
1048
1049
  }
1049
1050
  };
1050
1051
 
1051
- const synthWhisper = async(logger, {credentials, stats, voice, text, renderForCaching, disableTtsStreaming}) => {
1052
+ const synthWhisper = async(logger, {credentials, stats, voice, text, instructions,
1053
+ renderForCaching, disableTtsStreaming}) => {
1052
1054
  const {api_key, model_id, baseURL, timeout, speed} = credentials;
1053
1055
  /* if the env is set to stream then bag out, unless we are specifically rendering to generate a cache file */
1054
1056
  if (!JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
@@ -1059,6 +1061,8 @@ const synthWhisper = async(logger, {credentials, stats, voice, text, renderForCa
1059
1061
  params += `,voice=${voice}`;
1060
1062
  params += ',write_cache_file=1';
1061
1063
  if (speed) params += `,speed=${speed}`;
1064
+ // comma is used to separated parameters in freeswitch tts module
1065
+ if (instructions) params += `,instructions=${instructions.replace(/\n/g, ' ').replace(/,/g, ';')}`;
1062
1066
  params += '}';
1063
1067
 
1064
1068
  return {
@@ -1078,6 +1082,7 @@ const synthWhisper = async(logger, {credentials, stats, voice, text, renderForCa
1078
1082
  model: model_id,
1079
1083
  voice,
1080
1084
  input: text,
1085
+ ...(instructions && {instructions}),
1081
1086
  response_format: 'mp3'
1082
1087
  });
1083
1088
  return {
package/lib/utils.js CHANGED
@@ -23,10 +23,11 @@ function makeSynthKey({
23
23
  voice,
24
24
  engine = '',
25
25
  model = '',
26
- text
26
+ text,
27
+ instructions = '',
27
28
  }) {
28
29
  const hash = crypto.createHash('sha1');
29
- hash.update(`${language}:${vendor}:${voice}:${engine}:${model}:${text}`);
30
+ hash.update(`${language}:${vendor}:${voice}:${engine}:${model}:${text}:${instructions}`);
30
31
  const hexHashKey = hash.digest('hex');
31
32
  const accountKey = account_sid ? `:${account_sid}` : '';
32
33
  const key = `tts${accountKey}:${hexHashKey}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jambonz/speech-utils",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "TTS-related speech utilities for jambonz",
5
5
  "main": "index.js",
6
6
  "author": "Dave Horton",
@@ -26,6 +26,7 @@
26
26
  },
27
27
  "homepage": "https://github.com/jambonz/speech-utils#readme",
28
28
  "dependencies": {
29
+ "23": "^0.0.0",
29
30
  "@aws-sdk/client-polly": "^3.496.0",
30
31
  "@aws-sdk/client-sts": "^3.496.0",
31
32
  "@cartesia/cartesia-js": "^2.1.0",
@@ -38,7 +39,7 @@
38
39
  "google-protobuf": "^3.21.2",
39
40
  "ibm-watson": "^8.0.0",
40
41
  "microsoft-cognitiveservices-speech-sdk": "1.38.0",
41
- "openai": "^4.25.0",
42
+ "openai": "^4.98.0",
42
43
  "undici": "^7.5.0"
43
44
  },
44
45
  "devDependencies": {
package/test/synth.js CHANGED
@@ -887,7 +887,8 @@ test('TTS Cache tests', async(t) => {
887
887
  // save some random tts keys to cache
888
888
  const minRecords = 8;
889
889
  for (const i in Array(minRecords).fill(0)) {
890
- await client.set(makeSynthKey({vendor: i, language: i, voice: i, engine: i, model: i, text: i}), i);
890
+ await client.set(makeSynthKey({vendor: i, language: i, voice: i, engine: i, model: i, text: i,
891
+ instructions: i}), i);
891
892
  }
892
893
  const count = await getTtsSize();
893
894
  t.ok(count >= minRecords, 'getTtsSize worked.');
@@ -906,7 +907,7 @@ test('TTS Cache tests', async(t) => {
906
907
  try {
907
908
  // save some random tts keys to cache
908
909
  for (const i in Array(10).fill(0)) {
909
- await client.set(makeSynthKey({vendor: i, language: i, voice: i, engine: i, text: i}), i);
910
+ await client.set(makeSynthKey({vendor: i, language: i, voice: i, engine: i, text: i, instructions: i}), i);
910
911
  }
911
912
  // save a specific key to tts cache
912
913
  const opts = {vendor: 'aws', language: 'en-US', voice: 'MALE', engine: 'Engine', text: 'Hello World!'};
@@ -944,10 +945,10 @@ test('TTS Cache tests', async(t) => {
944
945
  const account_sid = "12412512_cabc_5aff"
945
946
  const account_sid2 = "22412512_cabc_5aff"
946
947
  for (const i in Array(minRecords).fill(0)) {
947
- await client.set(makeSynthKey({account_sid, vendor: i, language: i, voice: i, engine: i, text: i}), i);
948
+ await client.set(makeSynthKey({account_sid, vendor: i, language: i, voice: i, engine: i, text: i, instructions: i}), i);
948
949
  }
949
950
  for (const i in Array(minRecords).fill(0)) {
950
- await client.set(makeSynthKey({account_sid: account_sid2, vendor: i, language: i, voice: i, engine: i, text: i}), i);
951
+ await client.set(makeSynthKey({account_sid: account_sid2, vendor: i, language: i, voice: i, engine: i, text: i, instructions: i}), i);
951
952
  }
952
953
  const {purgedCount} = await purgeTtsCache({account_sid});
953
954
  t.equal(purgedCount, minRecords, `successfully purged at least ${minRecords} tts records from cache for account_sid:${account_sid}`);