mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-20 08:40:38 +00:00
wip: implemented listen, transcribe, play
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
const Task = require('./task');
|
||||
const {TaskName, TaskPreconditions} = require('../utils/constants');
|
||||
const {TaskName, TaskPreconditions, TranscriptionEvents} = require('../utils/constants');
|
||||
const makeTask = require('./make_task');
|
||||
const assert = require('assert');
|
||||
|
||||
@@ -19,6 +19,7 @@ class TaskGather extends Task {
|
||||
this.timeout = (this.timeout || 5) * 1000;
|
||||
this.language = this.language || 'en-US';
|
||||
this.digitBuffer = '';
|
||||
//this._earlyMedia = this.data.earlyMedia === true;
|
||||
|
||||
if (this.say) {
|
||||
this.sayTask = makeTask(this.logger, {say: this.say});
|
||||
@@ -27,6 +28,11 @@ class TaskGather extends Task {
|
||||
|
||||
get name() { return TaskName.Gather; }
|
||||
|
||||
get earlyMedia() {
|
||||
return (this.sayTask && this.sayTask.earlyMedia) ||
|
||||
(this.playTask && this.playTask.earlyMedia);
|
||||
}
|
||||
|
||||
async exec(cs, ep) {
|
||||
this.ep = ep;
|
||||
this.actionHook = cs.actionHook;
|
||||
@@ -35,33 +41,15 @@ class TaskGather extends Task {
|
||||
try {
|
||||
if (this.sayTask) {
|
||||
this.sayTask.exec(cs, ep); // kicked off, _not_ waiting for it to complete
|
||||
this.sayTask.on('playDone', this._onPlayDone.bind(this, ep));
|
||||
this.sayTask.on('playDone', (err) => {
|
||||
if (this.taskInProgress) this._startTimer();
|
||||
});
|
||||
}
|
||||
else this._startTimer();
|
||||
|
||||
if (this.input.includes('speech')) {
|
||||
const opts = {
|
||||
GOOGLE_SPEECH_USE_ENHANCED: true,
|
||||
GOOGLE_SPEECH_SINGLE_UTTERANCE: true,
|
||||
GOOGLE_SPEECH_MODEL: 'phone_call'
|
||||
};
|
||||
if (this.hints) {
|
||||
Object.assign(opts, {'GOOGLE_SPEECH_HINTS': this.hints.join(',')});
|
||||
}
|
||||
if (this.profanityFilter === true) {
|
||||
Object.assign(opts, {'GOOGLE_SPEECH_PROFANITY_FILTER': true});
|
||||
}
|
||||
this.logger.debug(`setting freeswitch vars ${JSON.stringify(opts)}`);
|
||||
await ep.set(opts)
|
||||
.catch((err) => this.logger.info(err, 'Error set'));
|
||||
ep.addCustomEventListener('google_transcribe::transcription', this._onTranscription.bind(this, ep));
|
||||
ep.addCustomEventListener('google_transcribe::no_audio_detected', this._onNoAudioDetected.bind(this, ep));
|
||||
ep.addCustomEventListener('google_transcribe::max_duration_exceeded', this._onMaxDuration.bind(this, ep));
|
||||
this.logger.debug('starting transcription');
|
||||
ep.startTranscription({
|
||||
interim: this.partialResultCallback ? true : false,
|
||||
language: this.language
|
||||
}).catch((err) => this.logger.error(err, 'TaskGather:exec error starting transcription'));
|
||||
await this._initSpeech(ep);
|
||||
this._startTranscribing(ep);
|
||||
}
|
||||
|
||||
if (this.input.includes('dtmf')) {
|
||||
@@ -73,10 +61,12 @@ class TaskGather extends Task {
|
||||
this.logger.error(err, 'TaskGather:exec error');
|
||||
}
|
||||
this.taskInProgress = false;
|
||||
ep.removeAllListeners();
|
||||
ep.removeCustomEventListener(TranscriptionEvents.Transcription);
|
||||
ep.removeCustomEventListener(TranscriptionEvents.EndOfUtterance);
|
||||
}
|
||||
|
||||
kill() {
|
||||
super.kill();
|
||||
this._killAudio();
|
||||
this._resolve('killed');
|
||||
}
|
||||
@@ -85,12 +75,6 @@ class TaskGather extends Task {
|
||||
return new Promise((resolve) => this.resolver = resolve);
|
||||
}
|
||||
|
||||
_onPlayDone(ep, err, evt) {
|
||||
if (err || !this.taskInProgress) return;
|
||||
this.logger.debug(evt, 'TaskGather:_onPlayDone, starting input timer');
|
||||
this._startTimer();
|
||||
}
|
||||
|
||||
_onDtmf(ep, evt) {
|
||||
this.logger.debug(evt, 'TaskGather:_onDtmf');
|
||||
if (evt.dtmf === this.finishOnKey) this._resolve('dtmf-terminator-key');
|
||||
@@ -101,6 +85,32 @@ class TaskGather extends Task {
|
||||
this._killAudio();
|
||||
}
|
||||
|
||||
async _initSpeech(ep) {
|
||||
const opts = {
|
||||
GOOGLE_SPEECH_USE_ENHANCED: true,
|
||||
GOOGLE_SPEECH_SINGLE_UTTERANCE: true,
|
||||
GOOGLE_SPEECH_MODEL: 'phone_call'
|
||||
};
|
||||
if (this.hints) {
|
||||
Object.assign(opts, {'GOOGLE_SPEECH_HINTS': this.hints.join(',')});
|
||||
}
|
||||
if (this.profanityFilter === true) {
|
||||
Object.assign(opts, {'GOOGLE_SPEECH_PROFANITY_FILTER': true});
|
||||
}
|
||||
this.logger.debug(`setting freeswitch vars ${JSON.stringify(opts)}`);
|
||||
await ep.set(opts)
|
||||
.catch((err) => this.logger.info(err, 'Error set'));
|
||||
ep.addCustomEventListener(TranscriptionEvents.Transcription, this._onTranscription.bind(this, ep));
|
||||
ep.addCustomEventListener(TranscriptionEvents.EndOfUtterance, this._onEndOfUtterance.bind(this, ep));
|
||||
}
|
||||
|
||||
_startTranscribing(ep) {
|
||||
ep.startTranscription({
|
||||
interim: this.partialResultCallback ? true : false,
|
||||
language: this.language
|
||||
}).catch((err) => this.logger.error(err, 'TaskGather:_startTranscribing error'));
|
||||
}
|
||||
|
||||
_startTimer() {
|
||||
assert(!this._timeoutTimer);
|
||||
this._timeoutTimer = setTimeout(() => this._resolve('timeout'), this.timeout);
|
||||
@@ -123,6 +133,8 @@ class TaskGather extends Task {
|
||||
_onTranscription(ep, evt) {
|
||||
this.logger.debug(evt, 'TaskGather:_onTranscription');
|
||||
if (evt.is_final) {
|
||||
ep.removeCustomEventListener(TranscriptionEvents.Transcription);
|
||||
ep.removeCustomEventListener(TranscriptionEvents.EndOfUtterance);
|
||||
this._resolve('speech', evt);
|
||||
}
|
||||
else if (this.partialResultCallback) {
|
||||
@@ -131,11 +143,9 @@ class TaskGather extends Task {
|
||||
});
|
||||
}
|
||||
}
|
||||
_onNoAudioDetected(ep, evt) {
|
||||
this.logger.info(evt, 'TaskGather:_onNoAudioDetected');
|
||||
}
|
||||
_onMaxDuration(ep, evt) {
|
||||
this.logger.info(evt, 'TaskGather:_onMaxDuration');
|
||||
_onEndOfUtterance(ep, evt) {
|
||||
this.logger.info(evt, 'TaskGather:_onEndOfUtterance');
|
||||
this._startTranscribing(ep);
|
||||
}
|
||||
|
||||
_resolve(reason, evt) {
|
||||
|
||||
Reference in New Issue
Block a user