mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2026-01-25 02:07:56 +00:00
Compare commits
1 Commits
v0.8.2-rc2
...
#271
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aad49c6d3b |
@@ -660,14 +660,6 @@ class CallSession extends Emitter {
|
||||
stt_region: credential.stt_region
|
||||
};
|
||||
}
|
||||
else if (vendor.startsWith('custom:')) {
|
||||
return {
|
||||
speech_credential_sid: credential.speech_credential_sid,
|
||||
auth_token: credential.auth_token,
|
||||
custom_stt_url: credential.custom_stt_url,
|
||||
custom_tts_url: credential.custom_tts_url
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
writeAlerts({
|
||||
|
||||
@@ -400,19 +400,15 @@ class TaskDial extends Task {
|
||||
let fqdn;
|
||||
|
||||
if (!sbcAddress) throw new Error('no SBC found for outbound call');
|
||||
this.headers = {
|
||||
'X-Account-Sid': cs.accountSid,
|
||||
...(req && req.has('X-CID') && {'X-CID': req.get('X-CID')}),
|
||||
...(req && req.has('P-Asserted-Identity') && {'P-Asserted-Identity': req.get('P-Asserted-Identity')}),
|
||||
// Put headers at the end to make sure opt.headers override all default behavior.
|
||||
...this.headers
|
||||
};
|
||||
|
||||
const opts = {
|
||||
headers: this.headers,
|
||||
headers: req && req.has('X-CID') ? Object.assign(this.headers, {'X-CID': req.get('X-CID')}) : this.headers,
|
||||
proxy: `sip:${sbcAddress}`,
|
||||
callingNumber: this.callerId || req.callingNumber
|
||||
};
|
||||
opts.headers = {
|
||||
...opts.headers,
|
||||
'X-Account-Sid': cs.accountSid
|
||||
};
|
||||
|
||||
const t = this.target.find((t) => t.type === 'teams');
|
||||
if (t) {
|
||||
|
||||
@@ -9,8 +9,7 @@ const {
|
||||
DeepgramTranscriptionEvents,
|
||||
SonioxTranscriptionEvents,
|
||||
IbmTranscriptionEvents,
|
||||
NvidiaTranscriptionEvents,
|
||||
JambonzTranscriptionEvents
|
||||
NvidiaTranscriptionEvents
|
||||
} = require('../utils/constants');
|
||||
|
||||
const makeTask = require('./make_task');
|
||||
@@ -380,6 +379,8 @@ class TaskGather extends Task {
|
||||
this._onTranscriptionComplete.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(NuanceTranscriptionEvents.VadDetected,
|
||||
this._onVadDetected.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(NuanceTranscriptionEvents.Error,
|
||||
this._onNuanceError.bind(this, cs, ep));
|
||||
|
||||
/* stall timers until prompt finishes playing */
|
||||
if ((this.sayTask || this.playTask) && this.listenDuringPrompt) {
|
||||
@@ -398,6 +399,8 @@ class TaskGather extends Task {
|
||||
case 'soniox':
|
||||
this.bugname = 'soniox_transcribe';
|
||||
ep.addCustomEventListener(SonioxTranscriptionEvents.Transcription, this._onTranscription.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(SonioxTranscriptionEvents.Error,
|
||||
this._onSonioxError.bind(this, cs, ep));
|
||||
break;
|
||||
|
||||
case 'ibm':
|
||||
@@ -406,6 +409,8 @@ class TaskGather extends Task {
|
||||
ep.addCustomEventListener(IbmTranscriptionEvents.Connect, this._onIbmConnect.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(IbmTranscriptionEvents.ConnectFailure,
|
||||
this._onIbmConnectFailure.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(IbmTranscriptionEvents.Error,
|
||||
this._onIbmError.bind(this, cs, ep));
|
||||
break;
|
||||
|
||||
case 'nvidia':
|
||||
@@ -418,6 +423,8 @@ class TaskGather extends Task {
|
||||
this._onTranscriptionComplete.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(NvidiaTranscriptionEvents.VadDetected,
|
||||
this._onVadDetected.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(NvidiaTranscriptionEvents.Error,
|
||||
this._onNvidiaError.bind(this, cs, ep));
|
||||
|
||||
/* I think nvidia has this (??) - stall timers until prompt finishes playing */
|
||||
if ((this.sayTask || this.playTask) && this.listenDuringPrompt) {
|
||||
@@ -426,23 +433,11 @@ class TaskGather extends Task {
|
||||
break;
|
||||
|
||||
default:
|
||||
if (this.vendor.startsWith('custom:')) {
|
||||
this.bugname = `${this.vendor}_transcribe`;
|
||||
ep.addCustomEventListener(JambonzTranscriptionEvents.Transcription, this._onTranscription.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(JambonzTranscriptionEvents.Connect, this._onJambonzConnect.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(JambonzTranscriptionEvents.ConnectFailure,
|
||||
this._onJambonzConnectFailure.bind(this, cs, ep));
|
||||
break;
|
||||
}
|
||||
else {
|
||||
this.notifyError({ msg: 'ASR error', details:`Invalid vendor ${this.vendor}`});
|
||||
this.notifyTaskDone();
|
||||
throw new Error(`Invalid vendor ${this.vendor}`);
|
||||
}
|
||||
this.notifyError({ msg: 'ASR error', details:`Invalid vendor ${this.vendor}`});
|
||||
this.notifyTaskDone();
|
||||
throw new Error(`Invalid vendor ${this.vendor}`);
|
||||
}
|
||||
|
||||
/* common handler for all stt engine errors */
|
||||
ep.addCustomEventListener(JambonzTranscriptionEvents.Error, this._onJambonzError.bind(this, cs, ep));
|
||||
await ep.set(opts)
|
||||
.catch((err) => this.logger.info(err, 'Error setting channel variables'));
|
||||
}
|
||||
@@ -667,30 +662,26 @@ class TaskGather extends Task {
|
||||
_onTranscriptionComplete(cs, ep) {
|
||||
this.logger.debug('TaskGather:_onTranscriptionComplete');
|
||||
}
|
||||
_onNuanceError(cs, ep, evt) {
|
||||
const {code, error, details} = evt;
|
||||
if (code === 404 && error === 'No speech') {
|
||||
this.logger.debug({code, error, details}, 'TaskGather:_onNuanceError');
|
||||
return this._resolve('timeout');
|
||||
}
|
||||
this.logger.info({code, error, details}, 'TaskGather:_onNuanceError');
|
||||
if (code === 413 && error === 'Too much speech') {
|
||||
return this._resolve('timeout');
|
||||
}
|
||||
}
|
||||
_onSonioxError(cs, ep, evt) {
|
||||
this.logger.info({evt}, 'TaskGather:_onSonioxError');
|
||||
}
|
||||
_onNvidiaError(cs, ep, evt) {
|
||||
this.logger.info({evt}, 'TaskGather:_onNvidiaError');
|
||||
}
|
||||
_onDeepgramConnect(_cs, _ep) {
|
||||
this.logger.debug('TaskGather:_onDeepgramConnect');
|
||||
}
|
||||
_onJambonzConnect(_cs, _ep) {
|
||||
this.logger.debug('TaskGather:_onJambonzConnect');
|
||||
}
|
||||
_onJambonzError(cs, _ep, evt) {
|
||||
this.logger.info({evt}, 'TaskGather:_onJambonzError');
|
||||
const {writeAlerts, AlertType} = cs.srf.locals;
|
||||
|
||||
if (this.vendor === 'nuance') {
|
||||
const {code, error} = evt;
|
||||
if (code === 404 && error === 'No speech') return this._resolve('timeout');
|
||||
if (code === 413 && error === 'Too much speech') return this._resolve('timeout');
|
||||
}
|
||||
this.logger.info({evt}, 'TaskGather:_onJambonzError');
|
||||
writeAlerts({
|
||||
account_sid: cs.accountSid,
|
||||
alert_type: AlertType.STT_FAILURE,
|
||||
message: `Custom speech vendor ${this.vendor} error: ${evt.error}`,
|
||||
vendor: this.vendor,
|
||||
}).catch((err) => this.logger.info({err}, 'Error generating alert for jambonz custom connection failure'));
|
||||
this.notifyError({msg: 'ASR error', details:`Custom speech vendor ${this.vendor} error: ${evt.error}`});
|
||||
}
|
||||
|
||||
_onDeepGramConnectFailure(cs, _ep, evt) {
|
||||
const {reason} = evt;
|
||||
@@ -705,19 +696,6 @@ class TaskGather extends Task {
|
||||
this.notifyError({msg: 'ASR error', details:`Failed connecting to speech vendor deepgram: ${reason}`});
|
||||
this.notifyTaskDone();
|
||||
}
|
||||
_onJambonzConnectFailure(cs, _ep, evt) {
|
||||
const {reason} = evt;
|
||||
const {writeAlerts, AlertType} = cs.srf.locals;
|
||||
this.logger.info({evt}, 'TaskGather:_onJambonzConnectFailure');
|
||||
writeAlerts({
|
||||
account_sid: cs.accountSid,
|
||||
alert_type: AlertType.STT_FAILURE,
|
||||
message: `Failed connecting to ${this.vendor} speech recognizer: ${reason}`,
|
||||
vendor: this.vendor,
|
||||
}).catch((err) => this.logger.info({err}, 'Error generating alert for jambonz custom connection failure'));
|
||||
this.notifyError({msg: 'ASR error', details:`Failed connecting to speech vendor ${this.vendor}: ${reason}`});
|
||||
this.notifyTaskDone();
|
||||
}
|
||||
|
||||
_onIbmConnect(_cs, _ep) {
|
||||
this.logger.debug('TaskGather:_onIbmConnect');
|
||||
|
||||
@@ -9,8 +9,7 @@ const {
|
||||
DeepgramTranscriptionEvents,
|
||||
SonioxTranscriptionEvents,
|
||||
IbmTranscriptionEvents,
|
||||
NvidiaTranscriptionEvents,
|
||||
JambonzTranscriptionEvents
|
||||
NvidiaTranscriptionEvents
|
||||
} = require('../utils/constants');
|
||||
const { normalizeJambones } = require('@jambonz/verb-specifications');
|
||||
|
||||
@@ -24,13 +23,11 @@ class TaskTranscribe extends Task {
|
||||
setChannelVarsForStt,
|
||||
normalizeTranscription,
|
||||
removeSpeechListeners,
|
||||
setSpeechCredentialsAtRuntime,
|
||||
compileSonioxTranscripts
|
||||
setSpeechCredentialsAtRuntime
|
||||
} = require('../utils/transcription-utils')(logger);
|
||||
this.setChannelVarsForStt = setChannelVarsForStt;
|
||||
this.normalizeTranscription = normalizeTranscription;
|
||||
this.removeSpeechListeners = removeSpeechListeners;
|
||||
this.compileSonioxTranscripts = compileSonioxTranscripts;
|
||||
|
||||
this.transcriptionHook = this.data.transcriptionHook;
|
||||
this.earlyMedia = this.data.earlyMedia === true || (parentTask && parentTask.earlyMedia);
|
||||
@@ -44,9 +41,6 @@ class TaskTranscribe extends Task {
|
||||
/* let credentials be supplied in the recognizer object at runtime */
|
||||
this.sttCredentials = setSpeechCredentialsAtRuntime(recognizer);
|
||||
|
||||
/* buffer for soniox transcripts */
|
||||
this._sonioxTranscripts = [];
|
||||
|
||||
recognizer.hints = recognizer.hints || [];
|
||||
recognizer.altLanguages = recognizer.altLanguages || [];
|
||||
}
|
||||
@@ -190,6 +184,8 @@ class TaskTranscribe extends Task {
|
||||
this._onStartOfSpeech.bind(this, cs, ep, channel));
|
||||
ep.addCustomEventListener(NuanceTranscriptionEvents.TranscriptionComplete,
|
||||
this._onTranscriptionComplete.bind(this, cs, ep, channel));
|
||||
ep.addCustomEventListener(AzureTranscriptionEvents.Error,
|
||||
this._onNuanceError.bind(this, cs, ep, channel));
|
||||
break;
|
||||
case 'deepgram':
|
||||
this.bugname = 'deepgram_transcribe';
|
||||
@@ -202,8 +198,9 @@ class TaskTranscribe extends Task {
|
||||
break;
|
||||
case 'soniox':
|
||||
this.bugname = 'soniox_transcribe';
|
||||
ep.addCustomEventListener(SonioxTranscriptionEvents.Transcription,
|
||||
this._onTranscription.bind(this, cs, ep, channel));
|
||||
ep.addCustomEventListener(SonioxTranscriptionEvents.Transcription, this._onTranscription.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(SonioxTranscriptionEvents.Error,
|
||||
this._onSonioxError.bind(this, cs, ep));
|
||||
break;
|
||||
case 'ibm':
|
||||
this.bugname = 'ibm_transcribe';
|
||||
@@ -213,6 +210,8 @@ class TaskTranscribe extends Task {
|
||||
this._onIbmConnect.bind(this, cs, ep, channel));
|
||||
ep.addCustomEventListener(IbmTranscriptionEvents.ConnectFailure,
|
||||
this._onIbmConnectFailure.bind(this, cs, ep, channel));
|
||||
ep.addCustomEventListener(IbmTranscriptionEvents.Error,
|
||||
this._onIbmError.bind(this, cs, ep, channel));
|
||||
break;
|
||||
|
||||
case 'nvidia':
|
||||
@@ -225,13 +224,14 @@ class TaskTranscribe extends Task {
|
||||
this._onTranscriptionComplete.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(NvidiaTranscriptionEvents.VadDetected,
|
||||
this._onVadDetected.bind(this, cs, ep));
|
||||
ep.addCustomEventListener(NvidiaTranscriptionEvents.Error,
|
||||
this._onNvidiaError.bind(this, cs, ep));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Invalid vendor ${this.vendor}`);
|
||||
}
|
||||
|
||||
/* common handler for all stt engine errors */
|
||||
ep.addCustomEventListener(JambonzTranscriptionEvents.Error, this._onJambonzError.bind(this, cs, ep));
|
||||
await ep.set(opts)
|
||||
.catch((err) => this.logger.info(err, 'Error setting channel variables'));
|
||||
|
||||
@@ -273,15 +273,6 @@ class TaskTranscribe extends Task {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.vendor === 'soniox') {
|
||||
/* compile transcripts into one */
|
||||
this._sonioxTranscripts.push(evt.vendor.finalWords);
|
||||
if (evt.is_final) {
|
||||
evt = this.compileSonioxTranscripts(this._sonioxTranscripts, 1, this.language);
|
||||
this._sonioxTranscripts = [];
|
||||
}
|
||||
}
|
||||
|
||||
if (this.transcriptionHook) {
|
||||
const b3 = this.getTracingPropagation();
|
||||
const httpHeaders = b3 && {b3};
|
||||
@@ -330,6 +321,23 @@ class TaskTranscribe extends Task {
|
||||
this._timer = null;
|
||||
}
|
||||
}
|
||||
_onNuanceError(_cs, _ep, _channel, evt) {
|
||||
const {code, error, details} = evt;
|
||||
if (code === 404 && error === 'No speech') {
|
||||
this.logger.debug({code, error, details}, 'TaskTranscribe:_onNuanceError');
|
||||
return this._resolve('timeout');
|
||||
}
|
||||
this.logger.info({code, error, details}, 'TaskTranscribe:_onNuanceError');
|
||||
if (code === 413 && error === 'Too much speech') {
|
||||
return this._resolve('timeout');
|
||||
}
|
||||
}
|
||||
_onSonioxError(cs, ep, evt) {
|
||||
this.logger.info({evt}, 'TaskTranscribe:_onSonioxError');
|
||||
}
|
||||
_onNvidiaError(cs, ep, evt) {
|
||||
this.logger.info({evt}, 'TaskTranscribe:_onNvidiaError');
|
||||
}
|
||||
_onDeepgramConnect(_cs, _ep) {
|
||||
this.logger.debug('TaskTranscribe:_onDeepgramConnect');
|
||||
}
|
||||
@@ -368,24 +376,6 @@ class TaskTranscribe extends Task {
|
||||
_onIbmError(cs, _ep, _channel, evt) {
|
||||
this.logger.info({evt}, 'TaskTranscribe:_onIbmError');
|
||||
}
|
||||
_onJambonzError(cs, _ep, evt) {
|
||||
this.logger.info({evt}, 'TaskTranscribe:_onJambonzError');
|
||||
const {writeAlerts, AlertType} = cs.srf.locals;
|
||||
|
||||
if (this.vendor === 'nuance') {
|
||||
const {code, error} = evt;
|
||||
if (code === 404 && error === 'No speech') return this._resolve('timeout');
|
||||
if (code === 413 && error === 'Too much speech') return this._resolve('timeout');
|
||||
}
|
||||
this.logger.info({evt}, 'TaskTranscribe:_onJambonzError');
|
||||
writeAlerts({
|
||||
account_sid: cs.accountSid,
|
||||
alert_type: AlertType.STT_FAILURE,
|
||||
message: `Custom speech vendor ${this.vendor} error: ${evt.error}`,
|
||||
vendor: this.vendor,
|
||||
}).catch((err) => this.logger.info({err}, 'Error generating alert for jambonz custom connection failure'));
|
||||
this.notifyError({msg: 'ASR error', details:`Custom speech vendor ${this.vendor} error: ${evt.error}`});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -110,12 +110,6 @@
|
||||
"NoSpeechDetected": "azure_transcribe::no_speech_detected",
|
||||
"VadDetected": "azure_transcribe::vad_detected"
|
||||
},
|
||||
"JambonzTranscriptionEvents": {
|
||||
"Transcription": "jambonz_transcribe::transcription",
|
||||
"ConnectFailure": "jambonz_transcribe::connect_failed",
|
||||
"Connect": "jambonz_transcribe::connect",
|
||||
"Error": "jambonz_transcribe::error"
|
||||
},
|
||||
"ListenEvents": {
|
||||
"Connect": "mod_audio_fork::connect",
|
||||
"ConnectFailure": "mod_audio_fork::connect_failed",
|
||||
|
||||
@@ -66,12 +66,6 @@ const speechMapper = (cred) => {
|
||||
const o = JSON.parse(decrypt(credential));
|
||||
obj.api_key = o.api_key;
|
||||
}
|
||||
else if (obj.vendor.startsWith('custom:')) {
|
||||
const o = JSON.parse(decrypt(credential));
|
||||
obj.auth_token = o.auth_token;
|
||||
obj.custom_stt_url = o.custom_stt_url;
|
||||
obj.custom_tts_url = o.custom_tts_url;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
@@ -89,13 +83,53 @@ module.exports = (logger, srf) => {
|
||||
const [r2] = await pp.query(sqlSpeechCredentials, account_sid);
|
||||
const speech = r2.map(speechMapper);
|
||||
|
||||
/* add service provider creds unless we have that vendor at the account level */
|
||||
const [r3] = await pp.query(sqlSpeechCredentialsForSP, account_sid);
|
||||
r3.forEach((s) => {
|
||||
if (!speech.find((s2) => s2.vendor === s.vendor)) {
|
||||
speech.push(speechMapper(s));
|
||||
/* search at the service provider level if we don't find it at the account level */
|
||||
const haveGoogle = speech.find((s) => s.vendor === 'google');
|
||||
const haveAws = speech.find((s) => s.vendor === 'aws');
|
||||
const haveMicrosoft = speech.find((s) => s.vendor === 'microsoft');
|
||||
const haveWellsaid = speech.find((s) => s.vendor === 'wellsaid');
|
||||
const haveNuance = speech.find((s) => s.vendor === 'nuance');
|
||||
const haveDeepgram = speech.find((s) => s.vendor === 'deepgram');
|
||||
const haveSoniox = speech.find((s) => s.vendor === 'soniox');
|
||||
const haveIbm = speech.find((s) => s.vendor === 'ibm');
|
||||
if (!haveGoogle || !haveAws || !haveMicrosoft || !haveWellsaid ||
|
||||
!haveNuance || !haveIbm || !haveDeepgram || !haveSoniox) {
|
||||
const [r3] = await pp.query(sqlSpeechCredentialsForSP, account_sid);
|
||||
if (r3.length) {
|
||||
if (!haveGoogle) {
|
||||
const google = r3.find((s) => s.vendor === 'google');
|
||||
if (google) speech.push(speechMapper(google));
|
||||
}
|
||||
if (!haveAws) {
|
||||
const aws = r3.find((s) => s.vendor === 'aws');
|
||||
if (aws) speech.push(speechMapper(aws));
|
||||
}
|
||||
if (!haveMicrosoft) {
|
||||
const ms = r3.find((s) => s.vendor === 'microsoft');
|
||||
if (ms) speech.push(speechMapper(ms));
|
||||
}
|
||||
if (!haveWellsaid) {
|
||||
const wellsaid = r3.find((s) => s.vendor === 'wellsaid');
|
||||
if (wellsaid) speech.push(speechMapper(wellsaid));
|
||||
}
|
||||
if (!haveNuance) {
|
||||
const nuance = r3.find((s) => s.vendor === 'nuance');
|
||||
if (nuance) speech.push(speechMapper(nuance));
|
||||
}
|
||||
if (!haveDeepgram) {
|
||||
const deepgram = r3.find((s) => s.vendor === 'deepgram');
|
||||
if (deepgram) speech.push(speechMapper(deepgram));
|
||||
}
|
||||
if (!haveSoniox) {
|
||||
const soniox = r3.find((s) => s.vendor === 'soniox');
|
||||
if (soniox) speech.push(speechMapper(soniox));
|
||||
}
|
||||
if (!haveIbm) {
|
||||
const ibm = r3.find((s) => s.vendor === 'ibm');
|
||||
if (ibm) speech.push(speechMapper(ibm));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...r[0],
|
||||
|
||||
@@ -138,6 +138,7 @@ function installSrfLocals(srf, logger) {
|
||||
retrieveCall,
|
||||
listCalls,
|
||||
deleteCall,
|
||||
synthAudio,
|
||||
createHash,
|
||||
retrieveHash,
|
||||
deleteKey,
|
||||
@@ -150,17 +151,11 @@ function installSrfLocals(srf, logger) {
|
||||
pushBack,
|
||||
popFront,
|
||||
removeFromList,
|
||||
getListPosition,
|
||||
lengthOfList,
|
||||
} = require('@jambonz/realtimedb-helpers')({
|
||||
host: process.env.JAMBONES_REDIS_HOST,
|
||||
port: process.env.JAMBONES_REDIS_PORT || 6379
|
||||
}, logger, tracer);
|
||||
const {
|
||||
synthAudio,
|
||||
getListPosition,
|
||||
getNuanceAccessToken,
|
||||
getIbmAccessToken,
|
||||
} = require('@jambonz/speech-utils')({
|
||||
} = require('@jambonz/realtimedb-helpers')({
|
||||
host: process.env.JAMBONES_REDIS_HOST,
|
||||
port: process.env.JAMBONES_REDIS_PORT || 6379
|
||||
}, logger, tracer);
|
||||
|
||||
@@ -6,8 +6,7 @@ const {
|
||||
NuanceTranscriptionEvents,
|
||||
DeepgramTranscriptionEvents,
|
||||
SonioxTranscriptionEvents,
|
||||
NvidiaTranscriptionEvents,
|
||||
JambonzTranscriptionEvents
|
||||
NvidiaTranscriptionEvents
|
||||
} = require('./constants');
|
||||
|
||||
const stickyVars = {
|
||||
@@ -224,15 +223,6 @@ const normalizeGoogle = (evt, channel, language) => {
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeCustom = (evt, channel, language) => {
|
||||
return {
|
||||
language_code: language,
|
||||
channel_tag: channel,
|
||||
is_final: evt.is_final,
|
||||
alternatives: [evt.alternatives[0]]
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeNuance = (evt, channel, language) => {
|
||||
const copy = JSON.parse(JSON.stringify(evt));
|
||||
return {
|
||||
@@ -312,9 +302,6 @@ module.exports = (logger) => {
|
||||
case 'soniox':
|
||||
return normalizeSoniox(evt, channel, language);
|
||||
default:
|
||||
if (vendor.startsWith('custom:')) {
|
||||
return normalizeCustom(evt, channel, language);
|
||||
}
|
||||
logger.error(`Unknown vendor ${vendor}`);
|
||||
return evt;
|
||||
}
|
||||
@@ -324,7 +311,6 @@ module.exports = (logger) => {
|
||||
let opts = {};
|
||||
const {enable, voiceMs = 0, mode = -1} = rOpts.vad || {};
|
||||
const vad = {enable, voiceMs, mode};
|
||||
const vendor = rOpts.vendor;
|
||||
|
||||
/* voice activity detection works across vendors */
|
||||
opts = {
|
||||
@@ -334,7 +320,7 @@ module.exports = (logger) => {
|
||||
...(vad.enable && typeof vad.mode === 'number' && {RECOGNIZER_VAD_MODE: vad.mode}),
|
||||
};
|
||||
|
||||
if ('google' === vendor) {
|
||||
if ('google' === rOpts.vendor) {
|
||||
opts = {
|
||||
...opts,
|
||||
...(sttCredentials &&
|
||||
@@ -386,7 +372,7 @@ module.exports = (logger) => {
|
||||
{GOOGLE_SPEECH_METADATA_INDUSTRY_NAICS_CODE: rOpts.naicsCode}),
|
||||
};
|
||||
}
|
||||
else if (['aws', 'polly'].includes(vendor)) {
|
||||
else if (['aws', 'polly'].includes(rOpts.vendor)) {
|
||||
opts = {
|
||||
...opts,
|
||||
...(rOpts.vocabularyName && {AWS_VOCABULARY_NAME: rOpts.vocabularyName}),
|
||||
@@ -399,7 +385,7 @@ module.exports = (logger) => {
|
||||
}),
|
||||
};
|
||||
}
|
||||
else if ('microsoft' === vendor) {
|
||||
else if ('microsoft' === rOpts.vendor) {
|
||||
opts = {
|
||||
...opts,
|
||||
...(rOpts.hints.length > 0 && typeof rOpts.hints[0] === 'string' &&
|
||||
@@ -424,7 +410,7 @@ module.exports = (logger) => {
|
||||
{AZURE_SERVICE_ENDPOINT_ID: sttCredentials.custom_stt_endpoint})
|
||||
};
|
||||
}
|
||||
else if ('nuance' === vendor) {
|
||||
else if ('nuance' === rOpts.vendor) {
|
||||
/**
|
||||
* Note: all nuance options are in recognizer.nuanceOptions, should migrate
|
||||
* other vendor settings to similar nested structure
|
||||
@@ -475,7 +461,7 @@ module.exports = (logger) => {
|
||||
{NUANCE_RESOURCES: JSON.stringify(nuanceOptions.resources)},
|
||||
};
|
||||
}
|
||||
else if ('deepgram' === vendor) {
|
||||
else if ('deepgram' === rOpts.vendor) {
|
||||
const {deepgramOptions = {}} = rOpts;
|
||||
opts = {
|
||||
...opts,
|
||||
@@ -519,7 +505,7 @@ module.exports = (logger) => {
|
||||
{DEEPGRAM_SPEECH_TAG: deepgramOptions.tag}
|
||||
};
|
||||
}
|
||||
else if ('soniox' === vendor) {
|
||||
else if ('soniox' === rOpts.vendor) {
|
||||
const {sonioxOptions = {}} = rOpts;
|
||||
const {storage = {}} = sonioxOptions;
|
||||
opts = {
|
||||
@@ -542,7 +528,7 @@ module.exports = (logger) => {
|
||||
...(storage?.id && storage?.disableSearch && {SONIOX_STORAGE_DISABLE_SEARCH: 1})
|
||||
};
|
||||
}
|
||||
else if ('ibm' === vendor) {
|
||||
else if ('ibm' === rOpts.vendor) {
|
||||
const {ibmOptions = {}} = rOpts;
|
||||
opts = {
|
||||
...opts,
|
||||
@@ -566,7 +552,7 @@ module.exports = (logger) => {
|
||||
{IBM_SPEECH_WATSON_LEARNING_OPT_OUT: ibmOptions.watsonLearningOptOut}
|
||||
};
|
||||
}
|
||||
else if ('nvidia' === vendor) {
|
||||
else if ('nvidia' === rOpts.vendor) {
|
||||
const {nvidiaOptions = {}} = rOpts;
|
||||
opts = {
|
||||
...opts,
|
||||
@@ -595,29 +581,11 @@ module.exports = (logger) => {
|
||||
{NVIDIA_CUSTOM_CONFIGURATION: JSON.stringify(nvidiaOptions.customConfiguration)}),
|
||||
};
|
||||
}
|
||||
else if (vendor.startsWith('custom:')) {
|
||||
let {options = {}} = rOpts;
|
||||
const {auth_token, custom_stt_url} = sttCredentials;
|
||||
options = {
|
||||
...options,
|
||||
...(rOpts.hints.length > 0 && typeof rOpts.hints[0] === 'string' &&
|
||||
{hints: rOpts.hints}),
|
||||
...(rOpts.hints.length > 0 && typeof rOpts.hints[0] === 'object' &&
|
||||
{hints: JSON.stringify(rOpts.hints)}),
|
||||
...(typeof rOpts.hintsBoost === 'number' && {hintsBoost: rOpts.hintsBoost})
|
||||
};
|
||||
|
||||
opts = {
|
||||
...opts,
|
||||
JAMBONZ_STT_API_KEY: auth_token,
|
||||
JAMBONZ_STT_URL: custom_stt_url,
|
||||
...(Object.keys(options).length > 0 && {JAMBONZ_STT_OPTIONS: JSON.stringify(options)}),
|
||||
};
|
||||
}
|
||||
|
||||
(stickyVars[vendor] || []).forEach((key) => {
|
||||
stickyVars[rOpts.vendor].forEach((key) => {
|
||||
if (!opts[key]) opts[key] = '';
|
||||
});
|
||||
//logger.debug({opts}, 'recognizer channel vars');
|
||||
return opts;
|
||||
};
|
||||
|
||||
@@ -636,6 +604,7 @@ module.exports = (logger) => {
|
||||
ep.removeCustomEventListener(NuanceTranscriptionEvents.Transcription);
|
||||
ep.removeCustomEventListener(NuanceTranscriptionEvents.TranscriptionComplete);
|
||||
ep.removeCustomEventListener(NuanceTranscriptionEvents.StartOfSpeech);
|
||||
ep.removeCustomEventListener(NuanceTranscriptionEvents.Error);
|
||||
ep.removeCustomEventListener(NuanceTranscriptionEvents.VadDetected);
|
||||
|
||||
ep.removeCustomEventListener(DeepgramTranscriptionEvents.Transcription);
|
||||
@@ -643,17 +612,13 @@ module.exports = (logger) => {
|
||||
ep.removeCustomEventListener(DeepgramTranscriptionEvents.ConnectFailure);
|
||||
|
||||
ep.removeCustomEventListener(SonioxTranscriptionEvents.Transcription);
|
||||
ep.removeCustomEventListener(SonioxTranscriptionEvents.Error);
|
||||
|
||||
ep.removeCustomEventListener(NvidiaTranscriptionEvents.Transcription);
|
||||
ep.removeCustomEventListener(NvidiaTranscriptionEvents.TranscriptionComplete);
|
||||
ep.removeCustomEventListener(NvidiaTranscriptionEvents.StartOfSpeech);
|
||||
ep.removeCustomEventListener(NvidiaTranscriptionEvents.Error);
|
||||
ep.removeCustomEventListener(NvidiaTranscriptionEvents.VadDetected);
|
||||
|
||||
ep.removeCustomEventListener(JambonzTranscriptionEvents.Transcription);
|
||||
ep.removeCustomEventListener(JambonzTranscriptionEvents.Connect);
|
||||
ep.removeCustomEventListener(JambonzTranscriptionEvents.ConnectFailure);
|
||||
|
||||
ep.removeCustomEventListener(JambonzTranscriptionEvents.Error);
|
||||
};
|
||||
|
||||
const setSpeechCredentialsAtRuntime = (recognizer) => {
|
||||
|
||||
1971
package-lock.json
generated
1971
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -26,8 +26,7 @@
|
||||
"dependencies": {
|
||||
"@jambonz/db-helpers": "^0.7.4",
|
||||
"@jambonz/http-health-check": "^0.0.1",
|
||||
"@jambonz/realtimedb-helpers": "^0.7.0",
|
||||
"@jambonz/speech-utils": "^0.0.2",
|
||||
"@jambonz/realtimedb-helpers": "^0.6.5",
|
||||
"@jambonz/stats-collector": "^0.1.6",
|
||||
"@jambonz/time-series": "^0.2.5",
|
||||
"@jambonz/verb-specifications": "^0.0.11",
|
||||
@@ -44,7 +43,7 @@
|
||||
"bent": "^7.3.12",
|
||||
"debug": "^4.3.4",
|
||||
"deepcopy": "^2.1.0",
|
||||
"drachtio-fsmrf": "^3.0.20",
|
||||
"drachtio-fsmrf": "^3.0.19",
|
||||
"drachtio-srf": "^4.5.23",
|
||||
"express": "^4.18.2",
|
||||
"ip": "^1.1.8",
|
||||
|
||||
Reference in New Issue
Block a user