From d7dcdb1d0c6a4ede50dda967bef1fb173cd72b27 Mon Sep 17 00:00:00 2001 From: Hoan Luu Huu <110280845+xquanluu@users.noreply.github.com> Date: Thu, 3 Aug 2023 20:49:44 +0700 Subject: [PATCH] Continuos ASR for transcribe (#398) * asrTimeout * fix jslint * change log * fix interrim --- lib/tasks/transcribe.js | 42 ++++++++++++++++++++++++++++++++++++++++ test/transcribe-tests.js | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/lib/tasks/transcribe.js b/lib/tasks/transcribe.js index 1f858d0c..869e5e07 100644 --- a/lib/tasks/transcribe.js +++ b/lib/tasks/transcribe.js @@ -1,4 +1,5 @@ const Task = require('./task'); +const assert = require('assert'); const { TaskName, TaskPreconditions, @@ -56,6 +57,12 @@ class TaskTranscribe extends Task { this._sonioxTranscripts = []; this.childSpan = [null, null]; + + // Continuos asr timeout + this.asrTimeout = typeof this.data.recognizer.asrTimeout === 'number' ? this.data.recognizer.asrTimeout * 1000 : 0; + this.isContinuousAsr = this.asrTimeout > 0; + /* buffer speech for continuous asr */ + this._bufferedTranscripts = []; } get name() { return TaskName.Transcribe; } @@ -308,6 +315,26 @@ class TaskTranscribe extends Task { } } + if (this.isContinuousAsr && evt.is_final) { + this._bufferedTranscripts.push(evt); + this._startAsrTimer(channel); + } else { + await this._resolve(channel, evt); + } + } + + _compileTranscripts() { + assert(this._bufferedTranscripts.length); + const evt = this._bufferedTranscripts[0]; + let t = ''; + for (const a of this._bufferedTranscripts) { + t += ` ${a.alternatives[0].transcript}`; + } + evt.alternatives[0].transcript = t.trim(); + return evt; + } + + async _resolve(channel, evt) { /* we've got a transcript, so end the otel child span for this channel */ if (this.childSpan[channel - 1] && this.childSpan[channel - 1].span) { this.childSpan[channel - 1].span.setAttributes({ @@ -485,7 +512,22 @@ class TaskTranscribe extends Task { this.notifyError({msg: 'ASR error', details:`Custom speech vendor ${this.vendor} error: ${evt.error}`}); } + _startAsrTimer(channel) { + assert(this.isContinuousAsr); + this._clearAsrTimer(channel); + this._asrTimer = setTimeout(() => { + this.logger.debug(`TaskTranscribe:_startAsrTimer - asr timer went off for channel: ${channel}`); + const evt = this._compileTranscripts(); + this._bufferedTranscripts = []; + this._resolve(channel, evt); + }, this.asrTimeout); + this.logger.debug(`TaskTranscribe:_startAsrTimer: set for ${this.asrTimeout}ms for channel ${channel}`); + } + _clearAsrTimer(channel) { + if (this._asrTimer) clearTimeout(this._asrTimer); + this._asrTimer = null; + } } module.exports = TaskTranscribe; diff --git a/test/transcribe-tests.js b/test/transcribe-tests.js index 09da543a..ecd87511 100644 --- a/test/transcribe-tests.js +++ b/test/transcribe-tests.js @@ -210,6 +210,44 @@ test('\'transcribe\' test - soniox', async(t) => { t.ok(obj.body.speech.alternatives[0].transcript.toLowerCase().startsWith('i\'d like to speak to customer support'), 'transcribe: succeeds when using soniox credentials'); + disconnect(); + } catch (err) { + console.log(`error received: ${err}`); + disconnect(); + t.error(err); + } +}); + +test('\'transcribe\' test - google with asrTimeout', async(t) => { + if (!GCP_JSON_KEY) { + t.pass('skipping google tests'); + return t.end(); + } + clearModule.all(); + const {srf, disconnect} = require('../app'); + + try { + await connect(srf); + // GIVEN + let verbs = [ + { + "verb": "transcribe", + "recognizer": { + "vendor": "google", + "hints": ["customer support", "sales", "human resources", "HR"], + "asrTimeout": 4 + }, + "transcriptionHook": "/transcriptionHook" + } + ]; + let from = "gather_success"; + await provisionCallHook(from, verbs); + // THEN + await sippUac('uac-gather-account-creds-success.xml', '172.38.0.10', from); + let obj = await getJSON(`http://127.0.0.1:3100/lastRequest/${from}_actionHook`); + t.ok(obj.body.speech.alternatives[0].transcript.toLowerCase().startsWith('i\'d like to speak to customer support'), + 'transcribe: succeeds when using google credentials'); + disconnect(); } catch (err) { console.log(`error received: ${err}`);