@eka-care/ekascribe-ts-sdk 1.4.39

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.
Files changed (71) hide show
  1. package/README.md +437 -0
  2. package/dist/api/get-transaction-history.d.ts +5 -0
  3. package/dist/api/get-transaction-history.js +28 -0
  4. package/dist/api/get-voice-api-v2-config.d.ts +2 -0
  5. package/dist/api/get-voice-api-v2-config.js +26 -0
  6. package/dist/api/get-voice-api-v2-status.d.ts +51 -0
  7. package/dist/api/get-voice-api-v2-status.js +25 -0
  8. package/dist/api/get-voice-api-v3-status.d.ts +51 -0
  9. package/dist/api/get-voice-api-v3-status.js +26 -0
  10. package/dist/api/patch-transaction-status.d.ts +4 -0
  11. package/dist/api/patch-transaction-status.js +43 -0
  12. package/dist/api/post-cog-init.d.ts +3 -0
  13. package/dist/api/post-cog-init.js +15 -0
  14. package/dist/api/post-transaction-commit.d.ts +3 -0
  15. package/dist/api/post-transaction-commit.js +32 -0
  16. package/dist/api/post-transaction-init.d.ts +3 -0
  17. package/dist/api/post-transaction-init.js +40 -0
  18. package/dist/api/post-transaction-stop.d.ts +3 -0
  19. package/dist/api/post-transaction-stop.js +32 -0
  20. package/dist/audio-chunker/__tests__/audio-file-manager.test.d.ts +1 -0
  21. package/dist/audio-chunker/__tests__/audio-file-manager.test.js +5 -0
  22. package/dist/audio-chunker/audio-buffer-manager.d.ts +53 -0
  23. package/dist/audio-chunker/audio-buffer-manager.js +136 -0
  24. package/dist/audio-chunker/audio-file-manager.d.ts +96 -0
  25. package/dist/audio-chunker/audio-file-manager.js +579 -0
  26. package/dist/audio-chunker/vad-web.d.ts +90 -0
  27. package/dist/audio-chunker/vad-web.js +389 -0
  28. package/dist/aws-services/configure-aws.d.ts +5 -0
  29. package/dist/aws-services/configure-aws.js +13 -0
  30. package/dist/aws-services/get-files-s3.d.ts +10 -0
  31. package/dist/aws-services/get-files-s3.js +30 -0
  32. package/dist/aws-services/s3-retry-wrapper.d.ts +2 -0
  33. package/dist/aws-services/s3-retry-wrapper.js +38 -0
  34. package/dist/aws-services/translate-text-to-target-language.d.ts +6 -0
  35. package/dist/aws-services/translate-text-to-target-language.js +18 -0
  36. package/dist/aws-services/upload-file-to-s3.d.ts +13 -0
  37. package/dist/aws-services/upload-file-to-s3.js +48 -0
  38. package/dist/constants/constant.d.ts +27 -0
  39. package/dist/constants/constant.js +33 -0
  40. package/dist/constants/enums.d.ts +46 -0
  41. package/dist/constants/enums.js +51 -0
  42. package/dist/constants/setup-config.d.ts +14 -0
  43. package/dist/constants/setup-config.js +31 -0
  44. package/dist/constants/types.d.ts +224 -0
  45. package/dist/constants/types.js +1 -0
  46. package/dist/fetch-client/helper.d.ts +11 -0
  47. package/dist/fetch-client/helper.js +28 -0
  48. package/dist/fetch-client/index.d.ts +1 -0
  49. package/dist/fetch-client/index.js +36 -0
  50. package/dist/index.d.ts +60 -0
  51. package/dist/index.js +267 -0
  52. package/dist/main/end-recording.d.ts +3 -0
  53. package/dist/main/end-recording.js +141 -0
  54. package/dist/main/init-transaction.d.ts +3 -0
  55. package/dist/main/init-transaction.js +86 -0
  56. package/dist/main/pause-recording.d.ts +3 -0
  57. package/dist/main/pause-recording.js +59 -0
  58. package/dist/main/resume-recording.d.ts +3 -0
  59. package/dist/main/resume-recording.js +33 -0
  60. package/dist/main/retry-upload-recording.d.ts +5 -0
  61. package/dist/main/retry-upload-recording.js +69 -0
  62. package/dist/main/start-recording.d.ts +3 -0
  63. package/dist/main/start-recording.js +55 -0
  64. package/dist/shared-worker/s3-file-upload.d.ts +1 -0
  65. package/dist/shared-worker/s3-file-upload.js +109 -0
  66. package/dist/shared-worker/s3-file-upload.ts +126 -0
  67. package/dist/store/store.d.ts +35 -0
  68. package/dist/store/store.js +121 -0
  69. package/dist/utils/compress-mp3-audio.d.ts +2 -0
  70. package/dist/utils/compress-mp3-audio.js +24 -0
  71. package/package.json +53 -0
