mirror of
https://github.com/jambonz/speech-utils.git
synced 2026-10-03 23:33:59 +00:00
Merge pull request #98 from jambonz/fix/freshdesk_411
Fix custom tts vendor cached file can not be played
This commit is contained in:
+25
-4
@@ -170,6 +170,8 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
|
|||||||
renderForCaching
|
renderForCaching
|
||||||
});
|
});
|
||||||
let filePath;
|
let filePath;
|
||||||
|
// used only for custom vendor
|
||||||
|
let fileExtension;
|
||||||
filePath = makeFilePath({vendor, voice, key, salt, renderForCaching});
|
filePath = makeFilePath({vendor, voice, key, salt, renderForCaching});
|
||||||
debug(`synth key is ${key}`);
|
debug(`synth key is ${key}`);
|
||||||
let cached;
|
let cached;
|
||||||
@@ -201,7 +203,17 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
|
|||||||
debug('result WAS found in cache');
|
debug('result WAS found in cache');
|
||||||
servedFromCache = true;
|
servedFromCache = true;
|
||||||
stats.increment('tts.cache.requests', ['found:yes']);
|
stats.increment('tts.cache.requests', ['found:yes']);
|
||||||
audioBuffer = Buffer.from(cached, 'base64');
|
if (vendor.startsWith('custom')) {
|
||||||
|
// custom vendors support multiple mime types such as: mp3, wav, r8, r16 ...etc,
|
||||||
|
// mime type/file extension is available when http response has header Content-type.
|
||||||
|
// In cache, file extension is store together with audiBuffer in a json.
|
||||||
|
// Normal cache audio will be base64 string
|
||||||
|
const payload = JSON.parse(cached);
|
||||||
|
filePath = filePath.replace(/\.[^\.]*$/g, payload.fileExtension);
|
||||||
|
audioBuffer = Buffer.from(payload.audioBuffer, 'base64');
|
||||||
|
} else {
|
||||||
|
audioBuffer = Buffer.from(cached, 'base64');
|
||||||
|
}
|
||||||
client.expire(key, EXPIRES).catch((err) => logger.info(err, 'Error setting expires'));
|
client.expire(key, EXPIRES).catch((err) => logger.info(err, 'Error setting expires'));
|
||||||
}
|
}
|
||||||
if (!cached) {
|
if (!cached) {
|
||||||
@@ -268,7 +280,7 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
|
|||||||
renderForCaching, disableTtsStreaming});
|
renderForCaching, disableTtsStreaming});
|
||||||
break;
|
break;
|
||||||
case vendor.startsWith('custom') ? vendor : 'cant_match_value':
|
case vendor.startsWith('custom') ? vendor : 'cant_match_value':
|
||||||
({ audioBuffer, filePath } = await synthCustomVendor(logger,
|
({ audioBuffer, filePath, fileExtension } = await synthCustomVendor(logger,
|
||||||
{credentials, stats, language, voice, text, filePath}));
|
{credentials, stats, language, voice, text, filePath}));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -282,7 +294,14 @@ async function synthAudio(client, createHash, retrieveHash, logger, stats, { acc
|
|||||||
debug(`tts rtt time for ${text.length} chars on ${vendorLabel}: ${rtt}`);
|
debug(`tts rtt time for ${text.length} chars on ${vendorLabel}: ${rtt}`);
|
||||||
logger.info(`tts rtt time for ${text.length} chars on ${vendorLabel}: ${rtt}`);
|
logger.info(`tts rtt time for ${text.length} chars on ${vendorLabel}: ${rtt}`);
|
||||||
|
|
||||||
client.setex(key, EXPIRES, audioBuffer.toString('base64'))
|
const base64Audio = audioBuffer.toString('base64');
|
||||||
|
const cacheContent = vendor.startsWith('custom') ?
|
||||||
|
JSON.stringify({
|
||||||
|
audioBuffer: base64Audio,
|
||||||
|
fileExtension
|
||||||
|
}) : base64Audio;
|
||||||
|
|
||||||
|
client.setex(key, EXPIRES, cacheContent)
|
||||||
.catch((err) => logger.error(err, `error calling setex on key ${key}`));
|
.catch((err) => logger.error(err, `error calling setex on key ${key}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,9 +748,11 @@ const synthCustomVendor = async(logger, {credentials, stats, language, voice, te
|
|||||||
const regex = /\.[^\.]*$/g;
|
const regex = /\.[^\.]*$/g;
|
||||||
const mime = response.headers['content-type'];
|
const mime = response.headers['content-type'];
|
||||||
const buffer = await response.arrayBuffer();
|
const buffer = await response.arrayBuffer();
|
||||||
|
const fileExtension = getFileExtFromMime(mime);
|
||||||
return {
|
return {
|
||||||
audioBuffer: buffer,
|
audioBuffer: buffer,
|
||||||
filePath: filePath.replace(regex, getFileExtFromMime(mime))
|
filePath: filePath.replace(regex, fileExtension),
|
||||||
|
fileExtension
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.info({err}, `Vendor ${vendor} returned error`);
|
logger.info({err}, `Vendor ${vendor} returned error`);
|
||||||
|
|||||||
@@ -554,6 +554,7 @@ test('Custom Vendor speech synth tests', async(t) => {
|
|||||||
text: 'This is a test. This is only a test',
|
text: 'This is a test. This is only a test',
|
||||||
});
|
});
|
||||||
t.ok(!opts.servedFromCache, `successfully synthesized custom vendor audio to ${opts.filePath}`);
|
t.ok(!opts.servedFromCache, `successfully synthesized custom vendor audio to ${opts.filePath}`);
|
||||||
|
t.ok(opts.filePath.endsWith('wav'), 'audio is cached as wav file');
|
||||||
let obj = await getJSON(`http://127.0.0.1:3100/lastRequest/somethingnew`);
|
let obj = await getJSON(`http://127.0.0.1:3100/lastRequest/somethingnew`);
|
||||||
t.ok(obj.headers.Authorization == 'Bearer some_jwt_token', 'Custom Vendor Authentication Header is correct');
|
t.ok(obj.headers.Authorization == 'Bearer some_jwt_token', 'Custom Vendor Authentication Header is correct');
|
||||||
t.ok(obj.body.language == 'en-US', 'Custom Vendor Language is correct');
|
t.ok(obj.body.language == 'en-US', 'Custom Vendor Language is correct');
|
||||||
@@ -561,6 +562,21 @@ test('Custom Vendor speech synth tests', async(t) => {
|
|||||||
t.ok(obj.body.type == 'text', 'Custom Vendor type is correct');
|
t.ok(obj.body.type == 'text', 'Custom Vendor type is correct');
|
||||||
t.ok(obj.body.text == 'This is a test. This is only a test', 'Custom Vendor text is correct');
|
t.ok(obj.body.text == 'This is a test. This is only a test', 'Custom Vendor text is correct');
|
||||||
|
|
||||||
|
// Checking if cache is stored with wav format
|
||||||
|
opts = await synthAudio(stats, {
|
||||||
|
vendor: 'custom:somethingnew',
|
||||||
|
credentials: {
|
||||||
|
use_for_tts: 1,
|
||||||
|
custom_tts_url: "http://127.0.0.1:3100/somethingnew",
|
||||||
|
auth_token: 'some_jwt_token'
|
||||||
|
},
|
||||||
|
language: 'en-US',
|
||||||
|
voice: 'English-US.Female-1',
|
||||||
|
text: 'This is a test. This is only a test',
|
||||||
|
});
|
||||||
|
t.ok(opts.servedFromCache, `successfully get custom vendor cached audio to ${opts.filePath}`);
|
||||||
|
t.ok(opts.filePath.endsWith('wav'), 'audio is cached as wav file');
|
||||||
|
|
||||||
opts = await synthAudio(stats, {
|
opts = await synthAudio(stats, {
|
||||||
vendor: 'custom:somethingnew2',
|
vendor: 'custom:somethingnew2',
|
||||||
credentials: {
|
credentials: {
|
||||||
|
|||||||
Reference in New Issue
Block a user