Compare commits

..

2 Commits

Author SHA1 Message Date
Quan HL
3b72c8316c fix: sip rect issue on re-invite 2023-04-05 06:28:32 +07:00
Quan HL
4271a3fe3d fix: update speech utils version 2023-04-01 13:41:37 +07:00
10 changed files with 39 additions and 83 deletions

View File

@@ -104,7 +104,7 @@ router.post('/', async(req, res) => {
proxy: `sip:${sbcAddress}`,
localSdp: ep.local.sdp
});
if (target.auth) opts.auth = target.auth;
if (target.auth) opts.auth = this.target.auth;
/**

View File

@@ -46,16 +46,7 @@ module.exports = function(srf, logger) {
}
if (req.has('X-Authenticated-User')) req.locals.originatingUser = req.get('X-Authenticated-User');
if (req.has('X-MS-Teams-Tenant-FQDN')) req.locals.msTeamsTenant = req.get('X-MS-Teams-Tenant-FQDN');
if (req.has('X-Cisco-Recording-Participant')) {
const ciscoParticipants = req.get('X-Cisco-Recording-Participant');
const regex = /sip:[\d]+@[\d]+\.[\d]+\.[\d]+\.[\d]+/g;
const sipURIs = ciscoParticipants.match(regex);
logger.info(`X-Cisco-Recording-Participant : ${sipURIs} `);
if (sipURIs && sipURIs.length > 0) {
req.locals.calledNumber = sipURIs[0];
req.locals.callingNumber = sipURIs[1];
}
}
next();
}
@@ -103,10 +94,8 @@ module.exports = function(srf, logger) {
.find((p) => p.type === 'application/sdp')
.content;
const {sdp1, sdp2, ...metadata} = await parseSiprecPayload(req, logger);
if (!req.locals.calledNumber && !req.locals.calledNumber) {
req.locals.calledNumber = metadata.caller.number;
req.locals.callingNumber = metadata.callee.number;
}
req.locals.calledNumber = metadata.caller.number;
req.locals.callingNumber = metadata.callee.number;
req.locals = {
...req.locals,
siprec: {

View File

@@ -33,23 +33,6 @@ class CallInfo {
this.callStatus = CallStatus.Trying;
this.originatingSipIp = req.get('X-Forwarded-For');
this.originatingSipTrunkName = req.get('X-Originating-Carrier');
const {siprec} = req.locals;
if (siprec) {
const caller = parseUri(req.locals.callingNumber);
const callee = parseUri(req.locals.calledNumber);
this.participants = [
{
participant: 'caller',
uriUser: caller.user,
uriHost: caller.host
},
{
participant: 'callee',
uriUser: callee.user,
uriHost: callee.host
}
];
}
}
else if (opts.parentCallInfo) {
// outbound call that is a child of an existing call

View File

@@ -19,7 +19,6 @@ class SipRecCallSession extends InboundCallSession {
async _onReinvite(req, res) {
try {
this.logger.info(req.payload, 'SipRec Re-INVITE payload');
const {sdp1: reSdp1, sdp2: reSdp2, metadata: reMetadata} = await parseSiprecPayload(req, this.logger);
this.sdp1 = reSdp1;
this.sdp2 = reSdp2;
@@ -32,10 +31,10 @@ class SipRecCallSession extends InboundCallSession {
const newSdp2 = await this.ep2.modify(remoteSdp);
const combinedSdp = await createSipRecPayload(newSdp1, newSdp2, this.logger);
res.send(200, {body: combinedSdp});
this.logger.info({offer: req.body, answer: combinedSdp}, 'SipRec handling reINVITE');
this.logger.info({offer: req.body, answer: combinedSdp}, 'handling reINVITE');
}
else {
this.logger.info('got SipRec reINVITE but no endpoint and media has not been released');
this.logger.info('got reINVITE but no endpoint and media has not been released');
res.send(488);
}
} catch (err) {

View File

@@ -47,16 +47,8 @@ const parseSiprecPayload = (req, logger) => {
}
}
if (!meta && sdp) {
const arr = /^([^]+)(m=[^]+?)(m=[^]+?)$/.exec(sdp);
opts.sdp1 = `${arr[1]}${arr[2]}`;
opts.sdp2 = `${arr[1]}${arr[3]}\r\n`;
opts.sessionId = uuidv4();
logger.info({ payload: req.payload }, 'SIPREC payload with no metadata (e.g. Cisco NBR)');
resolve(opts);
} else if (!sdp || !meta) {
logger.info({ payload: req.payload }, 'invalid SIPREC payload');
if (!sdp || !meta) {
logger.info({payload: req.payload}, 'invalid SIPREC payload');
return reject(new Error('expected multipart SIPREC body'));
}
@@ -250,8 +242,7 @@ const createSipRecPayload = (sdp1, sdp2, logger) => {
.replace(/a=sendonly\r\n/g, '')
.replace(/a=direction:both\r\n/g, '');
*/
return combinedSdp.replace(/sendrecv/g, 'recvonly');
return combinedSdp;
};
module.exports = { parseSiprecPayload, createSipRecPayload } ;

