@jambonz/speech-utils 0.2.8 → 0.2.10

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, {
@@ -854,11 +855,10 @@ const synthElevenlabs = async(logger, {
854
855
  const synthPlayHT = async(client, logger, {
855
856
  credentials, options, stats, voice, language, text, renderForCaching, disableTtsStreaming
856
857
  }) => {
857
- const {api_key, user_id, voice_engine, options: credOpts} = credentials;
858
+ const {api_key, user_id, voice_engine, playht_tts_uri, options: credOpts} = credentials;
858
859
  const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
859
860
 
860
- let synthesizeUrl = 'https://api.play.ht/api/v2/tts/stream';
861
-
861
+ let synthesizeUrl = playht_tts_uri ? `${playht_tts_uri}/api/v2/tts/stream` : 'https://api.play.ht/api/v2/tts/stream';
862
862
  // If model is play3.0, the synthesizeUrl is got from authentication endpoint
863
863
  if (voice_engine === 'Play3.0') {
864
864
  try {
@@ -1048,7 +1048,8 @@ const synthVerbio = async(client, logger, {credentials, stats, voice, text, rend
1048
1048
  }
1049
1049
  };
1050
1050
 
1051
- const synthWhisper = async(logger, {credentials, stats, voice, text, renderForCaching, disableTtsStreaming}) => {
1051
+ const synthWhisper = async(logger, {credentials, stats, voice, text, instructions,
1052
+ renderForCaching, disableTtsStreaming}) => {
1052
1053
  const {api_key, model_id, baseURL, timeout, speed} = credentials;
1053
1054
  /* if the env is set to stream then bag out, unless we are specifically rendering to generate a cache file */
1054
1055
  if (!JAMBONES_DISABLE_TTS_STREAMING && !renderForCaching && !disableTtsStreaming) {
@@ -1059,6 +1060,8 @@ const synthWhisper = async(logger, {credentials, stats, voice, text, renderForCa
1059
1060
  params += `,voice=${voice}`;
1060
1061
  params += ',write_cache_file=1';
1061
1062
  if (speed) params += `,speed=${speed}`;
1063
+ // comma is used to separated parameters in freeswitch tts module
1064
+ if (instructions) params += `,instructions=${instructions.replace(/\n/g, ' ').replace(/,/g, ';')}`;
1062
1065
  params += '}';
1063
1066
 
1064
1067
  return {
@@ -1078,6 +1081,7 @@ const synthWhisper = async(logger, {credentials, stats, voice, text, renderForCa
1078
1081
  model: model_id,
1079
1082
  voice,
1080
1083
  input: text,
1084
+ ...(instructions && {instructions}),
1081
1085
  response_format: 'mp3'
1082
1086
  });
1083
1087
  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.10",
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}`);