@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.
- package/README.md +437 -0
- package/dist/api/get-transaction-history.d.ts +5 -0
- package/dist/api/get-transaction-history.js +28 -0
- package/dist/api/get-voice-api-v2-config.d.ts +2 -0
- package/dist/api/get-voice-api-v2-config.js +26 -0
- package/dist/api/get-voice-api-v2-status.d.ts +51 -0
- package/dist/api/get-voice-api-v2-status.js +25 -0
- package/dist/api/get-voice-api-v3-status.d.ts +51 -0
- package/dist/api/get-voice-api-v3-status.js +26 -0
- package/dist/api/patch-transaction-status.d.ts +4 -0
- package/dist/api/patch-transaction-status.js +43 -0
- package/dist/api/post-cog-init.d.ts +3 -0
- package/dist/api/post-cog-init.js +15 -0
- package/dist/api/post-transaction-commit.d.ts +3 -0
- package/dist/api/post-transaction-commit.js +32 -0
- package/dist/api/post-transaction-init.d.ts +3 -0
- package/dist/api/post-transaction-init.js +40 -0
- package/dist/api/post-transaction-stop.d.ts +3 -0
- package/dist/api/post-transaction-stop.js +32 -0
- package/dist/audio-chunker/__tests__/audio-file-manager.test.d.ts +1 -0
- package/dist/audio-chunker/__tests__/audio-file-manager.test.js +5 -0
- package/dist/audio-chunker/audio-buffer-manager.d.ts +53 -0
- package/dist/audio-chunker/audio-buffer-manager.js +136 -0
- package/dist/audio-chunker/audio-file-manager.d.ts +96 -0
- package/dist/audio-chunker/audio-file-manager.js +579 -0
- package/dist/audio-chunker/vad-web.d.ts +90 -0
- package/dist/audio-chunker/vad-web.js +389 -0
- package/dist/aws-services/configure-aws.d.ts +5 -0
- package/dist/aws-services/configure-aws.js +13 -0
- package/dist/aws-services/get-files-s3.d.ts +10 -0
- package/dist/aws-services/get-files-s3.js +30 -0
- package/dist/aws-services/s3-retry-wrapper.d.ts +2 -0
- package/dist/aws-services/s3-retry-wrapper.js +38 -0
- package/dist/aws-services/translate-text-to-target-language.d.ts +6 -0
- package/dist/aws-services/translate-text-to-target-language.js +18 -0
- package/dist/aws-services/upload-file-to-s3.d.ts +13 -0
- package/dist/aws-services/upload-file-to-s3.js +48 -0
- package/dist/constants/constant.d.ts +27 -0
- package/dist/constants/constant.js +33 -0
- package/dist/constants/enums.d.ts +46 -0
- package/dist/constants/enums.js +51 -0
- package/dist/constants/setup-config.d.ts +14 -0
- package/dist/constants/setup-config.js +31 -0
- package/dist/constants/types.d.ts +224 -0
- package/dist/constants/types.js +1 -0
- package/dist/fetch-client/helper.d.ts +11 -0
- package/dist/fetch-client/helper.js +28 -0
- package/dist/fetch-client/index.d.ts +1 -0
- package/dist/fetch-client/index.js +36 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +267 -0
- package/dist/main/end-recording.d.ts +3 -0
- package/dist/main/end-recording.js +141 -0
- package/dist/main/init-transaction.d.ts +3 -0
- package/dist/main/init-transaction.js +86 -0
- package/dist/main/pause-recording.d.ts +3 -0
- package/dist/main/pause-recording.js +59 -0
- package/dist/main/resume-recording.d.ts +3 -0
- package/dist/main/resume-recording.js +33 -0
- package/dist/main/retry-upload-recording.d.ts +5 -0
- package/dist/main/retry-upload-recording.js +69 -0
- package/dist/main/start-recording.d.ts +3 -0
- package/dist/main/start-recording.js +55 -0
- package/dist/shared-worker/s3-file-upload.d.ts +1 -0
- package/dist/shared-worker/s3-file-upload.js +109 -0
- package/dist/shared-worker/s3-file-upload.ts +126 -0
- package/dist/store/store.d.ts +35 -0
- package/dist/store/store.js +121 -0
- package/dist/utils/compress-mp3-audio.d.ts +2 -0
- package/dist/utils/compress-mp3-audio.js +24 -0
- package/package.json +53 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// ekascribe main Class having all the methods - Entry point
|
|
2
|
+
import { getConfigV2 } from './api/get-voice-api-v2-config';
|
|
3
|
+
import { getVoiceApiV3Status } from './api/get-voice-api-v3-status';
|
|
4
|
+
import patchTransactionStatus from './api/patch-transaction-status';
|
|
5
|
+
import postTransactionCommit from './api/post-transaction-commit';
|
|
6
|
+
import AudioBufferManager from './audio-chunker/audio-buffer-manager';
|
|
7
|
+
import AudioFileManager from './audio-chunker/audio-file-manager';
|
|
8
|
+
import VadWebClient from './audio-chunker/vad-web';
|
|
9
|
+
import { AUDIO_BUFFER_SIZE_IN_S, DESP_CHUNK_LENGTH, FRAME_RATE, MAX_CHUNK_LENGTH, PREF_CHUNK_LENGTH, SAMPLING_RATE, SDK_STATUS_CODE, } from './constants/constant';
|
|
10
|
+
import { ERROR_CODE } from './constants/enums';
|
|
11
|
+
import setEnv from './fetch-client/helper';
|
|
12
|
+
import endVoiceRecording from './main/end-recording';
|
|
13
|
+
import pauseVoiceRecording from './main/pause-recording';
|
|
14
|
+
import resumeVoiceRecording from './main/resume-recording';
|
|
15
|
+
import retryUploadFailedFiles from './main/retry-upload-recording';
|
|
16
|
+
import startVoiceRecording from './main/start-recording';
|
|
17
|
+
import EkaScribeStore from './store/store';
|
|
18
|
+
import initialiseTransaction from './main/init-transaction';
|
|
19
|
+
import getTransactionHistory from './api/get-transaction-history';
|
|
20
|
+
class EkaScribe {
|
|
21
|
+
// Private constructor to prevent direct instantiation
|
|
22
|
+
constructor() {
|
|
23
|
+
Object.defineProperty(this, "vadInstance", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
writable: true,
|
|
27
|
+
value: void 0
|
|
28
|
+
}); // vadWebClient Instance
|
|
29
|
+
Object.defineProperty(this, "audioFileManagerInstance", {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
configurable: true,
|
|
32
|
+
writable: true,
|
|
33
|
+
value: void 0
|
|
34
|
+
}); // AudioFileManager Instance
|
|
35
|
+
Object.defineProperty(this, "audioBufferInstance", {
|
|
36
|
+
enumerable: true,
|
|
37
|
+
configurable: true,
|
|
38
|
+
writable: true,
|
|
39
|
+
value: void 0
|
|
40
|
+
});
|
|
41
|
+
this.audioFileManagerInstance = new AudioFileManager();
|
|
42
|
+
console.log('%c Line:48 🥕 this.audioFileManagerInstance', 'color:#b03734', this.audioFileManagerInstance);
|
|
43
|
+
EkaScribeStore.audioFileManagerInstance = this.audioFileManagerInstance;
|
|
44
|
+
this.audioBufferInstance = new AudioBufferManager(SAMPLING_RATE, AUDIO_BUFFER_SIZE_IN_S);
|
|
45
|
+
console.log('%c Line:50 🍇 this.audioBufferInstance', 'color:#fca650', this.audioBufferInstance);
|
|
46
|
+
EkaScribeStore.audioBufferInstance = this.audioBufferInstance;
|
|
47
|
+
this.vadInstance = new VadWebClient(PREF_CHUNK_LENGTH, DESP_CHUNK_LENGTH, MAX_CHUNK_LENGTH, FRAME_RATE);
|
|
48
|
+
EkaScribeStore.vadInstance = this.vadInstance;
|
|
49
|
+
console.log('%c Line:62 🍖 this.vadInstance', 'color:#2eafb0', this.vadInstance);
|
|
50
|
+
}
|
|
51
|
+
// Static method to get the singleton instance with optional initialization
|
|
52
|
+
static getInstance({ access_token, env, clientId, }) {
|
|
53
|
+
if (!EkaScribe.instance) {
|
|
54
|
+
EkaScribe.instance = new EkaScribe();
|
|
55
|
+
// Initialize if params are provided
|
|
56
|
+
if (access_token) {
|
|
57
|
+
setEnv({
|
|
58
|
+
auth_token: access_token,
|
|
59
|
+
env,
|
|
60
|
+
clientId,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return EkaScribe.instance;
|
|
65
|
+
}
|
|
66
|
+
// Method to reset the singleton instance (useful for testing)
|
|
67
|
+
static resetInstance() {
|
|
68
|
+
EkaScribe.instance = null;
|
|
69
|
+
}
|
|
70
|
+
async getEkascribeConfig() {
|
|
71
|
+
console.log('Fetching EkaScribe configuration...');
|
|
72
|
+
const response = await getConfigV2();
|
|
73
|
+
return response;
|
|
74
|
+
}
|
|
75
|
+
updateAuthTokens({ access_token }) {
|
|
76
|
+
setEnv({
|
|
77
|
+
auth_token: access_token,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async initTransaction(request) {
|
|
81
|
+
console.log('Initializing transaction...');
|
|
82
|
+
const initTransactionResponse = await initialiseTransaction(request);
|
|
83
|
+
console.log(initTransactionResponse, 'initTransactionResponse');
|
|
84
|
+
return initTransactionResponse;
|
|
85
|
+
}
|
|
86
|
+
async startRecording() {
|
|
87
|
+
console.log('Starting recording...');
|
|
88
|
+
const startResponse = await startVoiceRecording();
|
|
89
|
+
console.log('%c Line:110 🍓 startResponse', 'color:#465975', startResponse);
|
|
90
|
+
return startResponse;
|
|
91
|
+
}
|
|
92
|
+
reinitializeVad() {
|
|
93
|
+
this.vadInstance.reinitializeVad();
|
|
94
|
+
}
|
|
95
|
+
pauseRecording() {
|
|
96
|
+
console.log('Pausing recording...');
|
|
97
|
+
const pauseRecordingResponse = pauseVoiceRecording();
|
|
98
|
+
console.log('%c Line:117 🍌 pauseRecordingResponse', 'color:#6ec1c2', pauseRecordingResponse);
|
|
99
|
+
return pauseRecordingResponse;
|
|
100
|
+
}
|
|
101
|
+
resumeRecording() {
|
|
102
|
+
console.log('Resuming recording...');
|
|
103
|
+
const resumeRecordingResponse = resumeVoiceRecording();
|
|
104
|
+
console.log('%c Line:124 🌶 resumeRecordingResponse', 'color:#33a5ff', resumeRecordingResponse);
|
|
105
|
+
return resumeRecordingResponse;
|
|
106
|
+
}
|
|
107
|
+
async endRecording() {
|
|
108
|
+
console.log('Ending recording...');
|
|
109
|
+
const endRecordingResponse = await endVoiceRecording();
|
|
110
|
+
console.log('%c Line:131 🍅 endRecordingResponse', 'color:#e41a6a', endRecordingResponse);
|
|
111
|
+
return endRecordingResponse;
|
|
112
|
+
}
|
|
113
|
+
async retryUploadRecording({ force_commit }) {
|
|
114
|
+
console.log('Retrying upload for failed files...');
|
|
115
|
+
const retryUploadResponse = await retryUploadFailedFiles({ force_commit });
|
|
116
|
+
console.log('%c Line:138 🍖 retryUploadResponse', 'color:#3f7cff', retryUploadResponse);
|
|
117
|
+
return retryUploadResponse;
|
|
118
|
+
}
|
|
119
|
+
async patchSessionStatus({ sessionId, processing_status, processing_error, }) {
|
|
120
|
+
try {
|
|
121
|
+
const patchTransactionResponse = await patchTransactionStatus({
|
|
122
|
+
sessionId,
|
|
123
|
+
processing_status,
|
|
124
|
+
processing_error,
|
|
125
|
+
});
|
|
126
|
+
this.resetEkaScribe();
|
|
127
|
+
return patchTransactionResponse;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
console.error('Error cancelling recording session:', error);
|
|
131
|
+
return {
|
|
132
|
+
code: SDK_STATUS_CODE.INTERNAL_SERVER_ERROR,
|
|
133
|
+
message: `Failed to cancel recording session, ${error}`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async commitTransactionCall() {
|
|
138
|
+
try {
|
|
139
|
+
const txnID = EkaScribeStore.txnID;
|
|
140
|
+
let txnCommitMsg = '';
|
|
141
|
+
if (EkaScribeStore.sessionStatus[txnID].api?.status === 'stop' ||
|
|
142
|
+
EkaScribeStore.sessionStatus[txnID].api?.status === 'commit') {
|
|
143
|
+
const audioInfo = this.audioFileManagerInstance?.audioChunks;
|
|
144
|
+
const audioFiles = audioInfo.map((audio) => audio.fileName);
|
|
145
|
+
const { message, code: txnCommitStatusCode } = await postTransactionCommit({
|
|
146
|
+
audioFiles,
|
|
147
|
+
txnId: EkaScribeStore.txnID,
|
|
148
|
+
});
|
|
149
|
+
txnCommitMsg = message;
|
|
150
|
+
if (txnCommitStatusCode != 200) {
|
|
151
|
+
return {
|
|
152
|
+
error_code: ERROR_CODE.TXN_COMMIT_FAILED,
|
|
153
|
+
status_code: txnCommitStatusCode,
|
|
154
|
+
message: txnCommitMsg || 'Transaction commit failed.',
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
EkaScribeStore.sessionStatus[txnID] = {
|
|
158
|
+
...EkaScribeStore.sessionStatus[txnID],
|
|
159
|
+
api: {
|
|
160
|
+
status: 'commit',
|
|
161
|
+
code: txnCommitStatusCode,
|
|
162
|
+
response: txnCommitMsg,
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
// transaction is not stopped or committed
|
|
168
|
+
return {
|
|
169
|
+
error_code: ERROR_CODE.TXN_STATUS_MISMATCH,
|
|
170
|
+
status_code: SDK_STATUS_CODE.TXN_ERROR,
|
|
171
|
+
message: 'Transaction is not initialised or stopped. Cannot end recording.',
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
status_code: SDK_STATUS_CODE.SUCCESS,
|
|
176
|
+
message: txnCommitMsg || 'Transaction committed successfully.',
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
console.error('Error in transaction commit: ', error);
|
|
181
|
+
return {
|
|
182
|
+
error_code: ERROR_CODE.INTERNAL_SERVER_ERROR,
|
|
183
|
+
status_code: SDK_STATUS_CODE.INTERNAL_SERVER_ERROR,
|
|
184
|
+
message: `Failed to cancel recording session, ${error}`,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async stopTransactionCall() {
|
|
189
|
+
// call endRecording method since all the steps are same
|
|
190
|
+
const endRecordingResponse = await endVoiceRecording();
|
|
191
|
+
return endRecordingResponse;
|
|
192
|
+
}
|
|
193
|
+
async getTemplateOutput({ txn_id }) {
|
|
194
|
+
try {
|
|
195
|
+
const getStatusResponse = await getVoiceApiV3Status({
|
|
196
|
+
txnId: txn_id,
|
|
197
|
+
});
|
|
198
|
+
return getStatusResponse;
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
console.error('Error in fetching templates response: ', error);
|
|
202
|
+
return {
|
|
203
|
+
status_code: SDK_STATUS_CODE.INTERNAL_SERVER_ERROR,
|
|
204
|
+
message: `Failed to fetch output templates, ${error}`,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
async getSessionHistory({ txn_count }) {
|
|
209
|
+
try {
|
|
210
|
+
const transactionsResponse = await getTransactionHistory({
|
|
211
|
+
txn_count,
|
|
212
|
+
});
|
|
213
|
+
return transactionsResponse;
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
console.error('Error cancelling recording session:', error);
|
|
217
|
+
return {
|
|
218
|
+
status_code: SDK_STATUS_CODE.INTERNAL_SERVER_ERROR,
|
|
219
|
+
message: `Failed to fetch previous transactions, ${error}`,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
getSuccessFiles() {
|
|
224
|
+
return this.audioFileManagerInstance.getSuccessfulUploads();
|
|
225
|
+
}
|
|
226
|
+
getFailedFiles() {
|
|
227
|
+
return this.audioFileManagerInstance.getFailedUploads();
|
|
228
|
+
}
|
|
229
|
+
getTotalAudioFiles() {
|
|
230
|
+
return this.audioFileManagerInstance.getTotalAudioChunks();
|
|
231
|
+
}
|
|
232
|
+
resetEkaScribe() {
|
|
233
|
+
this.audioFileManagerInstance.resetFileManagerInstance();
|
|
234
|
+
this.audioBufferInstance.resetBufferManagerInstance();
|
|
235
|
+
this.vadInstance.resetVadWebInstance();
|
|
236
|
+
EkaScribeStore.resetStore();
|
|
237
|
+
}
|
|
238
|
+
onError(callback) {
|
|
239
|
+
EkaScribeStore.errorCallback = callback;
|
|
240
|
+
}
|
|
241
|
+
onUserSpeechCallback(callback) {
|
|
242
|
+
EkaScribeStore.userSpeechCallback = callback;
|
|
243
|
+
}
|
|
244
|
+
onFileUploadProgressCallback(callback) {
|
|
245
|
+
this.audioFileManagerInstance.setProgressCallback(callback);
|
|
246
|
+
}
|
|
247
|
+
configureVadConstants({ pref_length, desp_length, max_length, sr, frame_size, pre_speech_pad_frames, short_thsld, long_thsld, }) {
|
|
248
|
+
return this.vadInstance.configureVadConstants({
|
|
249
|
+
pref_length,
|
|
250
|
+
desp_length,
|
|
251
|
+
max_length,
|
|
252
|
+
sr,
|
|
253
|
+
frame_size,
|
|
254
|
+
pre_speech_pad_frames,
|
|
255
|
+
short_thsld,
|
|
256
|
+
long_thsld,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
Object.defineProperty(EkaScribe, "instance", {
|
|
261
|
+
enumerable: true,
|
|
262
|
+
configurable: true,
|
|
263
|
+
writable: true,
|
|
264
|
+
value: null
|
|
265
|
+
});
|
|
266
|
+
// Export the singleton instance getter with optional initialization
|
|
267
|
+
export const getEkaScribeInstance = ({ access_token, env, clientId, }) => EkaScribe.getInstance({ access_token, env, clientId });
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import postTransactionCommit from '../api/post-transaction-commit';
|
|
2
|
+
import postTransactionStop from '../api/post-transaction-stop';
|
|
3
|
+
import { OUTPUT_FORMAT, SDK_STATUS_CODE } from '../constants/constant';
|
|
4
|
+
import { ERROR_CODE } from '../constants/enums';
|
|
5
|
+
import EkaScribeStore from '../store/store';
|
|
6
|
+
const endVoiceRecording = async () => {
|
|
7
|
+
try {
|
|
8
|
+
const audioBufferInstance = EkaScribeStore.audioBufferInstance;
|
|
9
|
+
const fileManagerInstance = EkaScribeStore.audioFileManagerInstance;
|
|
10
|
+
const vadInstance = EkaScribeStore.vadInstance;
|
|
11
|
+
const txnID = EkaScribeStore.txnID;
|
|
12
|
+
if (!fileManagerInstance || !audioBufferInstance || !vadInstance) {
|
|
13
|
+
throw new Error('Class instances are not initialized');
|
|
14
|
+
}
|
|
15
|
+
vadInstance.pauseVad();
|
|
16
|
+
EkaScribeStore.sessionStatus[txnID] = {
|
|
17
|
+
...EkaScribeStore.sessionStatus[txnID],
|
|
18
|
+
vad: {
|
|
19
|
+
status: 'stop',
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
// upload last audio chunk
|
|
23
|
+
if (audioBufferInstance.getCurrentSampleLength() > 0) {
|
|
24
|
+
const audioFrames = audioBufferInstance.getAudioData();
|
|
25
|
+
const filenumber = (fileManagerInstance.audioChunks.length || 0) + 1;
|
|
26
|
+
const fileName = `${filenumber}.${OUTPUT_FORMAT}`;
|
|
27
|
+
const rawSampleDetails = fileManagerInstance.getRawSampleDetails();
|
|
28
|
+
const chunkTimestamps = audioBufferInstance.calculateChunkTimestamps(rawSampleDetails.totalRawSamples);
|
|
29
|
+
const chunkInfo = {
|
|
30
|
+
fileName,
|
|
31
|
+
timestamp: {
|
|
32
|
+
st: chunkTimestamps.start,
|
|
33
|
+
et: chunkTimestamps.end,
|
|
34
|
+
},
|
|
35
|
+
status: 'pending',
|
|
36
|
+
audioFrames,
|
|
37
|
+
};
|
|
38
|
+
const audioChunkLength = fileManagerInstance.updateAudioInfo(chunkInfo);
|
|
39
|
+
fileManagerInstance?.incrementInsertedSamples(audioBufferInstance.getCurrentSampleLength(), audioBufferInstance.getCurrentFrameLength());
|
|
40
|
+
audioBufferInstance.resetBufferState();
|
|
41
|
+
await fileManagerInstance.uploadAudioToS3({
|
|
42
|
+
audioFrames,
|
|
43
|
+
fileName,
|
|
44
|
+
chunkIndex: audioChunkLength - 1,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
await fileManagerInstance.waitForAllUploads();
|
|
48
|
+
const audioInfo = fileManagerInstance?.audioChunks;
|
|
49
|
+
const audioFiles = audioInfo.map((audio) => audio.fileName);
|
|
50
|
+
// call stop txn api
|
|
51
|
+
if (EkaScribeStore.sessionStatus[txnID].api?.status === 'init') {
|
|
52
|
+
const { message: txnStopMsg, code: txnStopStatusCode } = await postTransactionStop({
|
|
53
|
+
audioFiles,
|
|
54
|
+
txnId: txnID,
|
|
55
|
+
});
|
|
56
|
+
if (txnStopStatusCode != 200) {
|
|
57
|
+
return {
|
|
58
|
+
error_code: ERROR_CODE.TXN_STOP_FAILED,
|
|
59
|
+
status_code: txnStopStatusCode,
|
|
60
|
+
message: txnStopMsg || 'Transaction stop failed.',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
EkaScribeStore.sessionStatus[txnID] = {
|
|
64
|
+
...EkaScribeStore.sessionStatus[txnID],
|
|
65
|
+
api: {
|
|
66
|
+
status: 'stop',
|
|
67
|
+
code: txnStopStatusCode,
|
|
68
|
+
response: txnStopMsg,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
else if (EkaScribeStore.sessionStatus[txnID].api?.status === 'na') {
|
|
73
|
+
// transaction is not initialised
|
|
74
|
+
return {
|
|
75
|
+
error_code: ERROR_CODE.TXN_STATUS_MISMATCH,
|
|
76
|
+
status_code: SDK_STATUS_CODE.TXN_ERROR,
|
|
77
|
+
message: 'Transaction is not initialized. Cannot end recording.',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const failedFiles = fileManagerInstance.getFailedUploads() || [];
|
|
81
|
+
let retryFailedFiles = [];
|
|
82
|
+
// retry upload once if there are any failed uploads
|
|
83
|
+
if (failedFiles.length > 0) {
|
|
84
|
+
retryFailedFiles = await fileManagerInstance.retryFailedUploads();
|
|
85
|
+
}
|
|
86
|
+
// if there are still failed uploads after retry, return error
|
|
87
|
+
if (retryFailedFiles.length > 0) {
|
|
88
|
+
return {
|
|
89
|
+
error_code: ERROR_CODE.AUDIO_UPLOAD_FAILED,
|
|
90
|
+
status_code: SDK_STATUS_CODE.AUDIO_ERROR,
|
|
91
|
+
message: 'Audio upload failed for some files after retry.',
|
|
92
|
+
failed_files: retryFailedFiles,
|
|
93
|
+
total_audio_files: audioFiles,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// call commit transaction api
|
|
97
|
+
if (EkaScribeStore.sessionStatus[txnID].api?.status === 'stop' ||
|
|
98
|
+
EkaScribeStore.sessionStatus[txnID].api?.status === 'commit') {
|
|
99
|
+
const { message: txnCommitMsg, code: txnCommitStatusCode } = await postTransactionCommit({
|
|
100
|
+
txnId: txnID,
|
|
101
|
+
audioFiles,
|
|
102
|
+
});
|
|
103
|
+
if (txnCommitStatusCode != 200) {
|
|
104
|
+
return {
|
|
105
|
+
error_code: ERROR_CODE.TXN_COMMIT_FAILED,
|
|
106
|
+
status_code: txnCommitStatusCode,
|
|
107
|
+
message: txnCommitMsg || 'Transaction stop failed.',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
EkaScribeStore.sessionStatus[txnID] = {
|
|
111
|
+
...EkaScribeStore.sessionStatus[txnID],
|
|
112
|
+
api: {
|
|
113
|
+
status: 'commit',
|
|
114
|
+
code: txnCommitStatusCode,
|
|
115
|
+
response: txnCommitMsg,
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
// transaction is not stopped or committed
|
|
121
|
+
return {
|
|
122
|
+
error_code: ERROR_CODE.TXN_STATUS_MISMATCH,
|
|
123
|
+
status_code: SDK_STATUS_CODE.TXN_ERROR,
|
|
124
|
+
message: 'Transaction is not initialised or stopped. Cannot end recording.',
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
status_code: SDK_STATUS_CODE.SUCCESS,
|
|
129
|
+
message: 'Recording ended successfully.',
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
console.error('Error ending recording: ', error);
|
|
134
|
+
return {
|
|
135
|
+
error_code: ERROR_CODE.INTERNAL_SERVER_ERROR,
|
|
136
|
+
status_code: SDK_STATUS_CODE.INTERNAL_SERVER_ERROR,
|
|
137
|
+
message: `An error occurred while ending the recording: ${error}`,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
export default endVoiceRecording;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { TStartRecordingRequest, TStartRecordingResponse } from '../constants/types';
|
|
2
|
+
declare const initialiseTransaction: ({ mode, input_language, output_format_template, txn_id, auto_download, model_training_consent, transfer, system_info, patient_details, }: TStartRecordingRequest) => Promise<TStartRecordingResponse>;
|
|
3
|
+
export default initialiseTransaction;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import postTransactionInit from '../api/post-transaction-init';
|
|
2
|
+
import { S3_BUCKET_NAME, SDK_STATUS_CODE } from '../constants/constant';
|
|
3
|
+
import { ERROR_CODE } from '../constants/enums';
|
|
4
|
+
import EkaScribeStore from '../store/store';
|
|
5
|
+
const initialiseTransaction = async ({ mode, input_language, output_format_template, txn_id, auto_download, model_training_consent, transfer, system_info, patient_details, }) => {
|
|
6
|
+
try {
|
|
7
|
+
const fileManagerInstance = EkaScribeStore.audioFileManagerInstance;
|
|
8
|
+
const sessionStatus = EkaScribeStore.sessionStatus;
|
|
9
|
+
let businessID = '';
|
|
10
|
+
let userOID = '';
|
|
11
|
+
let userUUID = '';
|
|
12
|
+
if (!sessionStatus[txn_id] ||
|
|
13
|
+
Object.keys(sessionStatus[txn_id]).length === 0 ||
|
|
14
|
+
sessionStatus[txn_id].api?.status === 'na') {
|
|
15
|
+
EkaScribeStore.txnID = txn_id;
|
|
16
|
+
// File path calculation
|
|
17
|
+
const date = new Date();
|
|
18
|
+
// Format date to YYYYMMDD
|
|
19
|
+
const day = date.getDate().toString().padStart(2, '0');
|
|
20
|
+
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
21
|
+
const year = date.getFullYear().toString().substring(2);
|
|
22
|
+
// s3 file path format: <date>/txnID
|
|
23
|
+
const filePath = `${year}${month}${day}/${txn_id}`;
|
|
24
|
+
EkaScribeStore.sessionBucketPath = filePath;
|
|
25
|
+
const txnInitResponse = await postTransactionInit({
|
|
26
|
+
mode,
|
|
27
|
+
txnId: txn_id,
|
|
28
|
+
s3Url: `s3://${S3_BUCKET_NAME}/${filePath}`,
|
|
29
|
+
input_language,
|
|
30
|
+
output_format_template,
|
|
31
|
+
transfer,
|
|
32
|
+
auto_download,
|
|
33
|
+
model_training_consent,
|
|
34
|
+
system_info,
|
|
35
|
+
patient_details,
|
|
36
|
+
});
|
|
37
|
+
const { code: txnInitStatusCode, b_id: businessId, oid, uuid, message: txnInitMessage, error: txnInitError, } = txnInitResponse;
|
|
38
|
+
if (txnInitStatusCode === 400 && txnInitError?.code === ERROR_CODE.TXN_LIMIT_EXCEEDED) {
|
|
39
|
+
return {
|
|
40
|
+
error_code: ERROR_CODE.TXN_LIMIT_EXCEEDED,
|
|
41
|
+
status_code: txnInitStatusCode,
|
|
42
|
+
message: txnInitMessage || 'Transaction limit exceeded.',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (txnInitStatusCode >= 400) {
|
|
46
|
+
return {
|
|
47
|
+
error_code: ERROR_CODE.TXN_INIT_FAILED,
|
|
48
|
+
status_code: txnInitStatusCode,
|
|
49
|
+
message: txnInitMessage || 'Transaction initialization failed.',
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
EkaScribeStore.sessionStatus[txn_id] = {
|
|
53
|
+
api: {
|
|
54
|
+
status: 'init',
|
|
55
|
+
code: txnInitStatusCode,
|
|
56
|
+
response: txnInitMessage,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
businessID = businessId;
|
|
60
|
+
userOID = oid;
|
|
61
|
+
userUUID = uuid;
|
|
62
|
+
fileManagerInstance?.setSessionInfo({
|
|
63
|
+
sessionId: txn_id,
|
|
64
|
+
filePath: filePath,
|
|
65
|
+
businessID: businessId,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
message: 'Transaction initialized successfully.',
|
|
70
|
+
status_code: SDK_STATUS_CODE.SUCCESS,
|
|
71
|
+
business_id: businessID,
|
|
72
|
+
oid: userOID,
|
|
73
|
+
uuid: userUUID,
|
|
74
|
+
txn_id,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
console.log('%c Line:102 🍇 initialiseTransaction err', 'color:#b03734', err);
|
|
79
|
+
return {
|
|
80
|
+
error_code: ERROR_CODE.INTERNAL_SERVER_ERROR,
|
|
81
|
+
status_code: SDK_STATUS_CODE.INTERNAL_SERVER_ERROR,
|
|
82
|
+
message: `An error occurred in initializing the transaction: ${err}`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
export default initialiseTransaction;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { OUTPUT_FORMAT, SDK_STATUS_CODE } from '../constants/constant';
|
|
2
|
+
import { ERROR_CODE } from '../constants/enums';
|
|
3
|
+
import EkaScribeStore from '../store/store';
|
|
4
|
+
const pauseVoiceRecording = () => {
|
|
5
|
+
try {
|
|
6
|
+
const audioBufferInstance = EkaScribeStore.audioBufferInstance;
|
|
7
|
+
const fileManagerInstance = EkaScribeStore.audioFileManagerInstance;
|
|
8
|
+
const vadInstance = EkaScribeStore.vadInstance;
|
|
9
|
+
if (!fileManagerInstance || !audioBufferInstance || !vadInstance) {
|
|
10
|
+
throw new Error('Class instances are not initialized');
|
|
11
|
+
}
|
|
12
|
+
vadInstance.pauseVad();
|
|
13
|
+
const txn_id = EkaScribeStore.txnID;
|
|
14
|
+
EkaScribeStore.sessionStatus[txn_id] = {
|
|
15
|
+
...EkaScribeStore.sessionStatus[txn_id],
|
|
16
|
+
vad: {
|
|
17
|
+
status: 'pause',
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
if (audioBufferInstance.getCurrentSampleLength() > 0) {
|
|
21
|
+
const audioFrames = audioBufferInstance.getAudioData();
|
|
22
|
+
const filenumber = (fileManagerInstance.audioChunks.length || 0) + 1;
|
|
23
|
+
const fileName = `${filenumber}.${OUTPUT_FORMAT}`;
|
|
24
|
+
const rawSampleDetails = fileManagerInstance.getRawSampleDetails();
|
|
25
|
+
const chunkTimestamps = audioBufferInstance.calculateChunkTimestamps(rawSampleDetails.totalRawSamples);
|
|
26
|
+
const chunkInfo = {
|
|
27
|
+
fileName,
|
|
28
|
+
timestamp: {
|
|
29
|
+
st: chunkTimestamps.start,
|
|
30
|
+
et: chunkTimestamps.end,
|
|
31
|
+
},
|
|
32
|
+
status: 'pending',
|
|
33
|
+
audioFrames,
|
|
34
|
+
};
|
|
35
|
+
const audioChunkLength = fileManagerInstance.updateAudioInfo(chunkInfo);
|
|
36
|
+
fileManagerInstance?.incrementInsertedSamples(audioBufferInstance.getCurrentSampleLength(), audioBufferInstance.getCurrentFrameLength());
|
|
37
|
+
audioBufferInstance.resetBufferState();
|
|
38
|
+
fileManagerInstance.uploadAudioToS3({
|
|
39
|
+
audioFrames,
|
|
40
|
+
fileName,
|
|
41
|
+
chunkIndex: audioChunkLength - 1,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
status_code: SDK_STATUS_CODE.SUCCESS,
|
|
46
|
+
message: 'Recording paused successfully',
|
|
47
|
+
is_paused: true,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
console.log('%c Line:7 🍔 pauseRecording error', 'color:#3f7cff', error);
|
|
52
|
+
return {
|
|
53
|
+
error_code: ERROR_CODE.INTERNAL_SERVER_ERROR,
|
|
54
|
+
status_code: SDK_STATUS_CODE.INTERNAL_SERVER_ERROR,
|
|
55
|
+
message: `An error occurred while starting the recording: ${error}`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
export default pauseVoiceRecording;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { SDK_STATUS_CODE } from '../constants/constant';
|
|
2
|
+
import { ERROR_CODE } from '../constants/enums';
|
|
3
|
+
import EkaScribeStore from '../store/store';
|
|
4
|
+
const resumeVoiceRecording = () => {
|
|
5
|
+
try {
|
|
6
|
+
const vadInstance = EkaScribeStore.vadInstance;
|
|
7
|
+
if (!vadInstance) {
|
|
8
|
+
throw new Error('VAD instance is not initialized');
|
|
9
|
+
}
|
|
10
|
+
vadInstance.startVad();
|
|
11
|
+
const txn_id = EkaScribeStore.txnID;
|
|
12
|
+
EkaScribeStore.sessionStatus[txn_id] = {
|
|
13
|
+
...EkaScribeStore.sessionStatus[txn_id],
|
|
14
|
+
vad: {
|
|
15
|
+
status: 'resume',
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
status_code: SDK_STATUS_CODE.SUCCESS,
|
|
20
|
+
message: 'Recording resumed successfully',
|
|
21
|
+
is_paused: false,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
console.error('Error resuming recording:', error);
|
|
26
|
+
return {
|
|
27
|
+
error_code: ERROR_CODE.INTERNAL_SERVER_ERROR,
|
|
28
|
+
status_code: SDK_STATUS_CODE.INTERNAL_SERVER_ERROR,
|
|
29
|
+
message: `Failed to resume recording: ${error}`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
export default resumeVoiceRecording;
|