View File

@@ -336,7 +336,8 @@ module.exports = (logger) => {
};
if ('google' === vendor) {
const model = task.name === TaskName.Gather ? 'command_and_search' : 'latest_long';
let model = 'phone_call';
if (rOpts.altLanguages.length > 0) model = task.name === TaskName.Gather ? 'command_and_search' : 'latest_long';
opts = {
...opts,
...(sttCredentials && {GOOGLE_APPLICATION_CREDENTIALS: JSON.stringify(sttCredentials.credentials)}),
@@ -351,7 +352,7 @@ module.exports = (logger) => {
{GOOGLE_SPEECH_SPEAKER_DIARIZATION_MIN_SPEAKER_COUNT: rOpts.diarizationMinSpeakers}),
...(rOpts.diarization && rOpts.diarizationMaxSpeakers > 0 &&
{GOOGLE_SPEECH_SPEAKER_DIARIZATION_MAX_SPEAKER_COUNT: rOpts.diarizationMaxSpeakers}),
...(rOpts.enhancedModel !== false && {GOOGLE_SPEECH_USE_ENHANCED: 1}),
...(rOpts.enhancedModel && {GOOGLE_SPEECH_USE_ENHANCED: 1}),
...(rOpts.profanityFilter === false && {GOOGLE_SPEECH_PROFANITY_FILTER: 0}),
...(rOpts.punctuation === false && {GOOGLE_SPEECH_ENABLE_AUTOMATIC_PUNCTUATION: 0}),
...(rOpts.words == false && {GOOGLE_SPEECH_ENABLE_WORD_TIME_OFFSETS: 0}),

28
package-lock.json generated
View File

@@ -12,8 +12,8 @@
"@jambonz/db-helpers": "^0.7.4",
"@jambonz/http-health-check": "^0.0.1",
"@jambonz/realtimedb-helpers": "^0.7.0",
"@jambonz/speech-utils": "^0.0.12",
"@jambonz/stats-collector": "^0.1.8",
"@jambonz/speech-utils": "^0.0.9",
"@jambonz/stats-collector": "^0.1.6",
"@jambonz/time-series": "^0.2.5",
"@jambonz/verb-specifications": "^0.0.11",
"@opentelemetry/api": "^1.4.0",
@@ -1627,9 +1627,9 @@
}
},
"node_modules/@jambonz/speech-utils": {
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/@jambonz/speech-utils/-/speech-utils-0.0.12.tgz",
"integrity": "sha512-0S5HlFmVLGw6AA7R1HBE08tgCjT4P7szqsMioDKVrrTA84/qqqb4Vv70zc0F63lM2qUU5OXUnA1RJUcVpo9imQ==",
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/@jambonz/speech-utils/-/speech-utils-0.0.9.tgz",
"integrity": "sha512-YxhDpQvmDkLLTg6XguIrod6jm55RiuTCAiW+MDmx73Rm8FLDibxxoM7TKLR5Hl2Pbfv+j7eS1XraBbJO/bbxTQ==",
"dependencies": {
"@aws-sdk/client-polly": "^3.303.0",
"@google-cloud/text-to-speech": "^4.2.1",
@@ -1646,9 +1646,9 @@
}
},
"node_modules/@jambonz/stats-collector": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/@jambonz/stats-collector/-/stats-collector-0.1.8.tgz",
"integrity": "sha512-PadBKTmcphU7bZI7pVr4awhoIi+DMLw7An6AGE0GGsLCn2x0IGnxr9k47gI4Bk3OaSF6N7RyVLEAMkJfr24l8Q==",
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@jambonz/stats-collector/-/stats-collector-0.1.6.tgz",
"integrity": "sha512-Qk+kpeb2wravpj3OYPC4N3ML1qoAzARNLfKGZtJ05PTAtfWoZMPnyfPAM9EJHIiVfs2Lec3CXDjEpHna0mc9EA==",
"dependencies": {
"debug": "^4.3.2",
"hot-shots": "^8.5.0"
@@ -9962,9 +9962,9 @@
}
},
"@jambonz/speech-utils": {
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/@jambonz/speech-utils/-/speech-utils-0.0.12.tgz",
"integrity": "sha512-0S5HlFmVLGw6AA7R1HBE08tgCjT4P7szqsMioDKVrrTA84/qqqb4Vv70zc0F63lM2qUU5OXUnA1RJUcVpo9imQ==",
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/@jambonz/speech-utils/-/speech-utils-0.0.9.tgz",
"integrity": "sha512-YxhDpQvmDkLLTg6XguIrod6jm55RiuTCAiW+MDmx73Rm8FLDibxxoM7TKLR5Hl2Pbfv+j7eS1XraBbJO/bbxTQ==",
"requires": {
"@aws-sdk/client-polly": "^3.303.0",
"@google-cloud/text-to-speech": "^4.2.1",
@@ -9981,9 +9981,9 @@
}
},
"@jambonz/stats-collector": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/@jambonz/stats-collector/-/stats-collector-0.1.8.tgz",
"integrity": "sha512-PadBKTmcphU7bZI7pVr4awhoIi+DMLw7An6AGE0GGsLCn2x0IGnxr9k47gI4Bk3OaSF6N7RyVLEAMkJfr24l8Q==",
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@jambonz/stats-collector/-/stats-collector-0.1.6.tgz",
"integrity": "sha512-Qk+kpeb2wravpj3OYPC4N3ML1qoAzARNLfKGZtJ05PTAtfWoZMPnyfPAM9EJHIiVfs2Lec3CXDjEpHna0mc9EA==",
"requires": {
"debug": "^4.3.2",
"hot-shots": "^8.5.0"

View File

@@ -27,8 +27,8 @@
"@jambonz/db-helpers": "^0.7.4",
"@jambonz/http-health-check": "^0.0.1",
"@jambonz/realtimedb-helpers": "^0.7.0",
"@jambonz/speech-utils": "^0.0.12",
"@jambonz/stats-collector": "^0.1.8",
"@jambonz/speech-utils": "^0.0.11",
"@jambonz/stats-collector": "^0.1.6",
"@jambonz/time-series": "^0.2.5",
"@jambonz/verb-specifications": "^0.0.11",
"@opentelemetry/api": "^1.4.0",

View File

@@ -18,38 +18,30 @@ test('creating schema', (t) => {
if (err) return t.end(err);
t.pass('schema and test data successfully created');
const sql = [];
if (process.env.GCP_JSON_KEY) {
if (process.env.GCP_JSON_KEY && process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {
const google_credential = encrypt(process.env.GCP_JSON_KEY);
t.pass('adding google credentials');
sql.push(`UPDATE speech_credentials SET credential='${google_credential}' WHERE vendor='google';`);
}
if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {
const aws_credential = encrypt(JSON.stringify({
access_key_id: process.env.AWS_ACCESS_KEY_ID,
secret_access_key: process.env.AWS_SECRET_ACCESS_KEY,
aws_region: process.env.AWS_REGION
}));
t.pass('adding aws credentials');
sql.push(`UPDATE speech_credentials SET credential='${aws_credential}' WHERE vendor='aws';`);
}
if (process.env.MICROSOFT_REGION && process.env.MICROSOFT_API_KEY) {
const microsoft_credential = encrypt(JSON.stringify({
region: process.env.MICROSOFT_REGION,
api_key: process.env.MICROSOFT_API_KEY
region: process.env.MICROSOFT_REGION || 'useast',
api_key: process.env.MICROSOFT_API_KEY || '1234567890'
}));
t.pass('adding microsoft credentials');
sql.push(`UPDATE speech_credentials SET credential='${microsoft_credential}' WHERE vendor='microsoft';`);
}
if (sql.length > 0) {
const cmd = `
UPDATE speech_credentials SET credential='${google_credential}' WHERE vendor='google';
UPDATE speech_credentials SET credential='${aws_credential}' WHERE vendor='aws';
UPDATE speech_credentials SET credential='${microsoft_credential}' WHERE vendor='microsoft';
`;
const path = `${__dirname}/.creds.sql`;
const cmd = sql.join('\n');
fs.writeFileSync(path, sql.join('\n'));
fs.writeFileSync(path, cmd);
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 -D jambones_test < ${path}`, (err, stdout, stderr) => {
console.log(stdout);
console.log(stderr);
if (err) return t.end(err);
fs.unlinkSync(path)
fs.writeFileSync(`${__dirname}/credentials/gcp.json`, process.env.GCP_JSON_KEY);
t.pass('set account-level speech credentials');
t.end();
});

View File

@@ -5,6 +5,7 @@ test('dropping jambones_test database', (t) => {
exec(`mysql -h 127.0.0.1 -u root --protocol=tcp --port=3360 < ${__dirname}/db/remove_test_db.sql`, (err, stdout, stderr) => {
if (err) return t.end(err);
t.pass('database successfully dropped');
fs.unlinkSync(`${__dirname}/credentials/gcp.json`);
t.end();
});
});