@jambonz/speech-utils 0.0.7 → 0.0.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.
@@ -4,6 +4,8 @@ const getNuanceAccessToken = require('./get-nuance-access-token');
4
4
  const {GetVoicesRequest, Voice} = require('../stubs/nuance/synthesizer_pb');
5
5
  const TextToSpeechV1 = require('ibm-watson/text-to-speech/v1');
6
6
  const { IamAuthenticator } = require('ibm-watson/auth');
7
+ const ttsGoogle = require('@google-cloud/text-to-speech');
8
+ const { PollyClient, DescribeVoicesCommand } = require('@aws-sdk/client-polly');
7
9
 
8
10
  const getIbmVoices = async(client, logger, credentials) => {
9
11
  const {tts_region, tts_api_key} = credentials;
@@ -80,6 +82,30 @@ const getNuanceVoices = async(client, logger, credentials) => {
80
82
  });
81
83
  };
82
84
 
85
+ const getGoogleVoices = async(_client, logger, credentials) => {
86
+ const client = new ttsGoogle.TextToSpeechClient({credentials});
87
+ return await client.listVoices();
88
+ };
89
+
90
+ const getAwsVoices = async(_client, logger, credentials) => {
91
+ try {
92
+ const {region, accessKeyId, secretAccessKey} = credentials;
93
+ const client = new PollyClient({
94
+ region,
95
+ credentials: {
96
+ accessKeyId,
97
+ secretAccessKey
98
+ }
99
+ });
100
+ const command = new DescribeVoicesCommand({LanguageCode: 'en-US'});
101
+ const response = await client.send(command);
102
+ return response;
103
+ } catch (err) {
104
+ logger.info({err}, 'testMicrosoftTts - failed to list voices for region ${region}');
105
+ throw err;
106
+ }
107
+ };
108
+
83
109
  /**
84
110
  * Synthesize speech to an mp3 file, and also cache the generated speech
85
111
  * in redis (base64 format) for 24 hours so as to avoid unnecessarily paying
@@ -99,7 +125,7 @@ const getNuanceVoices = async(client, logger, credentials) => {
99
125
  async function getTtsVoices(client, logger, {vendor, credentials}) {
100
126
  logger = logger || noopLogger;
101
127
 
102
- assert.ok(['nuance', 'ibm'].includes(vendor),
128
+ assert.ok(['nuance', 'ibm', 'google', 'aws', 'polly'].includes(vendor),
103
129
  `getTtsVoices not supported for vendor ${vendor}`);
104
130
 
105
131
  switch (vendor) {
@@ -107,6 +133,11 @@ async function getTtsVoices(client, logger, {vendor, credentials}) {
107
133
  return getNuanceVoices(client, logger, credentials);
108
134
  case 'ibm':
109
135
  return getIbmVoices(client, logger, credentials);
136
+ case 'google':
137
+ return getGoogleVoices(client, logger, credentials);
138
+ case 'aws':
139
+ case 'polly':
140
+ return getAwsVoices(client, logger, credentials);
110
141
  default:
111
142
  break;
112
143
  }
@@ -444,7 +444,6 @@ const synthNvidia = async(client, logger, {credentials, stats, language, voice,
444
444
  request.setText(text);
445
445
 
446
446
  return new Promise((resolve, reject) => {
447
- console.log(`language ${language} voice ${voice} model ${model} text ${text}`);
448
447
  rivaClient.synthesize(request, (err, response) => {
449
448
  if (err) {
450
449
  console.error(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jambonz/speech-utils",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "TTS-related speech utilities for jambonz",
5
5
  "main": "index.js",
6
6
  "author": "Dave Horton",
@@ -24,18 +24,18 @@
24
24
  },
25
25
  "homepage": "https://github.com/jambonz/speech-utils#readme",
26
26
  "dependencies": {
27
- "@aws-sdk/client-polly": "^3.276.0",
28
- "@google-cloud/text-to-speech": "^4.2.0",
29
- "@grpc/grpc-js": "^1.8.7",
30
- "@jambonz/realtimedb-helpers": "^0.6.3",
31
- "aws-sdk": "^2.1310.0",
27
+ "@aws-sdk/client-polly": "^3.303.0",
28
+ "@google-cloud/text-to-speech": "^4.2.1",
29
+ "@grpc/grpc-js": "^1.8.13",
30
+ "@jambonz/promisify-redis": "^0.0.6",
32
31
  "bent": "^7.3.12",
33
32
  "debug": "^4.3.4",
34
- "google-protobuf": "^3.21.2",
35
- "ibm-watson": "^7.1.2",
36
33
  "form-urlencoded": "^6.1.0",
37
- "microsoft-cognitiveservices-speech-sdk": "^1.25.0",
38
- "undici": "^5.19.1"
34
+ "google-protobuf": "^3.21.2",
35
+ "ibm-watson": "^8.0.0",
36
+ "microsoft-cognitiveservices-speech-sdk": "^1.26.0",
37
+ "redis": "^3.1.2",
38
+ "undici": "^5.21.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "config": "^3.3.9",
package/test/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  require('./docker_start');
2
2
  require('./synth');
3
- require('./nuance');
4
- require('./ibm');
3
+ require('./list-voices');
5
4
  require('./docker_stop');
@@ -0,0 +1,205 @@
1
+ const test = require('tape').test ;
2
+ const config = require('config');
3
+ const opts = config.get('redis');
4
+ const fs = require('fs');
5
+ const logger = require('pino')({level: 'error'});
6
+ process.on('unhandledRejection', (reason, p) => {
7
+ console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
8
+ });
9
+
10
+ const stats = {
11
+ increment: () => {},
12
+ histogram: () => {}
13
+ };
14
+
15
+ test('IBM - create access key', async(t) => {
16
+ const fn = require('..');
17
+ const {client, getIbmAccessToken} = fn(opts, logger);
18
+
19
+ if (!process.env.IBM_API_KEY ) {
20
+ t.pass('skipping IBM test since no IBM api_key provided');
21
+ t.end();
22
+ client.quit();
23
+ return;
24
+ }
25
+ try {
26
+ let obj = await getIbmAccessToken(process.env.IBM_API_KEY);
27
+ //console.log({obj}, 'received access token from IBM');
28
+ t.ok(obj.access_token && !obj.servedFromCache, 'successfull received access token from IBM');
29
+
30
+ obj = await getIbmAccessToken(process.env.IBM_API_KEY);
31
+ //console.log({obj}, 'received access token from IBM - second request');
32
+ t.ok(obj.access_token && obj.servedFromCache, 'successfully received access token from cache');
33
+
34
+ await client.flushallAsync();
35
+ t.end();
36
+ }
37
+ catch (err) {
38
+ console.error(err);
39
+ t.end(err);
40
+ }
41
+ client.quit();
42
+ });
43
+
44
+ test('IBM - retrieve tts voices test', async(t) => {
45
+ const fn = require('..');
46
+ const {client, getTtsVoices} = fn(opts, logger);
47
+
48
+ if (!process.env.IBM_TTS_API_KEY || !process.env.IBM_TTS_REGION) {
49
+ t.pass('skipping IBM test since no IBM api_key and/or region provided');
50
+ t.end();
51
+ client.quit();
52
+ return;
53
+ }
54
+ try {
55
+ const opts = {
56
+ vendor: 'ibm',
57
+ credentials: {
58
+ tts_api_key: process.env.IBM_TTS_API_KEY,
59
+ tts_region: process.env.IBM_TTS_REGION
60
+ }
61
+ };
62
+ const obj = await getTtsVoices(opts);
63
+ const {voices} = obj.result;
64
+ //console.log(JSON.stringify(voices));
65
+ t.ok(voices.length > 0 && voices[0].language,
66
+ `GetVoices: successfully retrieved ${voices.length} voices from IBM`);
67
+
68
+ await client.flushallAsync();
69
+
70
+ t.end();
71
+
72
+ }
73
+ catch (err) {
74
+ console.error(err);
75
+ t.end(err);
76
+ }
77
+ client.quit();
78
+ });
79
+
80
+ test('Nuance hosted tests', async(t) => {
81
+ const fn = require('..');
82
+ const {client, getTtsVoices} = fn(opts, logger);
83
+
84
+ if (!process.env.NUANCE_CLIENT_ID || !process.env.NUANCE_SECRET ) {
85
+ t.pass('skipping Nuance hosted test since no Nuance client_id and secret provided');
86
+ t.end();
87
+ client.quit();
88
+ return;
89
+ }
90
+ try {
91
+ const opts = {
92
+ vendor: 'nuance',
93
+ credentials: {
94
+ client_id: process.env.NUANCE_CLIENT_ID,
95
+ secret: process.env.NUANCE_SECRET
96
+ }
97
+ };
98
+ let voices = await getTtsVoices(opts);
99
+ t.ok(voices.length > 0 && voices[0].language,
100
+ `GetVoices: successfully retrieved ${voices.length} voices from Nuance`);
101
+
102
+ await client.flushallAsync();
103
+
104
+ t.end();
105
+
106
+ }
107
+ catch (err) {
108
+ console.error(err);
109
+ t.end(err);
110
+ }
111
+ client.quit();
112
+ });
113
+
114
+ test('Nuance on-prem tests', async(t) => {
115
+ const fn = require('..');
116
+ const {client, getTtsVoices} = fn(opts, logger);
117
+
118
+ if (!process.env.NUANCE_TTS_URI ) {
119
+ t.pass('skipping Nuance on-prem test since no Nuance uri provided');
120
+ t.end();
121
+ client.quit();
122
+ return;
123
+ }
124
+ try {
125
+ const opts = {
126
+ vendor: 'nuance',
127
+ credentials: {
128
+ nuance_tts_uri: process.env.NUANCE_TTS_URI
129
+ }
130
+ };
131
+ let voices = await getTtsVoices(opts);
132
+ t.ok(voices.length > 0 && voices[0].language,
133
+ `GetVoices: successfully retrieved ${voices.length} voices from Nuance`);
134
+
135
+ await client.flushallAsync();
136
+
137
+ t.end();
138
+
139
+ }
140
+ catch (err) {
141
+ console.error(err);
142
+ t.end(err);
143
+ }
144
+ client.quit();
145
+ });
146
+
147
+ test('Google tests', async(t) => {
148
+ const fn = require('..');
149
+ const {client, getTtsVoices} = fn(opts, logger);
150
+
151
+ if (!process.env.GCP_FILE && !process.env.GCP_JSON_KEY) {
152
+ t.pass('skipping google speech synth tests since neither GCP_FILE nor GCP_JSON_KEY provided');
153
+ return t.end();
154
+ }
155
+ try {
156
+ const str = process.env.GCP_JSON_KEY || fs.readFileSync(process.env.GCP_FILE);
157
+ const credentials = JSON.parse(str);
158
+ const opts = {
159
+ vendor: 'google',
160
+ credentials
161
+ };
162
+ let result = await getTtsVoices(opts);
163
+ t.ok(result[0].voices.length > 0, `GetVoices: successfully retrieved ${result[0].voices.length} voices from Google`);
164
+
165
+ await client.flushallAsync();
166
+
167
+ t.end();
168
+ }
169
+ catch (err) {
170
+ console.error(err);
171
+ t.end(err);
172
+ }
173
+ client.quit();
174
+ });
175
+
176
+ test('AWS tests', async(t) => {
177
+ const fn = require('..');
178
+ const {client, getTtsVoices} = fn(opts, logger);
179
+
180
+ if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY || !process.env.AWS_REGION) {
181
+ t.pass('skipping AWS speech synth tests since AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, or AWS_REGION not provided');
182
+ return t.end();
183
+ }
184
+ try {
185
+ const opts = {
186
+ vendor: 'aws',
187
+ credentials: {
188
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
189
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
190
+ region: process.env.AWS_REGION,
191
+ }
192
+ };
193
+ let result = await getTtsVoices(opts);
194
+ t.ok(result?.Voices?.length > 0, `GetVoices: successfully retrieved ${result.Voices.length} voices from AWS`);
195
+
196
+ await client.flushallAsync();
197
+
198
+ t.end();
199
+ }
200
+ catch (err) {
201
+ console.error(err);
202
+ t.end(err);
203
+ }
204
+ client.quit();
205
+ });