mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-20 08:40:38 +00:00
allow say.text to accept either a string or an array of strings
This commit is contained in:
@@ -6,7 +6,7 @@ class TaskSay extends Task {
|
|||||||
super(logger, opts);
|
super(logger, opts);
|
||||||
this.preconditions = TaskPreconditions.Endpoint;
|
this.preconditions = TaskPreconditions.Endpoint;
|
||||||
|
|
||||||
this.text = this.data.text;
|
this.text = Array.isArray(this.data.text) ? this.data.text : [this.data.text];
|
||||||
this.loop = this.data.loop || 1;
|
this.loop = this.data.loop || 1;
|
||||||
this.earlyMedia = this.data.earlyMedia === true || (parentTask && parentTask.earlyMedia);
|
this.earlyMedia = this.data.earlyMedia === true || (parentTask && parentTask.earlyMedia);
|
||||||
this.synthesizer = this.data.synthesizer || {};
|
this.synthesizer = this.data.synthesizer || {};
|
||||||
@@ -20,21 +20,23 @@ class TaskSay extends Task {
|
|||||||
await super.exec(cs);
|
await super.exec(cs);
|
||||||
this.ep = ep;
|
this.ep = ep;
|
||||||
try {
|
try {
|
||||||
let filepath;
|
const filepath = [];
|
||||||
const opts = Object.assign({
|
|
||||||
text: this.text,
|
|
||||||
vendor: cs.speechSynthesisVendor,
|
|
||||||
language: cs.speechSynthesisLanguage,
|
|
||||||
voice: cs.speechSynthesisVoice
|
|
||||||
}, this.synthesizer);
|
|
||||||
|
|
||||||
while (!this.killed && this.loop--) {
|
while (!this.killed && this.loop--) {
|
||||||
if (!filepath) {
|
let segment = 0;
|
||||||
this.logger.debug('TaskSay:exec - retrieving synthesized audio');
|
do {
|
||||||
filepath = await synthAudio(opts);
|
if (filepath.length <= segment) {
|
||||||
cs.trackTmpFile(filepath);
|
const opts = Object.assign({
|
||||||
}
|
text: this.text[segment],
|
||||||
await ep.play(filepath);
|
vendor: cs.speechSynthesisVendor,
|
||||||
|
language: cs.speechSynthesisLanguage,
|
||||||
|
voice: cs.speechSynthesisVoice
|
||||||
|
}, this.synthesizer);
|
||||||
|
const path = await synthAudio(opts);
|
||||||
|
filepath.push(path);
|
||||||
|
cs.trackTmpFile(path);
|
||||||
|
}
|
||||||
|
await ep.play(filepath[segment]);
|
||||||
|
} while (++segment < this.text.length);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.logger.info(err, 'TaskSay:exec error');
|
this.logger.info(err, 'TaskSay:exec error');
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
},
|
},
|
||||||
"say": {
|
"say": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"text": "string",
|
"text": "string|array",
|
||||||
"loop": "number",
|
"loop": "number",
|
||||||
"synthesizer": "#synthesizer",
|
"synthesizer": "#synthesizer",
|
||||||
"earlyMedia": "boolean"
|
"earlyMedia": "boolean"
|
||||||
|
|||||||
@@ -117,21 +117,21 @@ class Task extends Emitter {
|
|||||||
const dSpec = specData.properties[dKey];
|
const dSpec = specData.properties[dKey];
|
||||||
debug(`Task:validate validating property ${dKey} with value ${JSON.stringify(dVal)}`);
|
debug(`Task:validate validating property ${dKey} with value ${JSON.stringify(dVal)}`);
|
||||||
|
|
||||||
if (typeof dSpec === 'string' && ['number', 'string', 'object', 'boolean'].includes(dSpec)) {
|
if (typeof dSpec === 'string' && dSpec === 'array') {
|
||||||
// simple types
|
|
||||||
if (typeof dVal !== specData.properties[dKey]) {
|
|
||||||
throw new Error(`${name}: property ${dKey} has invalid data type`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (typeof dSpec === 'string' && dSpec === 'array') {
|
|
||||||
if (!Array.isArray(dVal)) throw new Error(`${name}: property ${dKey} is not an array`);
|
if (!Array.isArray(dVal)) throw new Error(`${name}: property ${dKey} is not an array`);
|
||||||
}
|
}
|
||||||
else if (typeof dSpec === 'string' && dSpec.includes('|')) {
|
else if (typeof dSpec === 'string' && dSpec.includes('|')) {
|
||||||
const types = dSpec.split('|').map((t) => t.trim());
|
const types = dSpec.split('|').map((t) => t.trim());
|
||||||
if (!types.includes(typeof dVal)) {
|
if (!types.includes(typeof dVal) && !(types.includes('array') && Array.isArray(dVal))) {
|
||||||
throw new Error(`${name}: property ${dKey} has invalid data type, must be one of ${types}`);
|
throw new Error(`${name}: property ${dKey} has invalid data type, must be one of ${types}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (typeof dSpec === 'string' && ['number', 'string', 'object', 'boolean'].includes(dSpec)) {
|
||||||
|
// simple types
|
||||||
|
if (typeof dVal !== specData.properties[dKey]) {
|
||||||
|
throw new Error(`${name}: property ${dKey} has invalid data type`);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (Array.isArray(dSpec) && dSpec[0].startsWith('#')) {
|
else if (Array.isArray(dSpec) && dSpec[0].startsWith('#')) {
|
||||||
const name = dSpec[0].slice(1);
|
const name = dSpec[0].slice(1);
|
||||||
for (const item of dVal) {
|
for (const item of dVal) {
|
||||||
|
|||||||
9
test/data/good/say-text-array.json
Normal file
9
test/data/good/say-text-array.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"say": {
|
||||||
|
"text": ["hi there", "John"],
|
||||||
|
"synthesizer": {
|
||||||
|
"vendor": "google",
|
||||||
|
"language": "en-US"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
test/data/good/say.json
Normal file
9
test/data/good/say.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"say": {
|
||||||
|
"text": "hi there",
|
||||||
|
"synthesizer": {
|
||||||
|
"vendor": "google",
|
||||||
|
"language": "en-US"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,6 +39,12 @@ test('app payload parsing tests', (t) => {
|
|||||||
task = makeTask(logger, require('./data/good/pause'));
|
task = makeTask(logger, require('./data/good/pause'));
|
||||||
t.ok(task.name === 'pause', 'parsed pause');
|
t.ok(task.name === 'pause', 'parsed pause');
|
||||||
|
|
||||||
|
task = makeTask(logger, require('./data/good/say'));
|
||||||
|
t.ok(task.name === 'say', 'parsed say');
|
||||||
|
|
||||||
|
task = makeTask(logger, require('./data/good/say-text-array'));
|
||||||
|
t.ok(task.name === 'say', 'parsed say with multiple segments');
|
||||||
|
|
||||||
const alt = require('./data/good/alternate-syntax');
|
const alt = require('./data/good/alternate-syntax');
|
||||||
const normalize = require('../lib/utils/normalize-jambones');
|
const normalize = require('../lib/utils/normalize-jambones');
|
||||||
normalize(logger, alt).forEach((t) => {
|
normalize(logger, alt).forEach((t) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user