mirror of
https://github.com/jambonz/jambonz-api-server.git
synced 2026-07-24 13:02:16 +00:00
replace bent by native node fetch (#401)
* replace bent by native node fetch * wip * wip * wip
This commit is contained in:
+100
-65
@@ -3,7 +3,6 @@ const { TranscribeClient, ListVocabulariesCommand } = require('@aws-sdk/client-t
|
||||
const { Deepgram } = require('@deepgram/sdk');
|
||||
const sdk = require('microsoft-cognitiveservices-speech-sdk');
|
||||
const { SpeechClient } = require('@soniox/soniox-node');
|
||||
const bent = require('bent');
|
||||
const fs = require('fs');
|
||||
const { AssemblyAI } = require('assemblyai');
|
||||
const {decrypt, obscureKey} = require('./encrypt-decrypt');
|
||||
@@ -288,44 +287,46 @@ const testMicrosoftTts = async(logger, synthAudio, credentials) => {
|
||||
|
||||
const testWellSaidTts = async(logger, credentials) => {
|
||||
const {api_key} = credentials;
|
||||
try {
|
||||
const post = bent('https://api.wellsaidlabs.com', 'POST', 'buffer', {
|
||||
const response = await fetch('https://api.wellsaidlabs.com/v1/tts/stream', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Api-Key': api_key,
|
||||
'Accept': 'audio/mpeg',
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
const mp3 = await post('/v1/tts/stream', {
|
||||
},
|
||||
body: JSON.stringify({
|
||||
text: 'Hello, world',
|
||||
speaker_id: '3'
|
||||
});
|
||||
return mp3;
|
||||
} catch (err) {
|
||||
logger.info({err}, 'testWellSaidTts returned error');
|
||||
throw err;
|
||||
})
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error('failed to synthesize speech');
|
||||
}
|
||||
return response.body;
|
||||
};
|
||||
|
||||
const testElevenlabs = async(logger, credentials) => {
|
||||
const {api_key, model_id} = credentials;
|
||||
try {
|
||||
const post = bent('https://api.elevenlabs.io', 'POST', 'buffer', {
|
||||
const response = await fetch('https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'xi-api-key': api_key,
|
||||
'Accept': 'audio/mpeg',
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
const mp3 = await post('/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM', {
|
||||
},
|
||||
body: JSON.stringify({
|
||||
text: 'Hello',
|
||||
model_id,
|
||||
voice_settings: {
|
||||
stability: 0.5,
|
||||
similarity_boost: 0.5
|
||||
}
|
||||
});
|
||||
return mp3;
|
||||
} catch (err) {
|
||||
logger.info({err}, 'synthEvenlabs returned error');
|
||||
throw err;
|
||||
})
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error('failed to synthesize speech');
|
||||
}
|
||||
return response.body;
|
||||
};
|
||||
|
||||
const testPlayHT = async(logger, synthAudio, credentials) => {
|
||||
@@ -466,18 +467,18 @@ const testVerbioTts = async(logger, synthAudio, credentials) => {
|
||||
};
|
||||
const testVerbioStt = async(logger, getVerbioAccessToken, credentials) => {
|
||||
const token = await getVerbioAccessToken(credentials);
|
||||
try {
|
||||
const post = bent('https://us.rest.speechcenter.verbio.com', 'POST', 'json', {
|
||||
const response = await fetch('https://us.rest.speechcenter.verbio.com/api/v1/recognize?language=en-US&version=V1', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token.access_token}`,
|
||||
'User-Agent': 'jambonz',
|
||||
'Content-Type': 'audio/wav'
|
||||
});
|
||||
const json = await post('/api/v1/recognize?language=en-US&version=V1',
|
||||
fs.readFileSync(`${__dirname}/../../data/test_audio.wav`));
|
||||
logger.debug({json}, 'successfully speech to text from verbio');
|
||||
} catch (err) {
|
||||
logger.info({err}, 'testWellSaidTts returned error');
|
||||
throw err;
|
||||
},
|
||||
body: fs.readFileSync(`${__dirname}/../../data/test_audio.wav`)
|
||||
});
|
||||
if (!response.ok) {
|
||||
logger.error({Error: await response.text()}, 'Error transcribing speech');
|
||||
throw new Error('failed to transcribe speech');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -546,16 +547,17 @@ const testAssemblyStt = async(logger, credentials) => {
|
||||
|
||||
const testVoxistStt = async(logger, credentials) => {
|
||||
const {api_key} = credentials;
|
||||
try {
|
||||
const get = bent('https://api-asr.voxist.com', 'GET', 'json', {
|
||||
const response = await fetch('https://api-asr.voxist.com/clients', {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'x-lvl-key': api_key
|
||||
});
|
||||
await get('/clients');
|
||||
} catch (err) {
|
||||
logger.info({err}, 'failed to get clients from Voxist');
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
if (!response.ok) {
|
||||
logger.error({response}, 'Error retrieving clients');
|
||||
throw new Error('failed to get clients');
|
||||
}
|
||||
return response.json();
|
||||
};
|
||||
|
||||
const getSpeechCredential = (credential, logger) => {
|
||||
@@ -812,17 +814,18 @@ async function getLanguagesVoicesForAws(credential, getTtsVoices, logger) {
|
||||
|
||||
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);
|
||||
const response = await fetch('https://westus.tts.speech.microsoft.com/cognitiveservices/voices/list', {
|
||||
headers: {
|
||||
'Ocp-Apim-Subscription-Key': credential.api_key
|
||||
}
|
||||
});
|
||||
if (!response.ok) {
|
||||
logger.error({response}, 'Error fetching Microsoft voices');
|
||||
throw new Error('failed to list voices');
|
||||
}
|
||||
const voices = await response.json();
|
||||
const tts = parseMicrosoftLanguagesVoices(voices);
|
||||
return tranform(tts, SttMicrosoftLanguagesVoices);
|
||||
}
|
||||
return tranform(TtsMicrosoftLanguagesVoices, SttMicrosoftLanguagesVoices);
|
||||
}
|
||||
@@ -885,14 +888,27 @@ async function getLanguagesVoicesForSpeechmatics(credential) {
|
||||
|
||||
async function getLanguagesVoicesForElevenlabs(credential) {
|
||||
if (credential) {
|
||||
const get = bent('https://api.elevenlabs.io', 'GET', 'json', {
|
||||
'xi-api-key' : credential.api_key
|
||||
const headers = {
|
||||
'xi-api-key': credential.api_key
|
||||
};
|
||||
|
||||
const getModelPromise = fetch('https://api.elevenlabs.io/v1/models', {
|
||||
headers
|
||||
});
|
||||
const getVoicePromise = fetch('https://api.elevenlabs.io/v1/voices', {
|
||||
headers
|
||||
});
|
||||
const [langResp, voiceResp] = await Promise.all([getModelPromise, getVoicePromise]);
|
||||
|
||||
const [langResp, voiceResp] = await Promise.all([get('/v1/models'), get('/v1/voices')]);
|
||||
if (!langResp.ok || !voiceResp.ok) {
|
||||
throw new Error('failed to list voices');
|
||||
}
|
||||
|
||||
const model = langResp.find((m) => m.model_id === credential.model_id);
|
||||
const models = langResp.map((m) => {
|
||||
const langs = await langResp.json();
|
||||
const voicesR = await voiceResp.json();
|
||||
|
||||
const model = langs.find((m) => m.model_id === credential.model_id);
|
||||
const models = langs.map((m) => {
|
||||
return {
|
||||
value: m.model_id,
|
||||
name: m.name
|
||||
@@ -908,7 +924,7 @@ async function getLanguagesVoicesForElevenlabs(credential) {
|
||||
|
||||
if (languages && languages.length > 0) {
|
||||
// using if condition to avoid \n character in name
|
||||
const voices = voiceResp ? voiceResp.voices.map((v) => {
|
||||
const voices = voicesR ? voicesR.voices.map((v) => {
|
||||
let name = `${v.name}${v.category !== 'premade' ? ` (${v.category.trim()})` : ''} - (`;
|
||||
if (v.labels.accent) name += `${v.labels.accent}, `;
|
||||
if (v.labels.description) name += `${v.labels.description}, `;
|
||||
@@ -946,18 +962,28 @@ const concat = (a) => {
|
||||
|
||||
const fetchLayHTVoices = async(credential) => {
|
||||
if (credential) {
|
||||
const get = bent('https://api.play.ht', 'GET', 'json', {
|
||||
'AUTHORIZATION' : credential.api_key,
|
||||
const headers = {
|
||||
'AUTHORIZATION': credential.api_key,
|
||||
'X-USER-ID': credential.user_id,
|
||||
'Accept': 'application/json'
|
||||
};
|
||||
const response = await fetch('https://api.play.ht/api/v2/voices', {
|
||||
headers
|
||||
});
|
||||
|
||||
const voices = await get('/api/v2/voices');
|
||||
if (!response.ok) {
|
||||
throw new Error('failed to list voices');
|
||||
}
|
||||
const voices = await response.json();
|
||||
let clone_voices = [];
|
||||
try {
|
||||
// try if the account has permission to cloned voice
|
||||
//otherwise ignore this.
|
||||
clone_voices = await get('/api/v2/cloned-voices');
|
||||
const clone_voices_Response = await fetch('https://api.play.ht/api/v2/cloned-voices', {
|
||||
headers
|
||||
});
|
||||
if (clone_voices_Response.ok) {
|
||||
clone_voices = await clone_voices_Response.json();
|
||||
}
|
||||
} catch {}
|
||||
return [clone_voices, voices];
|
||||
}
|
||||
@@ -1032,10 +1058,15 @@ async function getLanguagesVoicesForPlayHT(credential) {
|
||||
|
||||
async function getLanguagesVoicesForRimelabs(credential) {
|
||||
const model_id = credential ? credential.model_id : null;
|
||||
const get = bent('https://users.rime.ai', 'GET', 'json', {
|
||||
'Accept': 'application/json'
|
||||
const response = await fetch('https://users.rime.ai//data/voices/all-v2.json', {
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
const voices = await get('/data/voices/all-v2.json');
|
||||
if (!response.ok) {
|
||||
throw new Error('failed to list models');
|
||||
}
|
||||
const voices = await response.json();
|
||||
const modelVoices = model_id ? voices[model_id] :
|
||||
Object.keys(voices).length > 0 ? voices[Object.keys(voices)[0]] : [];
|
||||
const ttsVoices = Object.entries(modelVoices).map(([key, voices]) => ({
|
||||
@@ -1238,14 +1269,18 @@ function parseVerbioLanguagesVoices(data) {
|
||||
|
||||
const fetchCartesiaVoices = async(credential) => {
|
||||
if (credential) {
|
||||
const get = bent('https://api.cartesia.ai', 'GET', 'json', {
|
||||
'X-API-Key' : credential.api_key,
|
||||
'Cartesia-Version': '2024-06-10',
|
||||
'Accept': 'application/json'
|
||||
const response = await fetch('https://api.cartesia.ai/voices', {
|
||||
headers: {
|
||||
'X-API-Key': credential.api_key,
|
||||
'Cartesia-Version': '2024-06-10',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error('failed to list voices');
|
||||
}
|
||||
|
||||
const voices = await get('/voices');
|
||||
return voices;
|
||||
return await response.json();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user