feat: record all calls (#352)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* fix jslint

* fix

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* fix: add file ext

* fix: record format

* fix outbound

* update to drachtio-fsmrf with support for multiple recording streams on a call

* enable DTMF during background listen recording

* fix merge commit

---------

Co-authored-by: Dave Horton <daveh@beachdognet.com>
This commit is contained in:
Hoan Luu Huu
2023-06-10 01:54:53 +07:00
committed by GitHub
parent ab0452879e
commit aad24744f3
11 changed files with 114 additions and 29 deletions

View File

@@ -137,6 +137,7 @@ class TaskDial extends Task {
get canReleaseMedia() {
const keepAnchor = this.data.anchorMedia ||
this.cs.isBackGroundListen ||
ANCHOR_MEDIA_ALWAYS ||
this.listenTask ||
this.transcribeTask ||

View File

@@ -3,6 +3,7 @@ const {TaskName, TaskPreconditions, ListenEvents, ListenStatus} = require('../ut
const makeTask = require('./make_task');
const moment = require('moment');
const MAX_PLAY_AUDIO_QUEUE_SIZE = 10;
const DTMF_SPAN_NAME = 'dtmf';
class TaskListen extends Task {
constructor(logger, opts, parentTask) {
@@ -29,6 +30,8 @@ class TaskListen extends Task {
get name() { return TaskName.Listen; }
set bugname(name) { this._bugname = name; }
async exec(cs, {ep}) {
await super.exec(cs);
this.ep = ep;
@@ -65,7 +68,8 @@ class TaskListen extends Task {
if (this.ep && this.ep.connected) {
this.logger.debug('TaskListen:kill closing websocket');
try {
await this.ep.forkAudioStop();
const args = this._bugname ? [this._bugname] : [];
await this.ep.forkAudioStop(...args);
this.logger.debug('TaskListen:kill successfully closed websocket');
} catch (err) {
this.logger.info(err, 'TaskListen:kill');
@@ -85,13 +89,16 @@ class TaskListen extends Task {
async updateListen(status) {
if (!this.killed && this.ep && this.ep.connected) {
const args = this._bugname ? [this._bugname] : [];
this.logger.info(`TaskListen:updateListen status ${status}`);
switch (status) {
case ListenStatus.Pause:
await this.ep.forkAudioPause().catch((err) => this.logger.info(err, 'TaskListen: error pausing audio'));
await this.ep.forkAudioPause(...args)
.catch((err) => this.logger.info(err, 'TaskListen: error pausing audio'));
break;
case ListenStatus.Resume:
await this.ep.forkAudioResume().catch((err) => this.logger.info(err, 'TaskListen: error resuming audio'));
await this.ep.forkAudioResume(...args)
.catch((err) => this.logger.info(err, 'TaskListen: error resuming audio'));
break;
}
}
@@ -120,6 +127,7 @@ class TaskListen extends Task {
wsUrl: this.hook.url,
mixType: this.mixType,
sampling: this.sampleRate,
...(this._bugname && {bugname: this._bugname}),
metadata
});
this.recordStartTime = moment();
@@ -161,12 +169,21 @@ class TaskListen extends Task {
}
_onDtmf(ep, evt) {
this.logger.debug({evt}, `TaskListen:_onDtmf received dtmf ${evt.dtmf}`);
const {dtmf, duration} = evt;
this.logger.debug({evt}, `TaskListen:_onDtmf received dtmf ${dtmf}`);
if (this.passDtmf && this.ep?.connected) {
const obj = {event: 'dtmf', dtmf: evt.dtmf, duration: evt.duration};
this.ep.forkAudioSendText(obj)
const obj = {event: 'dtmf', dtmf, duration};
const args = this._bugname ? [this._bugname, obj] : [obj];
this.ep.forkAudioSendText(...args)
.catch((err) => this.logger.info({err}, 'TaskListen:_onDtmf error sending dtmf'));
}
/* add a child span for the dtmf event */
const msDuration = Math.floor((duration / 8000) * 1000);
const {span} = this.startChildSpan(`${DTMF_SPAN_NAME}:${dtmf}`);
span.setAttributes({dtmf, duration: `${msDuration}ms`});
span.end();
if (evt.dtmf === this.finishOnKey) {
this.logger.info(`TaskListen:_onDtmf terminating task due to dtmf ${evt.dtmf}`);
this.results.digits = evt.dtmf;
@@ -192,7 +209,15 @@ class TaskListen extends Task {
try {
const results = await ep.play(evt.file);
logger.debug(`Finished playing file, result: ${JSON.stringify(results)}`);
ep.forkAudioSendText({type: 'playDone', data: Object.assign({id: evt.id}, results)});
const obj = {
type: 'playDone',
data: {
id: evt.id,
...results
}
};
const args = this._bugname ? [this._bugname, obj] : [obj];
ep.forkAudioSendText(...args);
} catch (err) {
logger.error({err}, 'Error playing file');
}