@jambonz/speech-utils 0.0.26 → 0.0.28
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.
- package/README.md +2 -1
- package/index.js +7 -4
- package/lib/get-aws-sts-token.js +45 -0
- package/lib/utils.js +7 -0
- package/package.json +3 -2
- package/test/aws.js +40 -0
- package/test/index.js +3 -0
package/README.md
CHANGED
package/index.js
CHANGED
|
@@ -3,10 +3,12 @@ const {noopLogger} = require('./lib/utils');
|
|
|
3
3
|
module.exports = (opts, logger) => {
|
|
4
4
|
logger = logger || noopLogger;
|
|
5
5
|
let client = opts.redis_client;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
const {
|
|
7
|
+
client: redisClient,
|
|
8
|
+
createHash,
|
|
9
|
+
retrieveHash
|
|
10
|
+
} = require('@jambonz/realtimedb-helpers')(opts, logger);
|
|
11
|
+
client = opts.redis_client || redisClient;
|
|
10
12
|
|
|
11
13
|
return {
|
|
12
14
|
client,
|
|
@@ -15,6 +17,7 @@ module.exports = (opts, logger) => {
|
|
|
15
17
|
synthAudio: require('./lib/synth-audio').bind(null, client, logger),
|
|
16
18
|
getNuanceAccessToken: require('./lib/get-nuance-access-token').bind(null, client, logger),
|
|
17
19
|
getIbmAccessToken: require('./lib/get-ibm-access-token').bind(null, client, logger),
|
|
20
|
+
getAwsAuthToken: require('./lib/get-aws-sts-token').bind(null, logger, createHash, retrieveHash),
|
|
18
21
|
getTtsVoices: require('./lib/get-tts-voices').bind(null, client, logger),
|
|
19
22
|
};
|
|
20
23
|
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const { STSClient, GetSessionTokenCommand } = require('@aws-sdk/client-sts');
|
|
2
|
+
const {makeAwsKey, noopLogger} = require('./utils');
|
|
3
|
+
const debug = require('debug')('jambonz:speech-utils');
|
|
4
|
+
const EXPIRY = 3600;
|
|
5
|
+
|
|
6
|
+
async function getAwsAuthToken(
|
|
7
|
+
logger,
|
|
8
|
+
createHash, retrieveHash,
|
|
9
|
+
awsAccessKeyId, awsSecretAccessKey, awsRegion) {
|
|
10
|
+
logger = logger || noopLogger;
|
|
11
|
+
try {
|
|
12
|
+
const key = makeAwsKey(awsAccessKeyId);
|
|
13
|
+
const obj = await retrieveHash(key);
|
|
14
|
+
if (obj) return {...obj, servedFromCache: true};
|
|
15
|
+
|
|
16
|
+
/* access token not found in cache, so generate it using STS */
|
|
17
|
+
const stsClient = new STSClient({
|
|
18
|
+
region: awsRegion,
|
|
19
|
+
credentials: {
|
|
20
|
+
accessKeyId: awsAccessKeyId,
|
|
21
|
+
secretAccessKey: awsSecretAccessKey,
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
const command = new GetSessionTokenCommand({DurationSeconds: EXPIRY});
|
|
25
|
+
const data = await stsClient.send(command);
|
|
26
|
+
|
|
27
|
+
const credentials = {
|
|
28
|
+
accessKeyId: data.Credentials.AccessKeyId,
|
|
29
|
+
secretAccessKey: data.Credentials.SecretAccessKey,
|
|
30
|
+
sessionToken: data.Credentials.SessionToken
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/* expire 10 minutes before the hour, so we don't lose the use of it during a call */
|
|
34
|
+
createHash(key, credentials, EXPIRY - 600)
|
|
35
|
+
.catch((err) => logger.error(err, `Error saving hash for key ${key}`));
|
|
36
|
+
|
|
37
|
+
return {...credentials, servedFromCache: false};
|
|
38
|
+
} catch (err) {
|
|
39
|
+
debug(err, 'getAwsAuthToken: Error retrieving AWS auth token');
|
|
40
|
+
logger.error(err, 'getAwsAuthToken: Error retrieving AWS auth token');
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = getAwsAuthToken;
|
package/lib/utils.js
CHANGED
|
@@ -43,6 +43,12 @@ function makeIbmKey(apiKey) {
|
|
|
43
43
|
return `ibm:${hash.digest('hex')}`;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
function makeAwsKey(awsAccessKeyId) {
|
|
47
|
+
const hash = crypto.createHash('sha1');
|
|
48
|
+
hash.update(awsAccessKeyId);
|
|
49
|
+
return `aws:${hash.digest('hex')}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
46
52
|
function makeNuanceKey(clientId, secret, scope) {
|
|
47
53
|
const hash = crypto.createHash('sha1');
|
|
48
54
|
hash.update(`${clientId}:${secret}:${scope}`);
|
|
@@ -110,6 +116,7 @@ module.exports = {
|
|
|
110
116
|
makeSynthKey,
|
|
111
117
|
makeNuanceKey,
|
|
112
118
|
makeIbmKey,
|
|
119
|
+
makeAwsKey,
|
|
113
120
|
getNuanceAccessToken,
|
|
114
121
|
createNuanceClient,
|
|
115
122
|
createKryptonClient,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jambonz/speech-utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.28",
|
|
4
4
|
"description": "TTS-related speech utilities for jambonz",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Dave Horton",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"homepage": "https://github.com/jambonz/speech-utils#readme",
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@aws-sdk/client-polly": "^3.359.0",
|
|
28
|
+
"@aws-sdk/client-sts": "^3.458.0",
|
|
28
29
|
"@google-cloud/text-to-speech": "^4.2.1",
|
|
29
30
|
"@grpc/grpc-js": "^1.8.13",
|
|
30
31
|
"@jambonz/realtimedb-helpers": "^0.8.7",
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
"form-urlencoded": "^6.1.0",
|
|
34
35
|
"google-protobuf": "^3.21.2",
|
|
35
36
|
"ibm-watson": "^8.0.0",
|
|
36
|
-
"microsoft-cognitiveservices-speech-sdk": "
|
|
37
|
+
"microsoft-cognitiveservices-speech-sdk": "1.32.0",
|
|
37
38
|
"openai": "^4.16.2",
|
|
38
39
|
"undici": "^5.21.0"
|
|
39
40
|
},
|
package/test/aws.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const test = require('tape').test ;
|
|
2
|
+
const config = require('config');
|
|
3
|
+
const opts = config.get('redis');
|
|
4
|
+
const logger = require('pino')({level: 'error'});
|
|
5
|
+
process.on('unhandledRejection', (reason, p) => {
|
|
6
|
+
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
10
|
+
|
|
11
|
+
test('AWS - create and cache auth token', async(t) => {
|
|
12
|
+
const fn = require('..');
|
|
13
|
+
const {client, getAwsAuthToken} = fn(opts, logger);
|
|
14
|
+
|
|
15
|
+
if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY || !process.env.AWS_REGION) {
|
|
16
|
+
t.pass('skipping AWS auth token tests since no AWS credentials provided');
|
|
17
|
+
t.end();
|
|
18
|
+
client.quit();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
let obj = await getAwsAuthToken(process.env.AWS_ACCESS_KEY_ID, process.env.AWS_SECRET_ACCESS_KEY, process.env.AWS_REGION);
|
|
23
|
+
//console.log({obj}, 'received auth token from AWS');
|
|
24
|
+
t.ok(obj.sessionToken && !obj.servedFromCache, 'successfullY generated auth token from AWS');
|
|
25
|
+
|
|
26
|
+
await sleep(250);
|
|
27
|
+
obj = await getAwsAuthToken(process.env.AWS_ACCESS_KEY_ID, process.env.AWS_SECRET_ACCESS_KEY, process.env.AWS_REGION);
|
|
28
|
+
//console.log({obj}, 'received auth token from AWS - second request');
|
|
29
|
+
t.ok(obj.sessionToken && obj.servedFromCache, 'successfully received access token from cache');
|
|
30
|
+
|
|
31
|
+
await client.flushall();
|
|
32
|
+
t.end();
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
console.error(err);
|
|
36
|
+
t.end(err);
|
|
37
|
+
}
|
|
38
|
+
client.quit();
|
|
39
|
+
});
|
|
40
|
+
|