@@ -0,0 +1,579 @@
1
+ import { AUDIO_EXTENSION_TYPE_MAP, OUTPUT_FORMAT } from '../constants/constant';
2
+ import pushFileToS3 from '../aws-services/upload-file-to-s3';
3
+ import postCogInit from '../api/post-cog-init';
4
+ import { configureAWS } from '../aws-services/configure-aws';
5
+ import { SHARED_WORKER_ACTION } from '../constants/enums';
6
+ import compressAudioToMp3 from '../utils/compress-mp3-audio';
7
+ class AudioFileManager {
8
+ initialiseClassInstance() {
9
+ this.audioChunks = [];
10
+ this.uploadPromises = [];
11
+ this.successfulUploads = [];
12
+ this.totalInsertedFrames = 0;
13
+ this.totalInsertedSamples = 0;
14
+ this.totalRawSamples = 0;
15
+ this.totalRawFrames = 0;
16
+ }
17
+ constructor() {
18
+ /**
19
+ * Class that handles uploading audio files to S3
20
+ * and downloading audio files for debugging
21
+ */
22
+ Object.defineProperty(this, "txnID", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: ''
27
+ });
28
+ Object.defineProperty(this, "filePath", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: ''
33
+ });
34
+ Object.defineProperty(this, "audioChunks", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: []
39
+ });
40
+ Object.defineProperty(this, "uploadPromises", {
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true,
44
+ value: []
45
+ });
46
+ Object.defineProperty(this, "successfulUploads", {
47
+ enumerable: true,
48
+ configurable: true,
49
+ writable: true,
50
+ value: []
51
+ });
52
+ Object.defineProperty(this, "onProgressCallback", {
53
+ enumerable: true,
54
+ configurable: true,
55
+ writable: true,
56
+ value: void 0
57
+ });
58
+ Object.defineProperty(this, "totalRawSamples", {
59
+ enumerable: true,
60
+ configurable: true,
61
+ writable: true,
62
+ value: 0
63
+ });
64
+ Object.defineProperty(this, "totalRawFrames", {
65
+ enumerable: true,
66
+ configurable: true,
67
+ writable: true,
68
+ value: 0
69
+ });
70
+ Object.defineProperty(this, "totalInsertedSamples", {
71
+ enumerable: true,
72
+ configurable: true,
73
+ writable: true,
74
+ value: 0
75
+ });
76
+ Object.defineProperty(this, "totalInsertedFrames", {
77
+ enumerable: true,
78
+ configurable: true,
79
+ writable: true,
80
+ value: 0
81
+ });
82
+ Object.defineProperty(this, "businessID", {
83
+ enumerable: true,
84
+ configurable: true,
85
+ writable: true,
86
+ value: ''
87
+ });
88
+ Object.defineProperty(this, "isAWSConfigured", {
89
+ enumerable: true,
90
+ configurable: true,
91
+ writable: true,
92
+ value: false
93
+ });
94
+ Object.defineProperty(this, "sharedWorkerInstance", {
95
+ enumerable: true,
96
+ configurable: true,
97
+ writable: true,
98
+ value: null
99
+ });
100
+ this.initialiseClassInstance();
101
+ }
102
+ /**
103
+ * Set basic file information
104
+ */
105
+ setSessionInfo({ sessionId, filePath, businessID, }) {
106
+ this.txnID = sessionId;
107
+ this.filePath = filePath;
108
+ this.businessID = businessID;
109
+ }
110
+ getRawSampleDetails() {
111
+ return {
112
+ totalRawSamples: this.totalRawSamples,
113
+ totalRawFrames: this.totalRawFrames,
114
+ };
115
+ }
116
+ incrementTotalRawSamples(frames) {
117
+ this.totalRawSamples += frames.length;
118
+ this.totalRawFrames += 1;
119
+ }
120
+ incrementInsertedSamples(samples, frames) {
121
+ this.totalInsertedSamples += samples;
122
+ this.totalInsertedFrames += frames;
123
+ }
124
+ getInsertedSampleDetails() {
125
+ return {
126
+ totalInsertedSamples: this.totalInsertedSamples,
127
+ totalInsertedFrames: this.totalInsertedFrames,
128
+ };
129
+ }
130
+ /**
131
+ * Set callback for upload progress updates
132
+ */
133
+ setProgressCallback(callback) {
134
+ this.onProgressCallback = callback;
135
+ }
136
+ /**
137
+ * Update audio information array, this will update the audio chunks info
138
+ * (+ the latest chunk , affects the length of chunks data struct)
139
+ */
140
+ updateAudioInfo(audioChunks) {
141
+ this.audioChunks.push(audioChunks);
142
+ return this.audioChunks.length;
143
+ }
144
+ createSharedWorkerInstance() {
145
+ try {
146
+ // new URL(relativeOrAbsolutePath, baseUrl)
147
+ const worker = new SharedWorker(new URL('../shared-worker/s3-file-upload.js', import.meta.url));
148
+ this.sharedWorkerInstance = worker;
149
+ this.sharedWorkerInstance.port.onmessage = async (event) => {
150
+ const workerResponse = event.data;
151
+ switch (workerResponse.action) {
152
+ case SHARED_WORKER_ACTION.CONFIGURE_AWS_SUCCESS: {
153
+ console.log('AWS configured successfully in worker');
154
+ return;
155
+ }
156
+ case SHARED_WORKER_ACTION.CONFIGURE_AWS_ERROR: {
157
+ console.error('Error configuring AWS in worker:', workerResponse.error);
158
+ return;
159
+ }
160
+ case SHARED_WORKER_ACTION.UPLOAD_FILE_WITH_WORKER_SUCCESS: {
161
+ console.log('File uploaded successfully in worker:', workerResponse.response);
162
+ const { fileCount: fileName, chunkIndex, fileBlob, compressedAudioBuffer, } = workerResponse.requestBody;
163
+ if (this.onProgressCallback && compressedAudioBuffer) {
164
+ this.onProgressCallback({
165
+ success: this.successfulUploads.length,
166
+ total: this.audioChunks.length,
167
+ fileName,
168
+ chunkData: compressedAudioBuffer,
169
+ });
170
+ }
171
+ if (workerResponse.response.success) {
172
+ this.successfulUploads.push(fileName);
173
+ // remove audioFrames if file uploaded successfully
174
+ if (chunkIndex !== -1) {
175
+ this.audioChunks[chunkIndex] = {
176
+ ...this.audioChunks[chunkIndex],
177
+ audioFrames: undefined,
178
+ fileBlob: undefined,
179
+ status: 'success',
180
+ response: workerResponse.response.success,
181
+ };
182
+ }
183
+ if (this.onProgressCallback) {
184
+ this.onProgressCallback({
185
+ success: this.successfulUploads.length,
186
+ total: this.audioChunks.length,
187
+ is_uploaded: true,
188
+ });
189
+ }
190
+ }
191
+ else {
192
+ if (this.onProgressCallback) {
193
+ this.onProgressCallback({
194
+ success: this.successfulUploads.length,
195
+ total: this.audioChunks.length,
196
+ fileName,
197
+ is_uploaded: false,
198
+ error: {
199
+ code: workerResponse.response.code,
200
+ msg: 'Tokens expired.',
201
+ },
202
+ });
203
+ }
204
+ // store that audioFrames in audioChunks
205
+ if (chunkIndex !== -1) {
206
+ this.audioChunks[chunkIndex] = {
207
+ ...this.audioChunks[chunkIndex],
208
+ fileBlob,
209
+ audioFrames: undefined,
210
+ status: 'failure',
211
+ response: workerResponse.response.error || 'Upload failed',
212
+ };
213
+ }
214
+ // call COG if S3 throws ExpiredToken error
215
+ if (workerResponse.response.errorCode === 'ExpiredToken') {
216
+ this.setupAWSConfiguration({
217
+ is_shared_worker: true,
218
+ });
219
+ }
220
+ }
221
+ }
222
+ }
223
+ };
224
+ worker.port.start();
225
+ return true;
226
+ }
227
+ catch (error) {
228
+ console.error('Error creating shared worker instance:', error);
229
+ return false;
230
+ }
231
+ }
232
+ async setupAWSConfiguration({ is_shared_worker }) {
233
+ try {
234
+ const response = await postCogInit();
235
+ const { credentials, is_session_expired } = response;
236
+ if (is_session_expired || !credentials) {
237
+ this.isAWSConfigured = false;
238
+ return false;
239
+ }
240
+ const { AccessKeyId, SecretKey, SessionToken } = credentials;
241
+ if (is_shared_worker) {
242
+ this.sharedWorkerInstance?.port.postMessage({
243
+ action: SHARED_WORKER_ACTION.CONFIGURE_AWS,
244
+ payload: {
245
+ accessKeyId: AccessKeyId,
246
+ secretKey: SecretKey,
247
+ sessionToken: SessionToken,
248
+ },
249
+ });
250
+ }
251
+ else {
252
+ configureAWS({
253
+ accessKeyId: AccessKeyId,
254
+ secretKey: SecretKey,
255
+ sessionToken: SessionToken,
256
+ });
257
+ }
258
+ this.isAWSConfigured = true;
259
+ return true;
260
+ }
261
+ catch (error) {
262
+ console.log('%c Line:198 🥃 error', 'color:#42b983', error);
263
+ this.isAWSConfigured = false;
264
+ return false;
265
+ }
266
+ }
267
+ /**
268
+ * Upload a chunk of audio data to S3 in main thread
269
+ */
270
+ async uploadAudioChunkInMain({ audioFrames, fileName, chunkIndex, }) {
271
+ const s3FileName = `${this.filePath}/${fileName}`; // fileName is ${fileCount}.mp3
272
+ const compressedAudioBuffer = compressAudioToMp3(audioFrames);
273
+ const audioBlob = new Blob(compressedAudioBuffer, {
274
+ type: AUDIO_EXTENSION_TYPE_MAP[OUTPUT_FORMAT],
275
+ });
276
+ if (this.onProgressCallback) {
277
+ this.onProgressCallback({
278
+ success: this.successfulUploads.length,
279
+ total: this.audioChunks.length,
280
+ fileName,
281
+ chunkData: compressedAudioBuffer,
282
+ });
283
+ }
284
+ // Push upload promise to track status
285
+ const uploadPromise = pushFileToS3({
286
+ fileBlob: audioBlob,
287
+ fileName: s3FileName,
288
+ txnID: this.txnID,
289
+ businessID: this.businessID,
290
+ is_shared_worker: false,
291
+ }).then((response) => {
292
+ if (response.success) {
293
+ this.successfulUploads.push(fileName);
294
+ // update file status if file uploaded successfully
295
+ if (chunkIndex !== -1) {
296
+ this.audioChunks[chunkIndex] = {
297
+ ...this.audioChunks[chunkIndex],
298
+ audioFrames: undefined,
299
+ fileBlob: undefined,
300
+ status: 'success',
301
+ response: response.success,
302
+ };
303
+ }
304
+ if (this.onProgressCallback) {
305
+ this.onProgressCallback({
306
+ success: this.successfulUploads.length,
307
+ total: this.audioChunks.length,
308
+ is_uploaded: true,
309
+ });
310
+ }
311
+ }
312
+ else {
313
+ if (chunkIndex !== -1) {
314
+ this.audioChunks[chunkIndex] = {
315
+ ...this.audioChunks[chunkIndex],
316
+ fileBlob: audioBlob,
317
+ audioFrames: undefined,
318
+ status: 'failure',
319
+ response: response.error || 'Upload failed',
320
+ };
321
+ }
322
+ if (this.onProgressCallback) {
323
+ this.onProgressCallback({
324
+ success: this.successfulUploads.length,
325
+ total: this.audioChunks.length,
326
+ fileName,
327
+ is_uploaded: false,
328
+ error: {
329
+ code: response.code || 500,
330
+ msg: 'Tokens expired.',
331
+ },
332
+ });
333
+ }
334
+ }
335
+ return response;
336
+ });
337
+ this.uploadPromises.push(uploadPromise);
338
+ return {
339
+ success: true,
340
+ fileName,
341
+ };
342
+ }
343
+ /**
344
+ * Upload audio chunks to S3 in shared worker
345
+ */
346
+ async uploadAudioChunkInWorker({ audioFrames, fileName, chunkIndex, }) {
347
+ const s3FileName = `${this.filePath}/${fileName}`;
348
+ if (this.onProgressCallback) {
349
+ this.onProgressCallback({
350
+ success: this.successfulUploads.length,
351
+ total: this.audioChunks.length,
352
+ });
353
+ }
354
+ this.sharedWorkerInstance?.port.postMessage({
355
+ action: SHARED_WORKER_ACTION.UPLOAD_FILE_WITH_WORKER,
356
+ payload: {
357
+ audioFrames,
358
+ fileName: s3FileName,
359
+ txnID: this.txnID,
360
+ businessID: this.businessID,
361
+ chunkIndex,
362
+ fileCount: fileName,
363
+ },
364
+ });
365
+ return {
366
+ success: true,
367
+ fileName,
368
+ };
369
+ }
370
+ async uploadAudioToS3({ audioFrames, fileName, chunkIndex }) {
371
+ if (typeof SharedWorker === 'undefined' || !SharedWorker) {
372
+ // Shared Workers are not supported in this browser
373
+ console.log('Shared Workers are NOT supported in this browser.');
374
+ await this.uploadAudioToS3WithoutWorker({ audioFrames, fileName, chunkIndex });
375
+ }
376
+ else {
377
+ // Shared Workers are supported
378
+ console.log('Shared Workers are supported in this browser.');
379
+ if (!this.sharedWorkerInstance) {
380
+ this.createSharedWorkerInstance();
381
+ }
382
+ await this.uploadAudioToS3WithWorker({ audioFrames, fileName, chunkIndex });
383
+ }
384
+ }
385
+ async uploadAudioToS3WithWorker({ audioFrames, fileName, chunkIndex, }) {
386
+ try {
387
+ if (!this.isAWSConfigured) {
388
+ const awsConfigResponse = await this.setupAWSConfiguration({
389
+ is_shared_worker: true,
390
+ });
391
+ if (!awsConfigResponse) {
392
+ throw new Error('Failed to configure AWS');
393
+ }
394
+ }
395
+ await this.uploadAudioChunkInWorker({ audioFrames, fileName, chunkIndex });
396
+ }
397
+ catch (error) {
398
+ console.error('Error uploading audio to S3: uploadAudioToS3WithWorker: ', error);
399
+ }
400
+ }
401
+ async uploadAudioToS3WithoutWorker({ audioFrames, fileName, chunkIndex, }) {
402
+ try {
403
+ if (!this.isAWSConfigured) {
404
+ const awsConfigResponse = await this.setupAWSConfiguration({
405
+ is_shared_worker: false,
406
+ });
407
+ if (!awsConfigResponse) {
408
+ throw new Error('Failed to configure AWS');
409
+ }
410
+ }
411
+ await this.uploadAudioChunkInMain({ audioFrames, fileName, chunkIndex });
412
+ }
413
+ catch (error) {
414
+ console.error('Error uploading audio to S3:', error);
415
+ }
416
+ }
417
+ /**
418
+ * Download audio as a file to the user's device (for debugging)
419
+ */
420
+ downloadAudio(audioBlob, fileName) {
421
+ const url = URL.createObjectURL(audioBlob);
422
+ const a = document.createElement('a');
423
+ a.style.display = 'none';
424
+ a.href = url;
425
+ a.download = fileName;
426
+ document.body.appendChild(a);
427
+ a.click();
428
+ URL.revokeObjectURL(url);
429
+ document.body.removeChild(a);
430
+ }
431
+ /**
432
+ * Wait for all upload promises to complete
433
+ */
434
+ async waitForAllUploads() {
435
+ if (this.sharedWorkerInstance) {
436
+ return new Promise((resolve, reject) => {
437
+ // one-time message handler to listen for the response
438
+ const messageHandler = (event) => {
439
+ if (event.data.action === SHARED_WORKER_ACTION.WAIT_FOR_ALL_UPLOADS_SUCCESS) {
440
+ this.sharedWorkerInstance?.port.removeEventListener('message', messageHandler);
441
+ resolve();
442
+ }
443
+ else if (event.data.action === SHARED_WORKER_ACTION.WAIT_FOR_ALL_UPLOADS_ERROR) {
444
+ const { uploadRequestReceived } = event.data.response || {};
445
+ if (uploadRequestReceived === 0) {
446
+ this.sharedWorkerInstance?.port.removeEventListener('message', messageHandler);
447
+ reject();
448
+ }
449
+ this.sharedWorkerInstance?.port.postMessage({
450
+ action: SHARED_WORKER_ACTION.WAIT_FOR_ALL_UPLOADS,
451
+ });
452
+ }
453
+ };
454
+ // one-time listener
455
+ this.sharedWorkerInstance?.port.addEventListener('message', messageHandler);
456
+ this.sharedWorkerInstance?.port.postMessage({
457
+ action: SHARED_WORKER_ACTION.WAIT_FOR_ALL_UPLOADS,
458
+ });
459
+ });
460
+ }
461
+ else {
462
+ await Promise.allSettled(this.uploadPromises);
463
+ }
464
+ }
465
+ /**
466
+ * Get list of successfully uploaded files
467
+ */
468
+ getSuccessfulUploads() {
469
+ return [...this.successfulUploads];
470
+ }
471
+ /**
472
+ * Get list of all failed files
473
+ */
474
+ getFailedUploads() {
475
+ const failedUploads = [];
476
+ this.audioChunks.forEach((chunk) => {
477
+ if (chunk.status != 'success') {
478
+ failedUploads.push(chunk.fileName);
479
+ }
480
+ });
481
+ return failedUploads;
482
+ }
483
+ /**
484
+ * Get list of all audio chunks
485
+ */
486
+ getTotalAudioChunks() {
487
+ return this.audioChunks;
488
+ }
489
+ /**
490
+ * Retry uploading failed files
491
+ */
492
+ async retryFailedUploads() {
493
+ const failedFiles = this.getFailedUploads();
494
+ if (failedFiles.length === 0) {
495
+ return [];
496
+ }
497
+ if (this.sharedWorkerInstance) {
498
+ this.audioChunks.forEach((chunk, index) => {
499
+ const { fileName, fileBlob, status, audioFrames } = chunk;
500
+ if (status != 'success') {
501
+ this.sharedWorkerInstance?.port.postMessage({
502
+ action: SHARED_WORKER_ACTION.UPLOAD_FILE_WITH_WORKER,
503
+ payload: {
504
+ audioFrames,
505
+ fileBlob,
506
+ fileName: `${this.filePath}/${fileName}`,
507
+ txnID: this.txnID,
508
+ businessID: this.businessID,
509
+ chunkIndex: index,
510
+ fileCount: fileName,
511
+ },
512
+ });
513
+ }
514
+ });
515
+ }
516
+ else {
517
+ this.uploadPromises = []; // Reset upload promises for retries
518
+ if (this.onProgressCallback) {
519
+ this.onProgressCallback({
520
+ success: this.successfulUploads.length,
521
+ total: this.audioChunks.length,
522
+ });
523
+ }
524
+ this.audioChunks.forEach((chunk, index) => {
525
+ const { fileName, fileBlob, status, audioFrames } = chunk;
526
+ if (status != 'success') {
527
+ let failedFileBlob;
528
+ if (status === 'failure') {
529
+ failedFileBlob = fileBlob;
530
+ }
531
+ if (status === 'pending') {
532
+ const compressedAudioBuffer = compressAudioToMp3(audioFrames);
533
+ failedFileBlob = new Blob(compressedAudioBuffer, {
534
+ type: AUDIO_EXTENSION_TYPE_MAP[OUTPUT_FORMAT],
535
+ });
536
+ }
537
+ if (failedFileBlob) {
538
+ const uploadPromise = pushFileToS3({
539
+ fileBlob: failedFileBlob,
540
+ fileName: `${this.filePath}/${fileName}`,
541
+ txnID: this.txnID,
542
+ businessID: this.businessID,
543
+ is_shared_worker: false,
544
+ }).then((response) => {
545
+ if (response.success) {
546
+ this.successfulUploads.push(fileName);
547
+ if (this.onProgressCallback) {
548
+ this.onProgressCallback({
549
+ success: this.successfulUploads.length,
550
+ total: this.audioChunks.length,
551
+ });
552
+ }
553
+ this.audioChunks[index] = {
554
+ ...this.audioChunks[index],
555
+ audioFrames: undefined,
556
+ fileBlob: undefined,
557
+ status: 'success',
558
+ response: response.success,
559
+ };
560
+ }
561
+ return response;
562
+ });
563
+ this.uploadPromises.push(uploadPromise);
564
+ }
565
+ }
566
+ });
567
+ }
568
+ // Wait for all retry promises to complete
569
+ await this.waitForAllUploads();
570
+ return this.getFailedUploads();
571
+ }
572
+ /**
573
+ * Reset the upload state
574
+ */
575
+ resetFileManagerInstance() {
576
+ this.initialiseClassInstance();
577
+ }
578
+ }
579
+ export default AudioFileManager;
@@ -0,0 +1,90 @@
1
+ import { MicVAD } from '@ricky0123/vad-web';
2
+ declare class VadWebClient {
3
+ private vad_past;
4
+ private last_clip_index;
5
+ private clip_points;
6
+ private sil_duration_acc;
7
+ private pref_length_samples;
8
+ private desp_length_samples;
9
+ private max_length_samples;
10
+ private shor_thsld;
11
+ private long_thsld;
12
+ private frame_size;
13
+ private speech_pad_frames;
14
+ private micVad;
15
+ private is_vad_loading;
16
+ private noSpeechStartTime;
17
+ private recording_started;
18
+ private lastWarningTime;
19
+ private warningCooldownPeriod;
20
+ /**
21
+ * Class that handle Vad functions and manages audio chunk
22
+ * @param pref_length Preferred length in seconds
23
+ * @param desp_length Desperate length in seconds
24
+ * @param max_length Maximum length in seconds
25
+ * @param sr Sample rate in Hz
26
+ */
27
+ constructor(pref_length: number, desp_length: number, max_length: number, sr: number);
28
+ /**
29
+ * Check for continuous silence and trigger periodic warnings
30
+ * @param isSpeech - vad probability (0 or 1)
31
+ */
32
+ checkNoSpeech(isSpeech: number): void;
33
+ /**
34
+ * Get the micVad instance
35
+ */
36
+ getMicVad(): MicVAD;
37
+ /**
38
+ * Check if VAD is loading
39
+ */
40
+ isVadLoading(): boolean;
41
+ /**
42
+ * Process a VAD frame and determine if it's a clip point
43
+ * @param vad_frame Voice activity detection frame (0 for silence, 1 for speech)
44
+ */
45
+ processVadFrame(vad_frame: number): [boolean, number];
46
+ /**
47
+ * initialize the VAD instance
48
+ */
49
+ initVad(): Promise<boolean>;
50
+ /**
51
+ * reinitialize the vad instance
52
+ */
53
+ reinitializeVad(): Promise<boolean>;
54
+ /**
55
+ * process and upload audio chunk to s3
56
+ */
57
+ processAudioChunk({ audioFrames }: {
58
+ audioFrames?: Float32Array;
59
+ }): Promise<void>;
60
+ /**
61
+ * Start VAD
62
+ */
63
+ startVad(): void;
64
+ /**
65
+ * Pause VAD
66
+ */
67
+ pauseVad(): void;
68
+ /**
69
+ * reset vadWeb instance
70
+ */
71
+ resetVadWebInstance(): void;
72
+ /**
73
+ * monitor initial audio capture within starting 4 seconds
74
+ */
75
+ monitorAudioCapture(): void;
76
+ /**
77
+ * Callback to configure constants
78
+ */
79
+ configureVadConstants({ pref_length, desp_length, max_length, sr, frame_size, pre_speech_pad_frames, short_thsld, long_thsld, }: {
80
+ pref_length: number;
81
+ desp_length: number;
82
+ max_length: number;
83
+ sr: number;
84
+ frame_size: number;
85
+ pre_speech_pad_frames: number;
86
+ short_thsld: number;
87
+ long_thsld: number;
88
+ }): void;
89
+ }
90
+ export default VadWebClient;