mirror of
https://github.com/jambonz/jambonz-api-server.git
synced 2026-01-25 02:08:24 +00:00
Merge branch 'main' into feature/pagination
This commit is contained in:
@@ -752,7 +752,7 @@ router.get('/:sid/test', async(req, res) => {
|
||||
*/
|
||||
|
||||
router.get('/speech/supportedLanguagesAndVoices', async(req, res) => {
|
||||
const logger = req.app.locals.logger;
|
||||
const {logger, getTtsVoices} = req.app.locals;
|
||||
try {
|
||||
const {vendor, label} = req.query;
|
||||
if (!vendor) {
|
||||
@@ -767,7 +767,7 @@ router.get('/speech/supportedLanguagesAndVoices', async(req, res) => {
|
||||
const tmp = credentials && credentials.length > 0 ? credentials[0] : null;
|
||||
const cred = tmp ? JSON.parse(decrypt(tmp.credential)) : null;
|
||||
try {
|
||||
const data = await getLanguagesAndVoicesForVendor(logger, vendor, cred);
|
||||
const data = await getLanguagesAndVoicesForVendor(logger, vendor, cred, getTtsVoices);
|
||||
res.status(200).json(data);
|
||||
} catch (err) {
|
||||
throw new DbErrorUnprocessableRequest(err.message);
|
||||
|
||||
@@ -382,11 +382,35 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GeneralError'
|
||||
/login:
|
||||
post:
|
||||
tags:
|
||||
- Authentication
|
||||
summary: login and retrieve a JWT
|
||||
operationId: login
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Login'
|
||||
responses:
|
||||
200:
|
||||
description: user logged in
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SuccessfulLogin'
|
||||
500:
|
||||
description: system error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GeneralError'
|
||||
/logout:
|
||||
post:
|
||||
tags:
|
||||
- Authentication
|
||||
summary: log out and deactivate jwt
|
||||
summary: log out and deactivate the JWT
|
||||
operationId: logoutUser
|
||||
responses:
|
||||
204:
|
||||
@@ -584,10 +608,9 @@ paths:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type:
|
||||
array
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Users'
|
||||
$ref: '#/components/schemas/UserList'
|
||||
403:
|
||||
description: unauthorized
|
||||
500:
|
||||
@@ -610,27 +633,13 @@ paths:
|
||||
- Users
|
||||
summary: retrieve user information
|
||||
operationId: getUser
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
is_active:
|
||||
type: boolean
|
||||
force_change:
|
||||
type: boolean
|
||||
scope:
|
||||
type: string
|
||||
permissions:
|
||||
type: array
|
||||
responses:
|
||||
204:
|
||||
200:
|
||||
description: user information
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserProfile'
|
||||
403:
|
||||
description: user information
|
||||
content:
|
||||
@@ -674,6 +683,8 @@ paths:
|
||||
type: string
|
||||
permissions:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
responses:
|
||||
204:
|
||||
description: user updated
|
||||
@@ -712,6 +723,8 @@ paths:
|
||||
type: string
|
||||
permissions:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
old_password:
|
||||
type: string
|
||||
description: existing password, which is to be replaced
|
||||
@@ -998,7 +1011,7 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GeneralError'
|
||||
/AccountTest/:ServiceProviderSid:
|
||||
/AccountTest/{ServiceProviderSid}:
|
||||
parameters:
|
||||
- name: ServiceProviderSid
|
||||
in: path
|
||||
@@ -1971,7 +1984,7 @@ paths:
|
||||
tags:
|
||||
- Service Providers
|
||||
summary: add a VoiPCarrier to a service provider based on PredefinedCarrier template
|
||||
operationId: createVoipCarrierFromTemplate
|
||||
operationId: createVoipCarrierFromTemplateBySP
|
||||
responses:
|
||||
201:
|
||||
description: voip carrier successfully created
|
||||
@@ -2079,6 +2092,12 @@ paths:
|
||||
summary: get supported languages, voices and models
|
||||
operationId: supportedLanguagesAndVoices
|
||||
parameters:
|
||||
- name: ServiceProviderSid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: vendor
|
||||
in: query
|
||||
required: true
|
||||
@@ -2920,7 +2939,7 @@ paths:
|
||||
tags:
|
||||
- Accounts
|
||||
summary: get a specific speech credential
|
||||
operationId: getSpeechCredential
|
||||
operationId: getSpeechCredentialByAccount
|
||||
responses:
|
||||
200:
|
||||
description: retrieve speech credentials for a specified account
|
||||
@@ -2934,7 +2953,7 @@ paths:
|
||||
tags:
|
||||
- Accounts
|
||||
summary: update a speech credential
|
||||
operationId: updateSpeechCredential
|
||||
operationId: updateSpeechCredentialByAccount
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
@@ -2955,7 +2974,7 @@ paths:
|
||||
tags:
|
||||
- Accounts
|
||||
summary: delete a speech credential
|
||||
operationId: deleteSpeechCredential
|
||||
operationId: deleteSpeechCredentialByAccount
|
||||
responses:
|
||||
204:
|
||||
description: credential successfully deleted
|
||||
@@ -2966,8 +2985,14 @@ paths:
|
||||
tags:
|
||||
- Accounts
|
||||
summary: get supported languages, voices and models
|
||||
operationId: supportedLanguagesAndVoices
|
||||
operationId: supportedLanguagesAndVoicesByAccount
|
||||
parameters:
|
||||
- name: AccountSid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: vendor
|
||||
in: query
|
||||
required: true
|
||||
@@ -2995,7 +3020,7 @@ paths:
|
||||
tags:
|
||||
- Accounts
|
||||
summary: test a speech credential
|
||||
operationId: testSpeechCredential
|
||||
operationId: testSpeechCredentialByAccount
|
||||
parameters:
|
||||
- name: AccountSid
|
||||
in: path
|
||||
@@ -3241,7 +3266,7 @@ paths:
|
||||
tags:
|
||||
- Service Providers
|
||||
summary: retrieve pcap for a call
|
||||
operationId: getRecentCallTrace
|
||||
operationId: getRecentCallTraceBySP
|
||||
responses:
|
||||
200:
|
||||
description: retrieve sip trace data
|
||||
@@ -3327,7 +3352,7 @@ paths:
|
||||
tags:
|
||||
- Service Providers
|
||||
summary: retrieve recent calls for an account
|
||||
operationId: listRecentCalls
|
||||
operationId: listRecentCallsBySP
|
||||
responses:
|
||||
200:
|
||||
description: retrieve recent call records for a specified account
|
||||
@@ -3428,7 +3453,7 @@ paths:
|
||||
tags:
|
||||
- Service Providers
|
||||
summary: retrieve sip trace detail for a call
|
||||
operationId: getRecentCallTrace
|
||||
operationId: getRecentCallTraceByCallId
|
||||
responses:
|
||||
200:
|
||||
description: retrieve sip trace data
|
||||
@@ -3455,7 +3480,7 @@ paths:
|
||||
tags:
|
||||
- Accounts
|
||||
summary: retrieve pcap for a call
|
||||
operationId: getRecentCallTrace
|
||||
operationId: getRecentCallTraceByAccount
|
||||
responses:
|
||||
200:
|
||||
description: retrieve sip trace data
|
||||
@@ -3641,7 +3666,7 @@ paths:
|
||||
tags:
|
||||
- Accounts
|
||||
summary: retrieve alerts for an account
|
||||
operationId: listAlerts
|
||||
operationId: listAlertsByAccount
|
||||
responses:
|
||||
200:
|
||||
description: retrieve alerts for a specified account
|
||||
@@ -4240,7 +4265,7 @@ paths:
|
||||
tags:
|
||||
- Accounts
|
||||
summary: retrieve online sip users for an account
|
||||
operationId: listQueues
|
||||
operationId: listRegisteredSipUsers
|
||||
responses:
|
||||
200:
|
||||
description: retrieve online sip users for an account
|
||||
@@ -4254,7 +4279,7 @@ paths:
|
||||
tags:
|
||||
- Accounts
|
||||
summary: retrieve online sip users for an account by list of sip username
|
||||
operationId: listRegisteredSipUsers
|
||||
operationId: listRegisteredSipUsersByUsername
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
@@ -4273,6 +4298,12 @@ paths:
|
||||
$ref: '#/components/schemas/RegisteredClient'
|
||||
/Accounts/{AccountSid}/RegisteredSipUsers/{Client}:
|
||||
parameters:
|
||||
- name: AccountSid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: Client
|
||||
in: path
|
||||
required: true
|
||||
@@ -4293,6 +4324,13 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RegisteredClient'
|
||||
/Accounts/{AccountSid}/TtsCache/Synthesize:
|
||||
parameters:
|
||||
- name: AccountSid
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
post:
|
||||
tags:
|
||||
- Accounts
|
||||
@@ -5031,17 +5069,32 @@ components:
|
||||
scheme: bearer
|
||||
bearerFormat: token
|
||||
schemas:
|
||||
SuccessfulLogin:
|
||||
type: object
|
||||
required:
|
||||
- username
|
||||
- password
|
||||
properties:
|
||||
token:
|
||||
type: string
|
||||
user_sid:
|
||||
type: string
|
||||
scope:
|
||||
type: string
|
||||
force_change:
|
||||
type: boolean
|
||||
|
||||
Login:
|
||||
type: object
|
||||
properties:
|
||||
user_sid:
|
||||
username:
|
||||
type: string
|
||||
api_token:
|
||||
type: string
|
||||
change_password:
|
||||
type: boolean
|
||||
password:
|
||||
type: string
|
||||
required:
|
||||
- user_sid
|
||||
- username
|
||||
- password
|
||||
|
||||
SuccessfulApiKeyAdd:
|
||||
type: object
|
||||
required:
|
||||
@@ -6096,8 +6149,23 @@ components:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TtsModel'
|
||||
|
||||
|
||||
UserList:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
email:
|
||||
type: string
|
||||
is_active:
|
||||
type: boolean
|
||||
force_change:
|
||||
type: boolean
|
||||
scope:
|
||||
type: string
|
||||
permissions:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
security:
|
||||
- bearerAuth: []
|
||||
@@ -464,49 +464,90 @@ function decryptCredential(obj, credential, logger, isObscureKey = true) {
|
||||
]
|
||||
}
|
||||
*/
|
||||
async function getLanguagesAndVoicesForVendor(logger, vendor, credential) {
|
||||
async function getLanguagesAndVoicesForVendor(logger, vendor, credential, getTtsVoices) {
|
||||
switch (vendor) {
|
||||
case 'google':
|
||||
return await getLanguagesVoicesForGoogle(credential);
|
||||
return await getLanguagesVoicesForGoogle(credential, getTtsVoices, logger);
|
||||
case 'aws':
|
||||
return await getLanguagesVoicesForAws(credential);
|
||||
return await getLanguagesVoicesForAws(credential, getTtsVoices, logger);
|
||||
case 'microsoft':
|
||||
return await getLanguagesVoicesForMicrosoft(credential);
|
||||
return await getLanguagesVoicesForMicrosoft(credential, getTtsVoices, logger);
|
||||
case 'wellsaid':
|
||||
return await getLanguagesVoicesForWellsaid(credential);
|
||||
return await getLanguagesVoicesForWellsaid(credential, getTtsVoices, logger);
|
||||
case 'nuance':
|
||||
return await getLanguagesVoicesForNuane(credential);
|
||||
return await getLanguagesVoicesForNuane(credential, getTtsVoices, logger);
|
||||
case 'deepgram':
|
||||
return await getLanguagesVoicesForDeepgram(credential);
|
||||
return await getLanguagesVoicesForDeepgram(credential, getTtsVoices, logger);
|
||||
case 'ibm':
|
||||
return await getLanguagesVoicesForIbm(credential);
|
||||
return await getLanguagesVoicesForIbm(credential, getTtsVoices, logger);
|
||||
case 'nvidia':
|
||||
return await getLanguagesVoicesForNvida(credential);
|
||||
return await getLanguagesVoicesForNvida(credential, getTtsVoices, logger);
|
||||
case 'cobalt':
|
||||
return await getLanguagesVoicesForCobalt(credential);
|
||||
return await getLanguagesVoicesForCobalt(credential, getTtsVoices, logger);
|
||||
case 'soniox':
|
||||
return await getLanguagesVoicesForSoniox(credential);
|
||||
return await getLanguagesVoicesForSoniox(credential, getTtsVoices, logger);
|
||||
case 'elevenlabs':
|
||||
return await getLanguagesVoicesForElevenlabs(credential);
|
||||
return await getLanguagesVoicesForElevenlabs(credential, getTtsVoices, logger);
|
||||
case 'assemblyai':
|
||||
return await getLanguagesVoicesForAssemblyAI(credential);
|
||||
return await getLanguagesVoicesForAssemblyAI(credential, getTtsVoices, logger);
|
||||
case 'whisper':
|
||||
return await getLanguagesVoicesForWhisper(credential);
|
||||
return await getLanguagesVoicesForWhisper(credential, getTtsVoices, logger);
|
||||
default:
|
||||
logger.info(`invalid vendor ${vendor}, return empty result`);
|
||||
throw new Error(`Invalid vendor ${vendor}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function getLanguagesVoicesForGoogle(credential) {
|
||||
async function getLanguagesVoicesForGoogle(credential, getTtsVoices, logger) {
|
||||
if (credential) {
|
||||
try {
|
||||
const [result] = await getTtsVoices({
|
||||
vendor: 'google',
|
||||
credentials: credential
|
||||
});
|
||||
const tts = parseGooglelanguagesVoices(result.voices);
|
||||
return tranform(tts, SttGoogleLanguagesVoices);
|
||||
} catch (err) {
|
||||
logger.info('Error while fetching google languages, voices, return predefined values', err);
|
||||
}
|
||||
}
|
||||
return tranform(TtsGoogleLanguagesVoices, SttGoogleLanguagesVoices);
|
||||
}
|
||||
|
||||
async function getLanguagesVoicesForAws(credential) {
|
||||
async function getLanguagesVoicesForAws(credential, getTtsVoices, logger) {
|
||||
if (credential) {
|
||||
try {
|
||||
const result = await getTtsVoices({
|
||||
vendor: 'aws',
|
||||
credentials: {
|
||||
accessKeyId: credential.access_key_id,
|
||||
secretAccessKey: credential.secret_access_key,
|
||||
region: credential.aws_region || process.env.AWS_REGION
|
||||
}
|
||||
});
|
||||
const tts = parseAwsLanguagesVoices(result.Voices);
|
||||
return tranform(tts, SttAwsLanguagesVoices);
|
||||
} catch (err) {
|
||||
logger.info('Error while fetching AWS languages, voices, return predefined values', err);
|
||||
}
|
||||
}
|
||||
return tranform(TtsAwsLanguagesVoices, SttAwsLanguagesVoices);
|
||||
}
|
||||
|
||||
async function getLanguagesVoicesForMicrosoft(credential) {
|
||||
async function getLanguagesVoicesForMicrosoft(credential, getTtsVoices, logger) {
|
||||
if (credential) {
|
||||
try {
|
||||
const get = bent('https://westus.tts.speech.microsoft.com', 'GET', 'json', {
|
||||
'Ocp-Apim-Subscription-Key' : credential.api_key
|
||||
});
|
||||
|
||||
const voices = await get('/cognitiveservices/voices/list');
|
||||
const tts = parseMicrosoftLanguagesVoices(voices);
|
||||
return tranform(tts, SttMicrosoftLanguagesVoices);
|
||||
} catch (err) {
|
||||
logger.info('Error while fetching Microsoft languages, voices, return predefined values', err);
|
||||
}
|
||||
}
|
||||
return tranform(TtsMicrosoftLanguagesVoices, SttMicrosoftLanguagesVoices);
|
||||
}
|
||||
|
||||
@@ -514,7 +555,19 @@ async function getLanguagesVoicesForWellsaid(credential) {
|
||||
return tranform(TtsWellsaidLanguagesVoices);
|
||||
}
|
||||
|
||||
async function getLanguagesVoicesForNuane(credential) {
|
||||
async function getLanguagesVoicesForNuane(credential, getTtsVoices, logger) {
|
||||
if (credential) {
|
||||
try {
|
||||
const result = await getTtsVoices({
|
||||
vendor: 'nuance',
|
||||
credentials: credential
|
||||
});
|
||||
const tts = parseNuanceLanguagesVoices(result.result.voices);
|
||||
return tranform(tts, SttNuanceLanguagesVoices);
|
||||
} catch (err) {
|
||||
logger.info('Error while fetching IBM languages, voices, return predefined values', err);
|
||||
}
|
||||
}
|
||||
return tranform(TtsNuanceLanguagesVoices, SttNuanceLanguagesVoices);
|
||||
}
|
||||
|
||||
@@ -522,7 +575,19 @@ async function getLanguagesVoicesForDeepgram(credential) {
|
||||
return tranform(undefined, SttDeepgramLanguagesVoices, TtsModelDeepgram);
|
||||
}
|
||||
|
||||
async function getLanguagesVoicesForIbm(credential) {
|
||||
async function getLanguagesVoicesForIbm(credential, getTtsVoices, logger) {
|
||||
if (credential) {
|
||||
try {
|
||||
const result = await getTtsVoices({
|
||||
vendor: 'ibm',
|
||||
credentials: credential
|
||||
});
|
||||
const tts = parseIBMLanguagesVoices(result.result.voices);
|
||||
return tranform(tts, SttIbmLanguagesVoices);
|
||||
} catch (err) {
|
||||
logger.info('Error while fetching IBM languages, voices, return predefined values', err);
|
||||
}
|
||||
}
|
||||
return tranform(TtsIbmLanguagesVoices, SttIbmLanguagesVoices);
|
||||
}
|
||||
|
||||
@@ -596,6 +661,125 @@ function tranform(tts, stt, models) {
|
||||
};
|
||||
}
|
||||
|
||||
function parseGooglelanguagesVoices(data) {
|
||||
return data.reduce((acc, voice) => {
|
||||
const languageCode = voice.languageCodes[0];
|
||||
const existingLanguage = acc.find((lang) => lang.value === languageCode);
|
||||
|
||||
if (existingLanguage) {
|
||||
existingLanguage.voices.push({
|
||||
value: voice.name,
|
||||
name: `${voice.name.substring(languageCode.length + 1, voice.name.length)} (${voice.ssmlGender})`
|
||||
});
|
||||
} else {
|
||||
acc.push({
|
||||
value: languageCode,
|
||||
name: SttGoogleLanguagesVoices.find((lang) => lang.value === languageCode)?.name || languageCode,
|
||||
voices: [{
|
||||
value: voice.name,
|
||||
name: `${voice.name.substring(languageCode.length + 1, voice.name.length)} (${voice.ssmlGender})`
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function parseIBMLanguagesVoices(data) {
|
||||
return data.reduce((acc, voice) => {
|
||||
const languageCode = voice.language;
|
||||
const existingLanguage = acc.find((lang) => lang.value === languageCode);
|
||||
if (existingLanguage) {
|
||||
existingLanguage.voices.push({
|
||||
value: voice.name,
|
||||
name: `(${voice.gender}) ${voice.description}`
|
||||
});
|
||||
} else {
|
||||
acc.push({
|
||||
value: languageCode,
|
||||
name: SttGoogleLanguagesVoices.find((lang) => lang.value === languageCode)?.name || languageCode,
|
||||
voices: [{
|
||||
value: voice.name,
|
||||
name: `(${voice.gender}) ${voice.description}`
|
||||
}]
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function parseAwsLanguagesVoices(data) {
|
||||
return data.reduce((acc, voice) => {
|
||||
const languageCode = voice.LanguageCode;
|
||||
const existingLanguage = acc.find((lang) => lang.value === languageCode);
|
||||
if (existingLanguage) {
|
||||
existingLanguage.voices.push({
|
||||
value: voice.Id,
|
||||
name: `(${voice.Gender}) ${voice.Name}`
|
||||
});
|
||||
} else {
|
||||
acc.push({
|
||||
value: languageCode,
|
||||
name: voice.LanguageName,
|
||||
voices: [{
|
||||
value: voice.Id,
|
||||
name: `(${voice.Gender}) ${voice.Name}`
|
||||
}]
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function parseNuanceLanguagesVoices(data) {
|
||||
return data.reduce((acc, voice) => {
|
||||
const languageCode = voice.language;
|
||||
const existingLanguage = acc.find((lang) => lang.value === languageCode);
|
||||
if (existingLanguage) {
|
||||
existingLanguage.voices.push({
|
||||
value: voice.name,
|
||||
name: voice.name,
|
||||
model: voice.model
|
||||
});
|
||||
} else {
|
||||
acc.push({
|
||||
value: languageCode,
|
||||
name: SttGoogleLanguagesVoices.find((lang) => lang.value === languageCode)?.name || languageCode,
|
||||
voices: [{
|
||||
value: voice.name,
|
||||
name: voice.name,
|
||||
model: voice.model
|
||||
}]
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function parseMicrosoftLanguagesVoices(data) {
|
||||
return data.reduce((acc, voice) => {
|
||||
const languageCode = voice.Locale;
|
||||
const existingLanguage = acc.find((lang) => lang.value === languageCode);
|
||||
if (existingLanguage) {
|
||||
existingLanguage.voices.push({
|
||||
value: voice.ShortName,
|
||||
name: `${voice.DisplayName} (${voice.Gender})`,
|
||||
});
|
||||
} else {
|
||||
acc.push({
|
||||
value: voice.Locale,
|
||||
name: voice.LocaleName,
|
||||
voices: [{
|
||||
value: voice.ShortName,
|
||||
name: `${voice.DisplayName} (${voice.Gender})`,
|
||||
}]
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
testGoogleTts,
|
||||
testGoogleStt,
|
||||
|
||||
5439
package-lock.json
generated
5439
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,7 @@
|
||||
"@jambonz/lamejs": "^1.2.2",
|
||||
"@jambonz/mw-registrar": "^0.2.7",
|
||||
"@jambonz/realtimedb-helpers": "^0.8.7",
|
||||
"@jambonz/speech-utils": "^0.0.33",
|
||||
"@jambonz/speech-utils": "^0.0.35",
|
||||
"@jambonz/time-series": "^0.2.8",
|
||||
"@jambonz/verb-specifications": "^0.0.45",
|
||||
"@soniox/soniox-node": "^1.1.1",
|
||||
|
||||
Reference in New Issue
Block a user