@fonoster/voice 0.2.24 → 0.2.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.d.ts +2 -0
- package/dist/server.js +6 -2
- package/dist/tracer.d.ts +10 -0
- package/dist/tracer.js +56 -0
- package/dist/types.d.ts +3 -0
- package/dist/voice.d.ts +3 -1
- package/dist/voice.js +61 -10
- package/package.json +14 -5
package/dist/server.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ServerConfig } from "./types";
|
|
2
2
|
import { Plugin } from "@fonoster/common";
|
|
3
|
+
import { VoiceTracer } from "./tracer";
|
|
3
4
|
export default class VoiceServer {
|
|
4
5
|
config: ServerConfig;
|
|
5
6
|
plugins: {};
|
|
7
|
+
voiceTracer: VoiceTracer;
|
|
6
8
|
constructor(config?: ServerConfig);
|
|
7
9
|
/**
|
|
8
10
|
* Add tts or asr plugin.
|
package/dist/server.js
CHANGED
|
@@ -10,6 +10,7 @@ const path_1 = require("path");
|
|
|
10
10
|
const fs_1 = __importDefault(require("fs"));
|
|
11
11
|
const os_1 = __importDefault(require("os"));
|
|
12
12
|
const pubsub_js_1 = __importDefault(require("pubsub-js"));
|
|
13
|
+
const tracer_1 = require("./tracer");
|
|
13
14
|
const merge = require("deepmerge");
|
|
14
15
|
const app = (0, express_1.default)();
|
|
15
16
|
app.use(express_1.default.json());
|
|
@@ -18,7 +19,8 @@ const defaultServerConfig = {
|
|
|
18
19
|
base: "/",
|
|
19
20
|
port: 3000,
|
|
20
21
|
bind: "0.0.0.0",
|
|
21
|
-
pathToFiles: os_1.default.tmpdir()
|
|
22
|
+
pathToFiles: os_1.default.tmpdir(),
|
|
23
|
+
otlSpanExporters: []
|
|
22
24
|
};
|
|
23
25
|
class VoiceServer {
|
|
24
26
|
constructor(config = defaultServerConfig) {
|
|
@@ -54,7 +56,9 @@ class VoiceServer {
|
|
|
54
56
|
res.send("pong");
|
|
55
57
|
});
|
|
56
58
|
app.post(path_1.posix.join(this.config.base), async (req, res) => {
|
|
57
|
-
|
|
59
|
+
this.voiceTracer = new tracer_1.VoiceTracer(this.config.otlSpanExporters);
|
|
60
|
+
this.voiceTracer.init();
|
|
61
|
+
const response = new voice_1.default(req.body, this.voiceTracer);
|
|
58
62
|
response.plugins = this.plugins;
|
|
59
63
|
handler(req.body, response);
|
|
60
64
|
res.end();
|
package/dist/tracer.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Context, Span, Tracer } from "@opentelemetry/api";
|
|
2
|
+
export declare class VoiceTracer {
|
|
3
|
+
callTracer: Tracer;
|
|
4
|
+
parentSpan: Span;
|
|
5
|
+
ctx: Context;
|
|
6
|
+
constructor(otlSpanExporters: Array<any>);
|
|
7
|
+
init(): void;
|
|
8
|
+
close(): void;
|
|
9
|
+
createSpan(name: string): Span;
|
|
10
|
+
}
|
package/dist/tracer.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.VoiceTracer = void 0;
|
|
7
|
+
/*
|
|
8
|
+
* Copyright (C) 2021 by Fonoster Inc (https://fonoster.com)
|
|
9
|
+
* http://github.com/fonoster/fonoster
|
|
10
|
+
*
|
|
11
|
+
* This file is part of Fonoster
|
|
12
|
+
*
|
|
13
|
+
* Licensed under the MIT License (the "License");
|
|
14
|
+
* you may not use this file except in compliance with
|
|
15
|
+
* the License. You may obtain a copy of the License at
|
|
16
|
+
*
|
|
17
|
+
* https://opensource.org/licenses/MIT
|
|
18
|
+
*
|
|
19
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
20
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
21
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
22
|
+
* See the License for the specific language governing permissions and
|
|
23
|
+
* limitations under the License.
|
|
24
|
+
*/
|
|
25
|
+
const api_1 = __importDefault(require("@opentelemetry/api"));
|
|
26
|
+
const resources_1 = require("@opentelemetry/resources");
|
|
27
|
+
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
|
|
28
|
+
const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
|
|
29
|
+
const { NodeTracerProvider } = require("@opentelemetry/node");
|
|
30
|
+
class VoiceTracer {
|
|
31
|
+
constructor(otlSpanExporters) {
|
|
32
|
+
// Configure span processor to send spans to the exporter
|
|
33
|
+
const provider = new NodeTracerProvider({
|
|
34
|
+
resource: new resources_1.Resource({
|
|
35
|
+
[semantic_conventions_1.SemanticResourceAttributes.SERVICE_NAME]: "voice-service"
|
|
36
|
+
})
|
|
37
|
+
});
|
|
38
|
+
for (const exp of otlSpanExporters) {
|
|
39
|
+
const exporter = new exp.exporter(exp.config);
|
|
40
|
+
provider.addSpanProcessor(new sdk_trace_base_1.BatchSpanProcessor(exporter));
|
|
41
|
+
}
|
|
42
|
+
provider.register();
|
|
43
|
+
this.callTracer = api_1.default.trace.getTracer("call_tracer");
|
|
44
|
+
}
|
|
45
|
+
init() {
|
|
46
|
+
this.parentSpan = this.callTracer.startSpan("call");
|
|
47
|
+
this.ctx = api_1.default.trace.setSpan(api_1.default.context.active(), this.parentSpan);
|
|
48
|
+
}
|
|
49
|
+
close() {
|
|
50
|
+
this.parentSpan.end();
|
|
51
|
+
}
|
|
52
|
+
createSpan(name) {
|
|
53
|
+
return this.callTracer.startSpan(name, undefined, this.ctx);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.VoiceTracer = VoiceTracer;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MeterProvider } from "@opentelemetry/sdk-metrics-base";
|
|
1
2
|
export interface VoiceRequest {
|
|
2
3
|
accessKeyId: string;
|
|
3
4
|
sessionToken: string;
|
|
@@ -13,6 +14,8 @@ export interface ServerConfig {
|
|
|
13
14
|
port?: number;
|
|
14
15
|
base?: string;
|
|
15
16
|
pathToFiles?: string;
|
|
17
|
+
otlSpanExporters?: Array<any>;
|
|
18
|
+
meterProvider?: MeterProvider;
|
|
16
19
|
}
|
|
17
20
|
export interface VoiceEventData {
|
|
18
21
|
type: string;
|
package/dist/voice.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { SGatherStream } from "./sgather/types";
|
|
|
11
11
|
import { DtmfOptions } from "./dtmf/types";
|
|
12
12
|
import { DialOptions } from "./dial/types";
|
|
13
13
|
import StreamStatus from "./dial/status_stream";
|
|
14
|
+
import { VoiceTracer } from "./tracer";
|
|
14
15
|
/**
|
|
15
16
|
* @classdesc Use the VoiceResponse object, to construct advance Interactive
|
|
16
17
|
* Voice Response (IVR) applications.
|
|
@@ -31,13 +32,14 @@ import StreamStatus from "./dial/status_stream";
|
|
|
31
32
|
export default class VoiceResponse {
|
|
32
33
|
request: VoiceRequest;
|
|
33
34
|
plugins: {};
|
|
35
|
+
voiceTracer: VoiceTracer;
|
|
34
36
|
/**
|
|
35
37
|
* Constructs a new VoiceResponse object.
|
|
36
38
|
*
|
|
37
39
|
* @param {VoiceRequest} request - Options to indicate the objects endpoint
|
|
38
40
|
* @see module:core:APIClient
|
|
39
41
|
*/
|
|
40
|
-
constructor(request: VoiceRequest);
|
|
42
|
+
constructor(request: VoiceRequest, voiceTracer: VoiceTracer);
|
|
41
43
|
/**
|
|
42
44
|
* Adds a tts or asr plugin. Only one type of plugin can be attached.
|
|
43
45
|
*
|
package/dist/voice.js
CHANGED
|
@@ -60,8 +60,9 @@ class VoiceResponse {
|
|
|
60
60
|
* @param {VoiceRequest} request - Options to indicate the objects endpoint
|
|
61
61
|
* @see module:core:APIClient
|
|
62
62
|
*/
|
|
63
|
-
constructor(request) {
|
|
63
|
+
constructor(request, voiceTracer) {
|
|
64
64
|
this.request = request;
|
|
65
|
+
this.voiceTracer = voiceTracer;
|
|
65
66
|
this.plugins = {};
|
|
66
67
|
}
|
|
67
68
|
/**
|
|
@@ -92,7 +93,9 @@ class VoiceResponse {
|
|
|
92
93
|
* }
|
|
93
94
|
*/
|
|
94
95
|
async play(media, options = {}) {
|
|
96
|
+
const span = this.voiceTracer.createSpan("play");
|
|
95
97
|
await new play_1.default(this.request).run(media, options);
|
|
98
|
+
span.end();
|
|
96
99
|
}
|
|
97
100
|
/**
|
|
98
101
|
* Converts a text into a sound and sends sound to media server. To use this verb, you must
|
|
@@ -118,9 +121,17 @@ class VoiceResponse {
|
|
|
118
121
|
(0, asserts_1.assertPluginExist)(this, "tts");
|
|
119
122
|
const tts = this.plugins["tts"];
|
|
120
123
|
// It should return the filename and the generated file location
|
|
124
|
+
const main = this.voiceTracer.createSpan("play");
|
|
125
|
+
const span = this.voiceTracer.createSpan("synthetize");
|
|
121
126
|
const result = await tts.synthetize(text, options);
|
|
127
|
+
span.setAttribute("text", text);
|
|
128
|
+
span.setAttribute("options", JSON.stringify(options));
|
|
129
|
+
span.end();
|
|
122
130
|
const media = `sound:${this.request.selfEndpoint}/tts/${result.filename}`;
|
|
123
131
|
await new play_1.default(this.request).run(media, options);
|
|
132
|
+
main.setAttribute("media", media);
|
|
133
|
+
main.setAttribute("options", JSON.stringify(options));
|
|
134
|
+
main.end();
|
|
124
135
|
}
|
|
125
136
|
/**
|
|
126
137
|
* Waits for data entry from the user's keypad or from a speech provider.
|
|
@@ -147,7 +158,11 @@ class VoiceResponse {
|
|
|
147
158
|
(0, asserts_1.assertPluginExist)(this, "asr");
|
|
148
159
|
asr = this.plugins["asr"];
|
|
149
160
|
}
|
|
150
|
-
|
|
161
|
+
const span = this.voiceTracer.createSpan("gather");
|
|
162
|
+
const result = await new gather_1.default(this.request, asr).run(options);
|
|
163
|
+
span.setAttribute("options", JSON.stringify(options));
|
|
164
|
+
span.end();
|
|
165
|
+
return result;
|
|
151
166
|
}
|
|
152
167
|
/**
|
|
153
168
|
* Waits for data entry from the user's keypad or from a stream speech provider. This command is different from `gather`
|
|
@@ -197,7 +212,11 @@ class VoiceResponse {
|
|
|
197
212
|
* }
|
|
198
213
|
*/
|
|
199
214
|
async dtmf(options) {
|
|
200
|
-
|
|
215
|
+
const span = this.voiceTracer.createSpan("dtmf");
|
|
216
|
+
const result = await new dtmf_1.default(this.request).run(options);
|
|
217
|
+
span.setAttribute("options", JSON.stringify(options));
|
|
218
|
+
span.end();
|
|
219
|
+
return result;
|
|
201
220
|
}
|
|
202
221
|
/**
|
|
203
222
|
* Forwards the call to an Agent or the PSTN.
|
|
@@ -219,7 +238,12 @@ class VoiceResponse {
|
|
|
219
238
|
* }
|
|
220
239
|
*/
|
|
221
240
|
async dial(destination, options) {
|
|
222
|
-
|
|
241
|
+
const span = this.voiceTracer.createSpan("dial");
|
|
242
|
+
const result = await new dial_1.default(this.request).run(destination, options);
|
|
243
|
+
span.setAttribute("destination", destination);
|
|
244
|
+
span.setAttribute("options", JSON.stringify(options));
|
|
245
|
+
span.end();
|
|
246
|
+
return result;
|
|
223
247
|
}
|
|
224
248
|
/**
|
|
225
249
|
* Returns a PlaybackControl control object.
|
|
@@ -243,7 +267,11 @@ class VoiceResponse {
|
|
|
243
267
|
* }
|
|
244
268
|
*/
|
|
245
269
|
playback(playbackId) {
|
|
246
|
-
|
|
270
|
+
const span = this.voiceTracer.createSpan("playback");
|
|
271
|
+
const result = new playback_1.PlaybackControl(this.request, playbackId);
|
|
272
|
+
span.setAttribute("playbackId", playbackId);
|
|
273
|
+
span.end();
|
|
274
|
+
return result;
|
|
247
275
|
}
|
|
248
276
|
/**
|
|
249
277
|
* Listens event publication.
|
|
@@ -284,7 +312,11 @@ class VoiceResponse {
|
|
|
284
312
|
* }
|
|
285
313
|
*/
|
|
286
314
|
async mute(options) {
|
|
287
|
-
|
|
315
|
+
const span = this.voiceTracer.createSpan("mute");
|
|
316
|
+
const result = new mute_1.default(this.request).run(options);
|
|
317
|
+
span.setAttribute("options", JSON.stringify(options));
|
|
318
|
+
span.end();
|
|
319
|
+
await result;
|
|
288
320
|
}
|
|
289
321
|
/**
|
|
290
322
|
* Unmutes a channel.
|
|
@@ -300,7 +332,11 @@ class VoiceResponse {
|
|
|
300
332
|
* }
|
|
301
333
|
*/
|
|
302
334
|
async unmute(options) {
|
|
303
|
-
|
|
335
|
+
const span = this.voiceTracer.createSpan("unmute");
|
|
336
|
+
const result = new unmute_1.default(this.request).run(options);
|
|
337
|
+
span.setAttribute("options", JSON.stringify(options));
|
|
338
|
+
span.end();
|
|
339
|
+
await result;
|
|
304
340
|
}
|
|
305
341
|
/**
|
|
306
342
|
* Answer the communication channel. Before running any other verb you
|
|
@@ -314,7 +350,10 @@ class VoiceResponse {
|
|
|
314
350
|
* }
|
|
315
351
|
*/
|
|
316
352
|
async answer() {
|
|
317
|
-
|
|
353
|
+
const span = this.voiceTracer.createSpan("answer");
|
|
354
|
+
const result = new answer_1.default(this.request).run();
|
|
355
|
+
span.end();
|
|
356
|
+
await result;
|
|
318
357
|
}
|
|
319
358
|
/**
|
|
320
359
|
* Terminates the communication channel.
|
|
@@ -327,7 +366,12 @@ class VoiceResponse {
|
|
|
327
366
|
* }
|
|
328
367
|
*/
|
|
329
368
|
async hangup() {
|
|
330
|
-
|
|
369
|
+
const span = this.voiceTracer.createSpan("hangup");
|
|
370
|
+
const result = new hangup_1.default(this.request).run();
|
|
371
|
+
span.end();
|
|
372
|
+
// Need to close or the span will be lost
|
|
373
|
+
this.voiceTracer.close();
|
|
374
|
+
await result;
|
|
331
375
|
}
|
|
332
376
|
/**
|
|
333
377
|
* Records the current channel and uploads the file to the storage subsystem.
|
|
@@ -348,17 +392,24 @@ class VoiceResponse {
|
|
|
348
392
|
* }
|
|
349
393
|
*/
|
|
350
394
|
async record(options) {
|
|
351
|
-
|
|
395
|
+
const span = this.voiceTracer.createSpan("record");
|
|
396
|
+
const result = await new record_1.default(this.request).run(options);
|
|
397
|
+
span.end();
|
|
398
|
+
return result;
|
|
352
399
|
}
|
|
353
400
|
// Requests media from Media server
|
|
354
401
|
async openMediaPipe() {
|
|
402
|
+
const span = this.voiceTracer.createSpan("openMediaPipe");
|
|
355
403
|
const genericVerb = new verb_1.Verb(this.request);
|
|
356
404
|
await (0, utils_1.startMediaTransfer)(genericVerb, this.request.sessionId);
|
|
405
|
+
span.end();
|
|
357
406
|
}
|
|
358
407
|
// Requests media stop from Media server
|
|
359
408
|
async closeMediaPipe() {
|
|
409
|
+
const span = this.voiceTracer.createSpan("stopMediaTransfer");
|
|
360
410
|
const genericVerb = new verb_1.Verb(this.request);
|
|
361
411
|
await (0, utils_1.stopMediaTransfer)(genericVerb, this.request.sessionId);
|
|
412
|
+
span.end();
|
|
362
413
|
}
|
|
363
414
|
}
|
|
364
415
|
exports.default = VoiceResponse;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fonoster/voice",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.32",
|
|
4
4
|
"description": "Voice verbs",
|
|
5
5
|
"author": "Pedro Sanders <psanders@fonoster.com>",
|
|
6
6
|
"homepage": "https://github.com/fonoster/fonoster#readme",
|
|
@@ -29,9 +29,18 @@
|
|
|
29
29
|
"url": "https://github.com/fonoster/fonoster/issues"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@fonoster/common": "^0.2.
|
|
33
|
-
"@fonoster/logger": "^0.2.
|
|
34
|
-
"
|
|
32
|
+
"@fonoster/common": "^0.2.32",
|
|
33
|
+
"@fonoster/logger": "^0.2.32",
|
|
34
|
+
"@opentelemetry/api": "^1.0.2",
|
|
35
|
+
"@opentelemetry/node": "^0.24.0",
|
|
36
|
+
"@opentelemetry/plugin-express": "^0.15.0",
|
|
37
|
+
"@opentelemetry/plugin-http": "^0.18.2",
|
|
38
|
+
"@opentelemetry/plugin-https": "^0.18.2",
|
|
39
|
+
"@opentelemetry/resources": "0.25.0",
|
|
40
|
+
"@opentelemetry/sdk-metrics-base": "0.25.0",
|
|
41
|
+
"@opentelemetry/sdk-trace-base": "0.25.0",
|
|
42
|
+
"@opentelemetry/semantic-conventions": "0.25.0",
|
|
43
|
+
"@opentelemetry/tracing": "^0.24.0",
|
|
35
44
|
"deepmerge": "^4.2.2",
|
|
36
45
|
"express": "^4.17.1",
|
|
37
46
|
"express-ws": "^4.0.0",
|
|
@@ -39,7 +48,7 @@
|
|
|
39
48
|
"pubsub-js": "^1.9.3",
|
|
40
49
|
"sync": "^0.2.5"
|
|
41
50
|
},
|
|
42
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "810f3ee3a90e495e78baf7d54e442d366566b434",
|
|
43
52
|
"devDependencies": {
|
|
44
53
|
"@types/pubsub-js": "^1.8.2"
|
|
45
54
|
}
|