@picovoice/eagle-web 2.0.0 → 3.0.0

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.
@@ -1,405 +1,443 @@
1
- /*
2
- Copyright 2023-2025 Picovoice Inc.
3
-
4
- You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
5
- file accompanying this source.
6
-
7
- Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
8
- an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
9
- specific language governing permissions and limitations under the License.
10
- */
11
-
12
- import PvWorker from 'web-worker:./eagle_profiler_worker_handler.ts';
13
-
14
- import {
15
- EagleModel,
16
- EagleProfile,
17
- EagleProfilerEnrollResult,
18
- EagleProfilerOptions,
19
- EagleProfilerWorkerEnrollResponse,
20
- EagleProfilerWorkerExportResponse,
21
- EagleProfilerWorkerInitResponse,
22
- EagleProfilerWorkerReleaseResponse,
23
- EagleProfilerWorkerResetResponse,
24
- PvStatus,
25
- } from './types';
26
- import { loadModel } from '@picovoice/web-utils';
27
- import { pvStatusToException } from "./eagle_errors";
28
-
29
- export class EagleProfilerWorker {
30
- private readonly _worker: Worker;
31
- private readonly _minEnrollSamples: number;
32
- private readonly _sampleRate: number;
33
- private readonly _version: string;
34
-
35
- private static _wasmSimd: string;
36
- private static _wasmSimdLib: string;
37
- private static _wasmPThread: string;
38
- private static _wasmPThreadLib: string;
39
-
40
- private static _sdk: string = 'web';
41
-
42
- private constructor(
43
- worker: Worker,
44
- minEnrollSamples: number,
45
- sampleRate: number,
46
- version: string
47
- ) {
48
- this._worker = worker;
49
- this._minEnrollSamples = minEnrollSamples;
50
- this._sampleRate = sampleRate;
51
- this._version = version;
52
- }
53
-
54
- /**
55
- * The minimum length of the input pcm required by `.enroll()`.
56
- */
57
- get minEnrollSamples(): number {
58
- return this._minEnrollSamples;
59
- }
60
-
61
- /**
62
- * Audio sample rate required by Eagle.
63
- */
64
- get sampleRate(): number {
65
- return this._sampleRate;
66
- }
67
-
68
- /**
69
- * Version of Eagle.
70
- */
71
- get version(): string {
72
- return this._version;
73
- }
74
-
75
- /**
76
- * Set base64 wasm file with SIMD feature.
77
- * @param wasmSimd Base64'd wasm SIMD file to use to initialize wasm.
78
- */
79
- public static setWasmSimd(wasmSimd: string): void {
80
- if (this._wasmSimd === undefined) {
81
- this._wasmSimd = wasmSimd;
82
- }
83
- }
84
-
85
- /**
86
- * Set base64 wasm file with SIMD feature in text format.
87
- * @param wasmSimdLib Base64'd wasm SIMD file in text format.
88
- */
89
- public static setWasmSimdLib(wasmSimdLib: string): void {
90
- if (this._wasmSimdLib === undefined) {
91
- this._wasmSimdLib = wasmSimdLib;
92
- }
93
- }
94
-
95
- /**
96
- * Set base64 wasm file with SIMD and pthread feature.
97
- * @param wasmPThread Base64'd wasm file to use to initialize wasm.
98
- */
99
- public static setWasmPThread(wasmPThread: string): void {
100
- if (this._wasmPThread === undefined) {
101
- this._wasmPThread = wasmPThread;
102
- }
103
- }
104
-
105
- /**
106
- * Set base64 SIMD and thread wasm file in text format.
107
- * @param wasmPThreadLib Base64'd wasm file in text format.
108
- */
109
- public static setWasmPThreadLib(wasmPThreadLib: string): void {
110
- if (this._wasmPThreadLib === undefined) {
111
- this._wasmPThreadLib = wasmPThreadLib;
112
- }
113
- }
114
-
115
- public static setSdk(sdk: string): void {
116
- EagleProfilerWorker._sdk = sdk;
117
- }
118
-
119
- /**
120
- * Creates an instance of profiler component of the Eagle Speaker Recognition Engine.
121
- *
122
- * @param accessKey AccessKey obtained from Picovoice Console (https://console.picovoice.ai/).
123
- * @param model Eagle model options.
124
- * @param model.base64 The model in base64 string to initialize Eagle.
125
- * @param model.publicPath The model path relative to the public directory.
126
- * @param model.customWritePath Custom path to save the model in storage.
127
- * Set to a different name to use multiple models across `eagle` instances.
128
- * @param model.forceWrite Flag to overwrite the model in storage even if it exists.
129
- * @param model.version Version of the model file. Increment to update the model file in storage.
130
- * @param options Optional configuration arguments.
131
- * @param options.device String representation of the device (e.g., CPU or GPU) to use. If set to `best`, the most
132
- * suitable device is selected automatically. If set to `gpu`, the engine uses the first available GPU device. To select a specific
133
- * GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the target GPU. If set to
134
- * `cpu`, the engine will run on the CPU with the default number of threads. To specify the number of threads, set this
135
- * argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads.
136
- *
137
- * @return An instance of the Eagle Profiler.
138
- */
139
- public static async create(
140
- accessKey: string,
141
- model: EagleModel,
142
- options: EagleProfilerOptions = {}
143
- ): Promise<EagleProfilerWorker> {
144
- const customWritePath = model.customWritePath
145
- ? model.customWritePath
146
- : 'eagle_model';
147
- const modelPath = await loadModel({ ...model, customWritePath });
148
-
149
- const worker = new PvWorker();
150
- const returnPromise: Promise<EagleProfilerWorker> = new Promise(
151
- (resolve, reject) => {
152
- // @ts-ignore - block from GC
153
- this.worker = worker;
154
- worker.onmessage = (
155
- event: MessageEvent<EagleProfilerWorkerInitResponse>
156
- ): void => {
157
- switch (event.data.command) {
158
- case 'ok':
159
- resolve(
160
- new EagleProfilerWorker(
161
- worker,
162
- event.data.minEnrollSamples,
163
- event.data.sampleRate,
164
- event.data.version
165
- )
166
- );
167
- break;
168
- case 'failed':
169
- case 'error':
170
- reject(
171
- pvStatusToException(
172
- event.data.status,
173
- event.data.shortMessage,
174
- event.data.messageStack
175
- )
176
- );
177
- break;
178
- default:
179
- reject(
180
- pvStatusToException(
181
- PvStatus.RUNTIME_ERROR,
182
- // @ts-ignore
183
- `Unrecognized command: ${event.data.command}`
184
- )
185
- );
186
- }
187
- };
188
- }
189
- );
190
-
191
- worker.postMessage({
192
- command: 'init',
193
- accessKey: accessKey,
194
- modelPath: modelPath,
195
- options: options,
196
- wasmSimd: this._wasmSimd,
197
- wasmSimdLib: this._wasmSimdLib,
198
- wasmPThread: this._wasmPThread,
199
- wasmPThreadLib: this._wasmPThreadLib,
200
- sdk: this._sdk,
201
- });
202
-
203
- return returnPromise;
204
- }
205
-
206
- /**
207
- * Enrolls a speaker. This function should be called multiple times with different utterances of the same speaker
208
- * until `percentage` reaches `100.0`, at which point a speaker voice profile can be exported using `.export()`.
209
- * Any further enrollment can be used to improve the speaker profile. The minimum length of the input pcm to
210
- * `.enroll()` can be obtained by calling `.minEnrollSamples`.
211
- * The audio data used for enrollment should satisfy the following requirements:
212
- * - only one speaker should be present in the audio
213
- * - the speaker should be speaking in a normal voice
214
- * - the audio should contain no speech from other speakers and no other sounds (e.g. music)
215
- * - it should be captured in a quiet environment with no background noise
216
- * @param pcm Audio data for enrollment. The audio needs to have a sample rate equal to `.sampleRate` and be
217
- * 16-bit linearly-encoded. EagleProfiler operates on single-channel audio.
218
- *
219
- * @return The percentage of completeness of the speaker enrollment process along with the feedback code
220
- * corresponding to the last enrollment attempt:
221
- * - `AUDIO_OK`: The audio is good for enrollment.
222
- * - `AUDIO_TOO_SHORT`: Audio length is insufficient for enrollment,
223
- * i.e. it is shorter than`.min_enroll_samples`.
224
- * - `UNKNOWN_SPEAKER`: There is another speaker in the audio that is different from the speaker
225
- * being enrolled. Too much background noise may cause this error as well.
226
- * - `NO_VOICE_FOUND`: The audio does not contain any voice, i.e. it is silent or
227
- * has a low signal-to-noise ratio.
228
- * - `QUALITY_ISSUE`: The audio quality is too low for enrollment due to a bad microphone
229
- * or recording environment.
230
- */
231
- public enroll(pcm: Int16Array): Promise<EagleProfilerEnrollResult> {
232
- const returnPromise: Promise<EagleProfilerEnrollResult> = new Promise(
233
- (resolve, reject) => {
234
- this._worker.onmessage = (
235
- event: MessageEvent<EagleProfilerWorkerEnrollResponse>
236
- ): void => {
237
- switch (event.data.command) {
238
- case 'ok':
239
- resolve(event.data.result);
240
- break;
241
- case 'failed':
242
- case 'error':
243
- reject(
244
- pvStatusToException(
245
- event.data.status,
246
- event.data.shortMessage,
247
- event.data.messageStack
248
- )
249
- );
250
- break;
251
- default:
252
- reject(
253
- pvStatusToException(
254
- PvStatus.RUNTIME_ERROR,
255
- // @ts-ignore
256
- `Unrecognized command: ${event.data.command}`
257
- )
258
- );
259
- }
260
- };
261
- }
262
- );
263
-
264
- this._worker.postMessage({
265
- command: 'enroll',
266
- inputFrame: pcm,
267
- });
268
-
269
- return returnPromise;
270
- }
271
-
272
- /**
273
- * Exports the speaker profile of the current session.
274
- * Will throw error if the profile is not ready.
275
- *
276
- * @return An EagleProfile object.
277
- */
278
- public async export(): Promise<EagleProfile> {
279
- const returnPromise: Promise<EagleProfile> = new Promise(
280
- (resolve, reject) => {
281
- this._worker.onmessage = (
282
- event: MessageEvent<EagleProfilerWorkerExportResponse>
283
- ): void => {
284
- switch (event.data.command) {
285
- case 'ok':
286
- resolve(event.data.profile);
287
- break;
288
- case 'failed':
289
- case 'error':
290
- reject(
291
- pvStatusToException(
292
- event.data.status,
293
- event.data.shortMessage,
294
- event.data.messageStack
295
- )
296
- );
297
- break;
298
- default:
299
- reject(
300
- pvStatusToException(
301
- PvStatus.RUNTIME_ERROR,
302
- // @ts-ignore
303
- `Unrecognized command: ${event.data.command}`
304
- )
305
- );
306
- }
307
- };
308
- }
309
- );
310
- this._worker.postMessage({
311
- command: 'export',
312
- });
313
-
314
- return returnPromise;
315
- }
316
-
317
- /**
318
- * Resets the internal state of Eagle Profiler.
319
- * It should be called before starting a new enrollment session.
320
- */
321
- public async reset(): Promise<void> {
322
- const returnPromise: Promise<void> = new Promise((resolve, reject) => {
323
- this._worker.onmessage = (
324
- event: MessageEvent<EagleProfilerWorkerResetResponse>
325
- ): void => {
326
- switch (event.data.command) {
327
- case 'ok':
328
- resolve();
329
- break;
330
- case 'failed':
331
- case 'error':
332
- reject(
333
- pvStatusToException(
334
- event.data.status,
335
- event.data.shortMessage,
336
- event.data.messageStack
337
- )
338
- );
339
- break;
340
- default:
341
- reject(
342
- pvStatusToException(
343
- PvStatus.RUNTIME_ERROR,
344
- // @ts-ignore
345
- `Unrecognized command: ${event.data.command}`
346
- )
347
- );
348
- }
349
- };
350
- });
351
- this._worker.postMessage({
352
- command: 'reset',
353
- });
354
-
355
- return returnPromise;
356
- }
357
-
358
- /**
359
- * Releases resources acquired by Eagle Profiler
360
- */
361
- public release(): Promise<void> {
362
- const returnPromise: Promise<void> = new Promise((resolve, reject) => {
363
- this._worker.onmessage = (
364
- event: MessageEvent<EagleProfilerWorkerReleaseResponse>
365
- ): void => {
366
- switch (event.data.command) {
367
- case 'ok':
368
- resolve();
369
- break;
370
- case 'failed':
371
- case 'error':
372
- reject(
373
- pvStatusToException(
374
- event.data.status,
375
- event.data.shortMessage,
376
- event.data.messageStack
377
- )
378
- );
379
- break;
380
- default:
381
- reject(
382
- pvStatusToException(
383
- PvStatus.RUNTIME_ERROR,
384
- // @ts-ignore
385
- `Unrecognized command: ${event.data.command}`
386
- )
387
- );
388
- }
389
- };
390
- });
391
-
392
- this._worker.postMessage({
393
- command: 'release',
394
- });
395
-
396
- return returnPromise;
397
- }
398
-
399
- /**
400
- * Terminates the active worker. Stops all requests being handled by worker.
401
- */
402
- public terminate(): void {
403
- this._worker.terminate();
404
- }
405
- }
1
+ /*
2
+ Copyright 2023-2026 Picovoice Inc.
3
+
4
+ You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE"
5
+ file accompanying this source.
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
8
+ an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
9
+ specific language governing permissions and limitations under the License.
10
+ */
11
+
12
+ import PvWorker from 'web-worker:./eagle_profiler_worker_handler.ts';
13
+
14
+ import {
15
+ EagleModel,
16
+ EagleProfile,
17
+ EagleProfilerOptions,
18
+ EagleProfilerWorkerEnrollResponse,
19
+ EagleProfilerWorkerFlushResponse,
20
+ EagleProfilerWorkerExportResponse,
21
+ EagleProfilerWorkerInitResponse,
22
+ EagleProfilerWorkerReleaseResponse,
23
+ EagleProfilerWorkerResetResponse,
24
+ PvStatus,
25
+ } from './types';
26
+ import { loadModel } from '@picovoice/web-utils';
27
+ import { pvStatusToException } from "./eagle_errors";
28
+
29
+ export class EagleProfilerWorker {
30
+ private readonly _worker: Worker;
31
+ private readonly _frameLength: number;
32
+ private readonly _sampleRate: number;
33
+ private readonly _version: string;
34
+
35
+ private static _wasmSimd: string;
36
+ private static _wasmSimdLib: string;
37
+ private static _wasmPThread: string;
38
+ private static _wasmPThreadLib: string;
39
+
40
+ private static _sdk: string = 'web';
41
+
42
+ private constructor(
43
+ worker: Worker,
44
+ frameLength: number,
45
+ sampleRate: number,
46
+ version: string
47
+ ) {
48
+ this._worker = worker;
49
+ this._frameLength = frameLength;
50
+ this._sampleRate = sampleRate;
51
+ this._version = version;
52
+ }
53
+
54
+ /**
55
+ * The length of the input pcm required by `.enroll()`.
56
+ */
57
+ get frameLength(): number {
58
+ return this._frameLength;
59
+ }
60
+
61
+ /**
62
+ * Audio sample rate required by Eagle.
63
+ */
64
+ get sampleRate(): number {
65
+ return this._sampleRate;
66
+ }
67
+
68
+ /**
69
+ * Version of Eagle.
70
+ */
71
+ get version(): string {
72
+ return this._version;
73
+ }
74
+
75
+ /**
76
+ * Set base64 wasm file with SIMD feature.
77
+ * @param wasmSimd Base64'd wasm SIMD file to use to initialize wasm.
78
+ */
79
+ public static setWasmSimd(wasmSimd: string): void {
80
+ if (this._wasmSimd === undefined) {
81
+ this._wasmSimd = wasmSimd;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Set base64 wasm file with SIMD feature in text format.
87
+ * @param wasmSimdLib Base64'd wasm SIMD file in text format.
88
+ */
89
+ public static setWasmSimdLib(wasmSimdLib: string): void {
90
+ if (this._wasmSimdLib === undefined) {
91
+ this._wasmSimdLib = wasmSimdLib;
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Set base64 wasm file with SIMD and pthread feature.
97
+ * @param wasmPThread Base64'd wasm file to use to initialize wasm.
98
+ */
99
+ public static setWasmPThread(wasmPThread: string): void {
100
+ if (this._wasmPThread === undefined) {
101
+ this._wasmPThread = wasmPThread;
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Set base64 SIMD and thread wasm file in text format.
107
+ * @param wasmPThreadLib Base64'd wasm file in text format.
108
+ */
109
+ public static setWasmPThreadLib(wasmPThreadLib: string): void {
110
+ if (this._wasmPThreadLib === undefined) {
111
+ this._wasmPThreadLib = wasmPThreadLib;
112
+ }
113
+ }
114
+
115
+ public static setSdk(sdk: string): void {
116
+ EagleProfilerWorker._sdk = sdk;
117
+ }
118
+
119
+ /**
120
+ * Creates an instance of profiler component of the Eagle Speaker Recognition Engine.
121
+ *
122
+ * @param accessKey AccessKey obtained from Picovoice Console (https://console.picovoice.ai/).
123
+ * @param model Eagle model options.
124
+ * @param model.base64 The model in base64 string to initialize Eagle.
125
+ * @param model.publicPath The model path relative to the public directory.
126
+ * @param model.customWritePath Custom path to save the model in storage.
127
+ * Set to a different name to use multiple models across `eagle` instances.
128
+ * @param model.forceWrite Flag to overwrite the model in storage even if it exists.
129
+ * @param model.version Version of the model file. Increment to update the model file in storage.
130
+ * @param options Optional configuration arguments.
131
+ * @param options.device String representation of the device (e.g., CPU or GPU) to use. If set to `best`, the most
132
+ * suitable device is selected automatically. If set to `gpu`, the engine uses the first available GPU device. To select a specific
133
+ * GPU device, set this argument to `gpu:${GPU_INDEX}`, where `${GPU_INDEX}` is the index of the target GPU. If set to
134
+ * `cpu`, the engine will run on the CPU with the default number of threads. To specify the number of threads, set this
135
+ * argument to `cpu:${NUM_THREADS}`, where `${NUM_THREADS}` is the desired number of threads.
136
+ * @param options.minEnrollmentChunks Minimum number of chunks to be processed before enroll returns 100%
137
+ * @param options.voiceThreshold Sensitivity threshold for detecting voice.
138
+ *
139
+ * @return An instance of the Eagle Profiler.
140
+ */
141
+ public static async create(
142
+ accessKey: string,
143
+ model: EagleModel,
144
+ options: EagleProfilerOptions = {}
145
+ ): Promise<EagleProfilerWorker> {
146
+ const customWritePath = model.customWritePath
147
+ ? model.customWritePath
148
+ : 'eagle_model';
149
+ const modelPath = await loadModel({ ...model, customWritePath });
150
+
151
+ const worker = new PvWorker();
152
+ const returnPromise: Promise<EagleProfilerWorker> = new Promise(
153
+ (resolve, reject) => {
154
+ // @ts-ignore - block from GC
155
+ this.worker = worker;
156
+ worker.onmessage = (
157
+ event: MessageEvent<EagleProfilerWorkerInitResponse>
158
+ ): void => {
159
+ switch (event.data.command) {
160
+ case 'ok':
161
+ resolve(
162
+ new EagleProfilerWorker(
163
+ worker,
164
+ event.data.frameLength,
165
+ event.data.sampleRate,
166
+ event.data.version
167
+ )
168
+ );
169
+ break;
170
+ case 'failed':
171
+ case 'error':
172
+ reject(
173
+ pvStatusToException(
174
+ event.data.status,
175
+ event.data.shortMessage,
176
+ event.data.messageStack
177
+ )
178
+ );
179
+ break;
180
+ default:
181
+ reject(
182
+ pvStatusToException(
183
+ PvStatus.RUNTIME_ERROR,
184
+ // @ts-ignore
185
+ `Unrecognized command: ${event.data.command}`
186
+ )
187
+ );
188
+ }
189
+ };
190
+ }
191
+ );
192
+
193
+ worker.postMessage({
194
+ command: 'init',
195
+ accessKey: accessKey,
196
+ modelPath: modelPath,
197
+ options: options,
198
+ wasmSimd: this._wasmSimd,
199
+ wasmSimdLib: this._wasmSimdLib,
200
+ wasmPThread: this._wasmPThread,
201
+ wasmPThreadLib: this._wasmPThreadLib,
202
+ sdk: this._sdk,
203
+ });
204
+
205
+ return returnPromise;
206
+ }
207
+
208
+ /**
209
+ * Enrolls a speaker. This function should be called multiple times with different utterances of the same speaker
210
+ * until `percentage` reaches `100.0`, at which point a speaker voice profile can be exported using `.export()`.
211
+ * Any further enrollment can be used to improve the speaker profile. The minimum length of the input pcm to
212
+ * `.enroll()` can be obtained by calling `.minEnrollSamples`.
213
+ * The audio data used for enrollment should satisfy the following requirements:
214
+ * - only one speaker should be present in the audio
215
+ * - the speaker should be speaking in a normal voice
216
+ * - the audio should contain no speech from other speakers and no other sounds (e.g. music)
217
+ * - it should be captured in a quiet environment with no background noise
218
+ * @param pcm Audio data for enrollment. The audio needs to have a sample rate equal to `.sampleRate` and be
219
+ * 16-bit linearly-encoded. EagleProfiler operates on single-channel audio.
220
+ *
221
+ * @return The percentage of completeness of the speaker enrollment process.
222
+ */
223
+ public enroll(pcm: Int16Array): Promise<number> {
224
+ const returnPromise: Promise<number> = new Promise(
225
+ (resolve, reject) => {
226
+ this._worker.onmessage = (
227
+ event: MessageEvent<EagleProfilerWorkerEnrollResponse>
228
+ ): void => {
229
+ switch (event.data.command) {
230
+ case 'ok':
231
+ resolve(event.data.result);
232
+ break;
233
+ case 'failed':
234
+ case 'error':
235
+ reject(
236
+ pvStatusToException(
237
+ event.data.status,
238
+ event.data.shortMessage,
239
+ event.data.messageStack
240
+ )
241
+ );
242
+ break;
243
+ default:
244
+ reject(
245
+ pvStatusToException(
246
+ PvStatus.RUNTIME_ERROR,
247
+ // @ts-ignore
248
+ `Unrecognized command: ${event.data.command}`
249
+ )
250
+ );
251
+ }
252
+ };
253
+ }
254
+ );
255
+
256
+ this._worker.postMessage({
257
+ command: 'enroll',
258
+ inputFrame: pcm,
259
+ });
260
+
261
+ return returnPromise;
262
+ }
263
+
264
+ /**
265
+ * Marks the end of the audio stream, flushes internal state of the object, and returns the percentage of enrollment
266
+ * completed.
267
+ *
268
+ * @return The percentage of completeness of the speaker enrollment process.
269
+ */
270
+ public flush(): Promise<number> {
271
+ const returnPromise: Promise<number> = new Promise(
272
+ (resolve, reject) => {
273
+ this._worker.onmessage = (
274
+ event: MessageEvent<EagleProfilerWorkerFlushResponse>
275
+ ): void => {
276
+ switch (event.data.command) {
277
+ case 'ok':
278
+ resolve(event.data.result);
279
+ break;
280
+ case 'failed':
281
+ case 'error':
282
+ reject(
283
+ pvStatusToException(
284
+ event.data.status,
285
+ event.data.shortMessage,
286
+ event.data.messageStack
287
+ )
288
+ );
289
+ break;
290
+ default:
291
+ reject(
292
+ pvStatusToException(
293
+ PvStatus.RUNTIME_ERROR,
294
+ // @ts-ignore
295
+ `Unrecognized command: ${event.data.command}`
296
+ )
297
+ );
298
+ }
299
+ };
300
+ }
301
+ );
302
+
303
+ this._worker.postMessage({
304
+ command: 'flush',
305
+ });
306
+
307
+ return returnPromise;
308
+ }
309
+
310
+ /**
311
+ * Exports the speaker profile of the current session.
312
+ * Will throw error if the profile is not ready.
313
+ *
314
+ * @return An EagleProfile object.
315
+ */
316
+ public async export(): Promise<EagleProfile> {
317
+ const returnPromise: Promise<EagleProfile> = new Promise(
318
+ (resolve, reject) => {
319
+ this._worker.onmessage = (
320
+ event: MessageEvent<EagleProfilerWorkerExportResponse>
321
+ ): void => {
322
+ switch (event.data.command) {
323
+ case 'ok':
324
+ resolve(event.data.profile);
325
+ break;
326
+ case 'failed':
327
+ case 'error':
328
+ reject(
329
+ pvStatusToException(
330
+ event.data.status,
331
+ event.data.shortMessage,
332
+ event.data.messageStack
333
+ )
334
+ );
335
+ break;
336
+ default:
337
+ reject(
338
+ pvStatusToException(
339
+ PvStatus.RUNTIME_ERROR,
340
+ // @ts-ignore
341
+ `Unrecognized command: ${event.data.command}`
342
+ )
343
+ );
344
+ }
345
+ };
346
+ }
347
+ );
348
+ this._worker.postMessage({
349
+ command: 'export',
350
+ });
351
+
352
+ return returnPromise;
353
+ }
354
+
355
+ /**
356
+ * Resets the internal state of Eagle Profiler.
357
+ * It should be called before starting a new enrollment session.
358
+ */
359
+ public async reset(): Promise<void> {
360
+ const returnPromise: Promise<void> = new Promise((resolve, reject) => {
361
+ this._worker.onmessage = (
362
+ event: MessageEvent<EagleProfilerWorkerResetResponse>
363
+ ): void => {
364
+ switch (event.data.command) {
365
+ case 'ok':
366
+ resolve();
367
+ break;
368
+ case 'failed':
369
+ case 'error':
370
+ reject(
371
+ pvStatusToException(
372
+ event.data.status,
373
+ event.data.shortMessage,
374
+ event.data.messageStack
375
+ )
376
+ );
377
+ break;
378
+ default:
379
+ reject(
380
+ pvStatusToException(
381
+ PvStatus.RUNTIME_ERROR,
382
+ // @ts-ignore
383
+ `Unrecognized command: ${event.data.command}`
384
+ )
385
+ );
386
+ }
387
+ };
388
+ });
389
+ this._worker.postMessage({
390
+ command: 'reset',
391
+ });
392
+
393
+ return returnPromise;
394
+ }
395
+
396
+ /**
397
+ * Releases resources acquired by Eagle Profiler
398
+ */
399
+ public release(): Promise<void> {
400
+ const returnPromise: Promise<void> = new Promise((resolve, reject) => {
401
+ this._worker.onmessage = (
402
+ event: MessageEvent<EagleProfilerWorkerReleaseResponse>
403
+ ): void => {
404
+ switch (event.data.command) {
405
+ case 'ok':
406
+ resolve();
407
+ break;
408
+ case 'failed':
409
+ case 'error':
410
+ reject(
411
+ pvStatusToException(
412
+ event.data.status,
413
+ event.data.shortMessage,
414
+ event.data.messageStack
415
+ )
416
+ );
417
+ break;
418
+ default:
419
+ reject(
420
+ pvStatusToException(
421
+ PvStatus.RUNTIME_ERROR,
422
+ // @ts-ignore
423
+ `Unrecognized command: ${event.data.command}`
424
+ )
425
+ );
426
+ }
427
+ };
428
+ });
429
+
430
+ this._worker.postMessage({
431
+ command: 'release',
432
+ });
433
+
434
+ return returnPromise;
435
+ }
436
+
437
+ /**
438
+ * Terminates the active worker. Stops all requests being handled by worker.
439
+ */
440
+ public terminate(): void {
441
+ this._worker.terminate();
442
+ }
443
+ }