Compare commits

..
7 Commits
Author SHA1 Message Date
Dave Horton 7b4a71f55d 0.2.3 2025-02-07 07:20:12 -05:00
Dave Horton d552b65618 Merge pull request #106 from jambonz/feat/rimelabs_voices
rimelabs support multiple model and languages
2025-02-07 07:19:47 -05:00
Quan HL f701b50244 rimelabs support multiple model and languages 2025-02-07 14:20:52 +07:00
Dave Horton 199e502fbe 0.2.2 2025-02-03 08:14:15 -05:00
Dave Horton 6769779189 Merge pull request #105 from jambonz/fix/gh_1059
tts key should include model
2025-02-03 08:13:54 -05:00
Quan HL 4b43c3986c wip 2025-02-02 19:03:09 +07:00
Quan HL e1292772e6 tts key should include model 2025-02-02 18:54:16 +07:00
7 changed files with 61 additions and 14 deletions
+2 -1
View File
@@ -25,7 +25,7 @@ function getExtensionAndSampleRate(path) {
}
async function addFileToCache(client, logger, path,
{account_sid, vendor, language, voice, deploymentId, engine, text}) {
{account_sid, vendor, language, voice, deploymentId, engine, model, text}) {
let key;
logger = logger || noopLogger;
@@ -36,6 +36,7 @@ async function addFileToCache(client, logger, path,
language: language || '',
voice: voice || deploymentId,
engine,
model,
text,
});
const [extension, sampleRate] = getExtensionAndSampleRate(path);
+2 -1
View File
@@ -12,7 +12,7 @@ const debug = require('debug')('jambonz:realtimedb-helpers');
* @returns {object} result - {error, purgedCount}
*/
async function purgeTtsCache(client, logger, {all, account_sid, vendor,
language, voice, deploymentId, engine, text} = {all: true}) {
language, voice, deploymentId, engine, model, text} = {all: true}) {
logger = logger || noopLogger;
let purgedCount = 0, error;
@@ -33,6 +33,7 @@ async function purgeTtsCache(client, logger, {all, account_sid, vendor,
language: language || '',
voice: voice || deploymentId,
engine,
model,
text,
});
purgedCount = await client.del(key);
+5 -1
View File
@@ -169,6 +169,8 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
language: language || '',
voice: voice || deploymentId,
engine,
// model or model_id is used to identify the tts cache.
model: model || credentials.model_id,
text
});
@@ -924,7 +926,7 @@ const synthPlayHT = async(client, logger, {
};
const synthRimelabs = async(logger, {
credentials, options, stats, voice, text, renderForCaching, disableTtsStreaming
credentials, options, stats, language, voice, text, renderForCaching, disableTtsStreaming
}) => {
const {api_key, model_id, options: credOpts} = credentials;
const opts = !!options && Object.keys(options).length !== 0 ? options : JSON.parse(credOpts || '{}');
@@ -935,6 +937,7 @@ const synthRimelabs = async(logger, {
params += `{api_key=${api_key}`;
params += `,model_id=${model_id}`;
params += ',vendor=rimelabs';
params += `,language=${language}`;
params += `,voice=${voice}`;
params += ',write_cache_file=1';
if (opts.speedAlpha) params += `,speed_alpha=${opts.speedAlpha}`;
@@ -960,6 +963,7 @@ const synthRimelabs = async(logger, {
text,
modelId: model_id,
samplingRate: sampleRate,
lang: language,
...opts
});
return {
+9 -2
View File
@@ -17,9 +17,16 @@ const debug = require('debug')('jambonz:realtimedb-helpers');
//const nuanceClientMap = new Map();
function makeSynthKey({
account_sid = '', vendor, language, voice, engine = '', text}) {
account_sid = '',
vendor,
language,
voice,
engine = '',
model = '',
text
}) {
const hash = crypto.createHash('sha1');
hash.update(`${language}:${vendor}:${voice}:${engine}:${text}`);
hash.update(`${language}:${vendor}:${voice}:${engine}:${model}:${text}`);
const hexHashKey = hash.digest('hex');
const accountKey = account_sid ? `:${account_sid}` : '';
const key = `tts${accountKey}:${hexHashKey}`;
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@jambonz/speech-utils",
"version": "0.2.1",
"version": "0.2.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@jambonz/speech-utils",
"version": "0.2.1",
"version": "0.2.3",
"license": "MIT",
"dependencies": {
"@aws-sdk/client-polly": "^3.496.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@jambonz/speech-utils",
"version": "0.2.1",
"version": "0.2.3",
"description": "TTS-related speech utilities for jambonz",
"main": "index.js",
"author": "Dave Horton",
+40 -6
View File
@@ -5,7 +5,7 @@ const fs = require('fs');
const {makeSynthKey} = require('../lib/utils');
const logger = require('pino')();
const bent = require('bent');
const getJSON = bent('json')
const getJSON = bent('json');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
@@ -720,7 +720,7 @@ test('Cartesia speech synth tests', async(t) => {
client.quit();
});
test('rimelabs speech synth tests', async(t) => {
test('rimelabs speech synth tests mist', async(t) => {
const fn = require('..');
const {synthAudio, client} = fn(opts, logger);
@@ -730,7 +730,7 @@ test('rimelabs speech synth tests', async(t) => {
}
const text = 'Hi there and welcome to jambones!';
try {
let opts = await synthAudio(stats, {
const opts = await synthAudio(stats, {
vendor: 'rimelabs',
credentials: {
api_key: process.env.RIMELABS_API_KEY,
@@ -740,7 +740,7 @@ test('rimelabs speech synth tests', async(t) => {
reduceLatency: false
})
},
language: 'en-US',
language: 'eng',
voice: 'amber',
text,
renderForCaching: true
@@ -754,6 +754,40 @@ test('rimelabs speech synth tests', async(t) => {
client.quit();
});
test('rimelabs speech synth tests mistv2', async(t) => {
const fn = require('..');
const {synthAudio, client} = fn(opts, logger);
if (!process.env.RIMELABS_API_KEY) {
t.pass('skipping rimelabs speech synth tests since RIMELABS_API_KEY is not provided');
return t.end();
}
const text = 'Hi there and welcome to jambones!';
try {
const opts = await synthAudio(stats, {
vendor: 'rimelabs',
credentials: {
api_key: process.env.RIMELABS_API_KEY,
model_id: 'mistv2',
options: JSON.stringify({
speedAlpha: 1.0,
reduceLatency: false
})
},
language: 'spa',
voice: 'pablo',
text,
renderForCaching: true
});
t.ok(!opts.servedFromCache, `successfully synthesized rimelabs mistv2 audio to ${opts.filePath}`);
} catch (err) {
console.error(JSON.stringify(err));
t.end(err);
}
client.quit();
});
test('whisper speech synth tests', async(t) => {
const fn = require('..');
const {synthAudio, client} = fn(opts, logger);
@@ -853,11 +887,11 @@ test('TTS Cache tests', async(t) => {
// save some random tts keys to cache
const minRecords = 8;
for (const i in Array(minRecords).fill(0)) {
await client.set(makeSynthKey({vendor: i, language: i, voice: i, engine: i, text: i}), i);
await client.set(makeSynthKey({vendor: i, language: i, voice: i, engine: i, model: i, text: i}), i);
}
const count = await getTtsSize();
t.ok(count >= minRecords, 'getTtsSize worked.');
const {purgedCount} = await purgeTtsCache();
t.ok(purgedCount >= minRecords, `successfully purged at least ${minRecords} tts records from cache`);