@jambonz/speech-utils 0.0.19 → 0.0.20
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/lib/synth-audio.js +62 -4
- package/lib/utils.js +0 -1
- package/package.json +2 -2
package/lib/synth-audio.js
CHANGED
|
@@ -14,7 +14,13 @@ const {
|
|
|
14
14
|
CancellationDetails,
|
|
15
15
|
SpeechSynthesisOutputFormat
|
|
16
16
|
} = sdk;
|
|
17
|
-
const {
|
|
17
|
+
const {
|
|
18
|
+
makeSynthKey,
|
|
19
|
+
createNuanceClient,
|
|
20
|
+
createKryptonClient,
|
|
21
|
+
createRivaClient,
|
|
22
|
+
noopLogger
|
|
23
|
+
} = require('./utils');
|
|
18
24
|
const getNuanceAccessToken = require('./get-nuance-access-token');
|
|
19
25
|
const {
|
|
20
26
|
SynthesisRequest,
|
|
@@ -297,6 +303,47 @@ const synthIbm = async(logger, {credentials, stats, voice, text}) => {
|
|
|
297
303
|
}
|
|
298
304
|
};
|
|
299
305
|
|
|
306
|
+
async function _synthOnPremMicrosoft(logger, {
|
|
307
|
+
credentials,
|
|
308
|
+
stats,
|
|
309
|
+
language,
|
|
310
|
+
voice,
|
|
311
|
+
text,
|
|
312
|
+
filePath
|
|
313
|
+
}) {
|
|
314
|
+
const {use_custom_tts, custom_tts_endpoint_url} = credentials;
|
|
315
|
+
let content = text;
|
|
316
|
+
|
|
317
|
+
if (use_custom_tts && !content.startsWith('<speak')) {
|
|
318
|
+
/**
|
|
319
|
+
* Note: it seems that to use custom voice ssml is required with the voice attribute
|
|
320
|
+
* Otherwise sending plain text we get "Voice does not match"
|
|
321
|
+
*/
|
|
322
|
+
content = `<speak>${text}</speak>`;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (content.startsWith('<speak>')) {
|
|
326
|
+
/* microsoft enforces some properties and uses voice xml element so if the user did not supply do it for them */
|
|
327
|
+
const words = content.slice(7, -8).trim().replace(/(\r\n|\n|\r)/gm, ' ');
|
|
328
|
+
// eslint-disable-next-line max-len
|
|
329
|
+
content = `<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xml:lang="${language}"><voice name="${voice}">${words}</voice></speak>`;
|
|
330
|
+
logger.info({content}, 'synthMicrosoft');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
try {
|
|
334
|
+
const post = bent('POST', 'buffer', {
|
|
335
|
+
'X-Microsoft-OutputFormat': 'audio-16khz-128kbitrate-mono-mp3',
|
|
336
|
+
'Content-Type': 'application/ssml+xml',
|
|
337
|
+
'User-Agent': 'Jambonz'
|
|
338
|
+
});
|
|
339
|
+
const mp3 = await post(custom_tts_endpoint_url, content);
|
|
340
|
+
return mp3;
|
|
341
|
+
} catch (err) {
|
|
342
|
+
logger.info({err}, '_synthMicrosoftByHttp returned error');
|
|
343
|
+
throw err;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
300
347
|
const synthMicrosoft = async(logger, {
|
|
301
348
|
credentials,
|
|
302
349
|
stats,
|
|
@@ -306,7 +353,17 @@ const synthMicrosoft = async(logger, {
|
|
|
306
353
|
filePath
|
|
307
354
|
}) => {
|
|
308
355
|
try {
|
|
309
|
-
const {api_key: apiKey, region, use_custom_tts, custom_tts_endpoint} = credentials;
|
|
356
|
+
const {api_key: apiKey, region, use_custom_tts, custom_tts_endpoint, custom_tts_endpoint_url} = credentials;
|
|
357
|
+
if (use_custom_tts && custom_tts_endpoint_url) {
|
|
358
|
+
return await _synthOnPremMicrosoft(logger, {
|
|
359
|
+
credentials,
|
|
360
|
+
stats,
|
|
361
|
+
language,
|
|
362
|
+
voice,
|
|
363
|
+
text,
|
|
364
|
+
filePath
|
|
365
|
+
});
|
|
366
|
+
}
|
|
310
367
|
const trimSilence = filePath.endsWith('.r8');
|
|
311
368
|
let content = text;
|
|
312
369
|
const speechConfig = SpeechConfig.fromSubscription(apiKey, region);
|
|
@@ -314,12 +371,13 @@ const synthMicrosoft = async(logger, {
|
|
|
314
371
|
speechConfig.speechSynthesisVoiceName = voice;
|
|
315
372
|
if (use_custom_tts && custom_tts_endpoint) {
|
|
316
373
|
speechConfig.endpointId = custom_tts_endpoint;
|
|
317
|
-
|
|
374
|
+
}
|
|
375
|
+
if (use_custom_tts && !content.startsWith('<speak')) {
|
|
318
376
|
/**
|
|
319
377
|
* Note: it seems that to use custom voice ssml is required with the voice attribute
|
|
320
378
|
* Otherwise sending plain text we get "Voice does not match"
|
|
321
379
|
*/
|
|
322
|
-
|
|
380
|
+
content = `<speak>${text}</speak>`;
|
|
323
381
|
}
|
|
324
382
|
speechConfig.speechSynthesisOutputFormat = trimSilence ?
|
|
325
383
|
SpeechSynthesisOutputFormat.Raw8Khz16BitMonoPcm :
|
package/lib/utils.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jambonz/speech-utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.20",
|
|
4
4
|
"description": "TTS-related speech utilities for jambonz",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Dave Horton",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"form-urlencoded": "^6.1.0",
|
|
33
33
|
"google-protobuf": "^3.21.2",
|
|
34
34
|
"ibm-watson": "^8.0.0",
|
|
35
|
-
"microsoft-cognitiveservices-speech-sdk": "^1.
|
|
35
|
+
"microsoft-cognitiveservices-speech-sdk": "^1.31.0",
|
|
36
36
|
"ioredis": "^5.3.2",
|
|
37
37
|
"undici": "^5.21.0"
|
|
38
38
|
},
|