easyproctor-hml 2.8.0 → 3.1.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.
- package/README.md +6 -0
- package/esm/index.js +77 -47
- package/index.js +77 -47
- package/new-flow/proctoring/ProctoringUploader.d.ts +0 -1
- package/new-flow/recorders/AlertRecorder.d.ts +2 -0
- package/package.json +1 -1
- package/plugins/recorder.d.ts +5 -1
- package/unpkg/easyproctor.min.js +27 -27
package/README.md
CHANGED
|
@@ -263,6 +263,12 @@ const {
|
|
|
263
263
|
token: "...",
|
|
264
264
|
});
|
|
265
265
|
```
|
|
266
|
+
|
|
267
|
+
## Release Note V 3.0.0
|
|
268
|
+
- Envio do vídeo por partes durante o exame para o proctoring REALTIME
|
|
269
|
+
- Fix: correção do bug do import pacote fix-webm-duration
|
|
270
|
+
- Possibilidade de check automático no check devices através do parametro 'auto'
|
|
271
|
+
|
|
266
272
|
## Release Note V 2.7.0
|
|
267
273
|
- Implementação da comunicação com a API para o proctoring do tipo realtime
|
|
268
274
|
- Envio do vídeo durante o exame
|
package/esm/index.js
CHANGED
|
@@ -12771,7 +12771,7 @@ var proctoringId;
|
|
|
12771
12771
|
function setRecorderProctoringId(id) {
|
|
12772
12772
|
proctoringId = id;
|
|
12773
12773
|
}
|
|
12774
|
-
function recorder(stream, buffer, onBufferSizeError = false, onBufferSizeErrorCallback, audio = false) {
|
|
12774
|
+
function recorder(stream, buffer, onBufferSizeError = false, onBufferSizeErrorCallback, audio = false, recorderOpts) {
|
|
12775
12775
|
let resolvePromise;
|
|
12776
12776
|
let onBufferSizeInterval;
|
|
12777
12777
|
let lastEvent;
|
|
@@ -12779,6 +12779,7 @@ function recorder(stream, buffer, onBufferSizeError = false, onBufferSizeErrorCa
|
|
|
12779
12779
|
bufferSize = 0;
|
|
12780
12780
|
let startTime;
|
|
12781
12781
|
let duration = 0;
|
|
12782
|
+
let chunkIndex = 0;
|
|
12782
12783
|
let recorderOptions = {
|
|
12783
12784
|
// eslint-disable-next-line no-useless-escape
|
|
12784
12785
|
mimeType: "video/webm",
|
|
@@ -12813,6 +12814,10 @@ function recorder(stream, buffer, onBufferSizeError = false, onBufferSizeErrorCa
|
|
|
12813
12814
|
mediaRecorder2.ondataavailable = (e3) => {
|
|
12814
12815
|
bufferSize = bufferSize + e3.data.size;
|
|
12815
12816
|
if (e3.data.size > 0) {
|
|
12817
|
+
if (recorderOpts == null ? void 0 : recorderOpts.onChunkAvailable) {
|
|
12818
|
+
recorderOpts.onChunkAvailable(e3.data, chunkIndex);
|
|
12819
|
+
chunkIndex++;
|
|
12820
|
+
}
|
|
12816
12821
|
buffer.push(e3.data);
|
|
12817
12822
|
}
|
|
12818
12823
|
};
|
|
@@ -12844,7 +12849,13 @@ function recorder(stream, buffer, onBufferSizeError = false, onBufferSizeErrorCa
|
|
|
12844
12849
|
};
|
|
12845
12850
|
try {
|
|
12846
12851
|
console.log("State antes do start:", recorder2.state);
|
|
12847
|
-
|
|
12852
|
+
chunkIndex = 0;
|
|
12853
|
+
if ((recorderOpts == null ? void 0 : recorderOpts.timeslice) && (recorderOpts == null ? void 0 : recorderOpts.timeslice) > 0) {
|
|
12854
|
+
recorder2.start(recorderOpts.timeslice);
|
|
12855
|
+
} else {
|
|
12856
|
+
recorder2.start(1e4);
|
|
12857
|
+
}
|
|
12858
|
+
bufferSize = 0;
|
|
12848
12859
|
startTime = new Date(Date.now());
|
|
12849
12860
|
} catch (e3) {
|
|
12850
12861
|
console.error("Recorder erro ao chamar start event:", e3);
|
|
@@ -13258,9 +13269,6 @@ var ObjectDetection = class extends BaseDetection {
|
|
|
13258
13269
|
}
|
|
13259
13270
|
};
|
|
13260
13271
|
|
|
13261
|
-
// src/new-flow/recorders/CameraRecorder.ts
|
|
13262
|
-
var import_jszip_min = __toESM(require_jszip_min());
|
|
13263
|
-
|
|
13264
13272
|
// src/new-flow/chunk/ChunkStorageService.ts
|
|
13265
13273
|
var _ChunkStorageService = class _ChunkStorageService {
|
|
13266
13274
|
constructor() {
|
|
@@ -13872,6 +13880,7 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
13872
13880
|
};
|
|
13873
13881
|
|
|
13874
13882
|
// src/new-flow/recorders/CameraRecorder.ts
|
|
13883
|
+
var import_jszip_min = __toESM(require_jszip_min());
|
|
13875
13884
|
var pkg = require_fix_webm_duration();
|
|
13876
13885
|
var fixWebmDuration = pkg.default || pkg;
|
|
13877
13886
|
var _CameraRecorder = class _CameraRecorder {
|
|
@@ -13944,11 +13953,11 @@ var _CameraRecorder = class _CameraRecorder {
|
|
|
13944
13953
|
paramsConfig && (this.paramsConfig = paramsConfig);
|
|
13945
13954
|
}
|
|
13946
13955
|
/**
|
|
13947
|
-
|
|
13948
|
-
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
|
|
13956
|
+
* Determina se o fluxo de chunks e lifecycle deve estar ativo.
|
|
13957
|
+
* Retorna true se:
|
|
13958
|
+
* 1. O proctoringId já foi definido (ou seja, estamos em uma sessão real, NÃO no checkDevices)
|
|
13959
|
+
* 2. E (`useChunkRecording` foi explicitamente setado como true OU o dispositivo é mobile)
|
|
13960
|
+
*/
|
|
13952
13961
|
get isChunkEnabled() {
|
|
13953
13962
|
return !!this.proctoringId && this.options.proctoringType === "REALTIME" && !isSafeBrowser();
|
|
13954
13963
|
}
|
|
@@ -14211,9 +14220,15 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14211
14220
|
await new Promise((r3) => setTimeout(r3, 300));
|
|
14212
14221
|
}
|
|
14213
14222
|
async startRecording() {
|
|
14214
|
-
var _a2, _b, _c2, _d, _e3, _f, _g;
|
|
14223
|
+
var _a2, _b, _c2, _d, _e3, _f, _g, _h;
|
|
14215
14224
|
await this.startStream();
|
|
14216
14225
|
await this.attachAndWarmup(this.cameraStream);
|
|
14226
|
+
const recorderOpts = this.isChunkEnabled ? {
|
|
14227
|
+
timeslice: _CameraRecorder.CHUNK_TIMESLICE_MS,
|
|
14228
|
+
onChunkAvailable: (blob, idx) => {
|
|
14229
|
+
this.handleNewChunk(blob, idx);
|
|
14230
|
+
}
|
|
14231
|
+
} : {};
|
|
14217
14232
|
const {
|
|
14218
14233
|
startRecording,
|
|
14219
14234
|
stopRecording,
|
|
@@ -14229,7 +14244,8 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14229
14244
|
this.blobs,
|
|
14230
14245
|
this.options.onBufferSizeError,
|
|
14231
14246
|
(e3) => this.bufferError(e3),
|
|
14232
|
-
false
|
|
14247
|
+
false,
|
|
14248
|
+
recorderOpts
|
|
14233
14249
|
);
|
|
14234
14250
|
this.recordingStart = startRecording;
|
|
14235
14251
|
this.recordingStop = stopRecording;
|
|
@@ -14239,13 +14255,18 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14239
14255
|
this.getBufferSize = getBufferSize;
|
|
14240
14256
|
this.getStartTime = getStartTime;
|
|
14241
14257
|
this.getDuration = getDuration;
|
|
14258
|
+
this.chunkIndex = 0;
|
|
14259
|
+
if (this.isChunkEnabled) {
|
|
14260
|
+
(_a2 = this.backgroundUpload) == null ? void 0 : _a2.start();
|
|
14261
|
+
this.setupLifecycleListeners();
|
|
14262
|
+
}
|
|
14242
14263
|
try {
|
|
14243
14264
|
await new Promise((r3) => setTimeout(r3, 500));
|
|
14244
14265
|
await this.recordingStart();
|
|
14245
14266
|
} catch (error) {
|
|
14246
14267
|
console.log("Camera Recorder error", error);
|
|
14247
14268
|
this.stopRecording();
|
|
14248
|
-
const maxRetries = ((
|
|
14269
|
+
const maxRetries = ((_b = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _b.maxRetries) || 3;
|
|
14249
14270
|
if (this.currentRetries < maxRetries) {
|
|
14250
14271
|
console.log("Camera Recorder retry", this.currentRetries);
|
|
14251
14272
|
this.currentRetries++;
|
|
@@ -14255,13 +14276,13 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14255
14276
|
}
|
|
14256
14277
|
}
|
|
14257
14278
|
this.stopped = false;
|
|
14258
|
-
if (((
|
|
14279
|
+
if (((_c2 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _c2.detectPerson) || ((_d = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _d.detectCellPhone) || ((_e3 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _e3.detectFace)) {
|
|
14259
14280
|
await this.initializeDetectors();
|
|
14260
14281
|
}
|
|
14261
|
-
if ((
|
|
14282
|
+
if ((_f = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _f.detectFace) {
|
|
14262
14283
|
await this.faceDetection.enableCam(this.cameraStream);
|
|
14263
14284
|
}
|
|
14264
|
-
if (((
|
|
14285
|
+
if (((_g = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _g.detectPerson) || ((_h = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _h.detectCellPhone)) {
|
|
14265
14286
|
await this.objectDetection.enableCam(this.cameraStream);
|
|
14266
14287
|
}
|
|
14267
14288
|
this.filesToUpload = [];
|
|
@@ -14500,7 +14521,7 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14500
14521
|
if (this.blobs != null)
|
|
14501
14522
|
trackers.registerSaveOnSession(
|
|
14502
14523
|
this.proctoringId,
|
|
14503
|
-
`Blobs Length: ${this.blobs.length} Buffer Size: ${this.getBufferSize()} `
|
|
14524
|
+
`Blobs Length: ${this.blobs.length} Buffer Size: ${this.getBufferSize()} ChunkEnabled: ${this.isChunkEnabled}`
|
|
14504
14525
|
);
|
|
14505
14526
|
const settings = this.cameraStream.getVideoTracks()[0].getSettings();
|
|
14506
14527
|
const settingsAudio = this.cameraStream.getAudioTracks()[0].getSettings();
|
|
@@ -14520,7 +14541,12 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14520
14541
|
});
|
|
14521
14542
|
let finalBlob = rawBlob;
|
|
14522
14543
|
if (typeof fixWebmDuration === "function") {
|
|
14523
|
-
|
|
14544
|
+
try {
|
|
14545
|
+
finalBlob = await fixWebmDuration(rawBlob, this.duration);
|
|
14546
|
+
} catch (e3) {
|
|
14547
|
+
console.warn("Erro ao corrigir a dura\xE7\xE3o do v\xEDdeo", e3);
|
|
14548
|
+
finalBlob = rawBlob;
|
|
14549
|
+
}
|
|
14524
14550
|
} else {
|
|
14525
14551
|
console.warn("fixWebmDuration n\xE3o dispon\xEDvel");
|
|
14526
14552
|
}
|
|
@@ -16666,19 +16692,9 @@ var ProctoringUploader = class {
|
|
|
16666
16692
|
}
|
|
16667
16693
|
toFile(rec) {
|
|
16668
16694
|
const suffix = rec.origin === "Screen" /* Screen */ ? "screen" : rec.origin === "Camera" /* Camera */ ? "camera" : "audio";
|
|
16669
|
-
const name = `EP_${this.
|
|
16695
|
+
const name = `EP_${this.session.id}_${suffix}_0.webm`;
|
|
16670
16696
|
return new File([rec.arrayBuffer], name, { type: "video/webm" });
|
|
16671
16697
|
}
|
|
16672
|
-
getFileType(origin2) {
|
|
16673
|
-
switch (origin2) {
|
|
16674
|
-
case "Camera" /* Camera */:
|
|
16675
|
-
return "Camera";
|
|
16676
|
-
case "Screen" /* Screen */:
|
|
16677
|
-
return "Screen";
|
|
16678
|
-
case "Mic" /* Mic */:
|
|
16679
|
-
return "Audio";
|
|
16680
|
-
}
|
|
16681
|
-
}
|
|
16682
16698
|
async uploadFile(rec, token, onProgress) {
|
|
16683
16699
|
const file = this.toFile(rec);
|
|
16684
16700
|
for await (const uploadService of this.uploadServices) {
|
|
@@ -16690,24 +16706,23 @@ var ProctoringUploader = class {
|
|
|
16690
16706
|
}
|
|
16691
16707
|
},
|
|
16692
16708
|
token
|
|
16693
|
-
).catch(
|
|
16694
|
-
|
|
16695
|
-
this.proctoringId,
|
|
16696
|
-
`Upload File
|
|
16709
|
+
).catch(
|
|
16710
|
+
async (e3) => {
|
|
16711
|
+
console.log("Upload File Error", e3), trackers.registerError(this.proctoringId, `Upload File
|
|
16697
16712
|
Name: ${file.name}
|
|
16698
16713
|
Error: ${e3.message}
|
|
16699
|
-
Size: ${e3.error}`
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
}
|
|
16707
|
-
|
|
16708
|
-
|
|
16709
|
-
|
|
16710
|
-
|
|
16714
|
+
Size: ${e3.error}`);
|
|
16715
|
+
await uploadService.upload(
|
|
16716
|
+
{
|
|
16717
|
+
file,
|
|
16718
|
+
onProgress: (progress) => {
|
|
16719
|
+
if (onProgress) onProgress(progress);
|
|
16720
|
+
}
|
|
16721
|
+
},
|
|
16722
|
+
token
|
|
16723
|
+
);
|
|
16724
|
+
}
|
|
16725
|
+
);
|
|
16711
16726
|
if (result) {
|
|
16712
16727
|
let fileType = "";
|
|
16713
16728
|
if (rec.origin === "Camera" /* Camera */) {
|
|
@@ -16746,8 +16761,9 @@ var AlertRecorder = class {
|
|
|
16746
16761
|
this.handleLostFocus();
|
|
16747
16762
|
}
|
|
16748
16763
|
};
|
|
16764
|
+
this.lastLostFocusTime = Date.now();
|
|
16749
16765
|
this.handleLostFocus = () => {
|
|
16750
|
-
if (this.getRelativeTime() > 1e4) {
|
|
16766
|
+
if (this.getRelativeTime() > 1e4 && Date.now() - this.lastLostFocusTime > 1e3) {
|
|
16751
16767
|
const alertPayload = {
|
|
16752
16768
|
begin: this.getRelativeTime(),
|
|
16753
16769
|
end: 0,
|
|
@@ -16756,9 +16772,13 @@ var AlertRecorder = class {
|
|
|
16756
16772
|
};
|
|
16757
16773
|
this.onLostFocusCallback(alertPayload);
|
|
16758
16774
|
this.alerts.push(alertPayload);
|
|
16775
|
+
this.lastLostFocusTime = Date.now();
|
|
16759
16776
|
}
|
|
16760
16777
|
};
|
|
16778
|
+
this.lastReturnFocusTime = Date.now();
|
|
16761
16779
|
this.handleReturnFocus = () => {
|
|
16780
|
+
const diffTime = Date.now() - this.lastReturnFocusTime;
|
|
16781
|
+
if (diffTime < 1e3) return;
|
|
16762
16782
|
const lastAlert = this.alerts[this.alerts.length - 1];
|
|
16763
16783
|
if (lastAlert) {
|
|
16764
16784
|
this.onFocusCallback({
|
|
@@ -16769,6 +16789,7 @@ var AlertRecorder = class {
|
|
|
16769
16789
|
});
|
|
16770
16790
|
lastAlert.end = this.getRelativeTime();
|
|
16771
16791
|
}
|
|
16792
|
+
this.lastReturnFocusTime = Date.now();
|
|
16772
16793
|
};
|
|
16773
16794
|
// 2. SPLIT SCREEN DETECTION
|
|
16774
16795
|
this.handleResize = () => {
|
|
@@ -16853,6 +16874,8 @@ var AlertRecorder = class {
|
|
|
16853
16874
|
attachListeners() {
|
|
16854
16875
|
if (this.optionsProctoring.captureScreen) {
|
|
16855
16876
|
window.addEventListener("visibilitychange", this.handleVisibilityChange);
|
|
16877
|
+
window.addEventListener("blur", this.handleLostFocus);
|
|
16878
|
+
window.addEventListener("focus", this.handleReturnFocus);
|
|
16856
16879
|
window.addEventListener("resize", this.handleResize);
|
|
16857
16880
|
window.document.addEventListener("copy", this.handleCopy);
|
|
16858
16881
|
window.document.addEventListener("cut", this.handleCut);
|
|
@@ -16861,6 +16884,8 @@ var AlertRecorder = class {
|
|
|
16861
16884
|
}
|
|
16862
16885
|
detachListeners() {
|
|
16863
16886
|
window.removeEventListener("visibilitychange", this.handleVisibilityChange);
|
|
16887
|
+
window.removeEventListener("blur", this.handleLostFocus);
|
|
16888
|
+
window.removeEventListener("focus", this.handleReturnFocus);
|
|
16864
16889
|
window.removeEventListener("resize", this.handleResize);
|
|
16865
16890
|
window.document.removeEventListener("copy", this.handleCopy);
|
|
16866
16891
|
window.document.removeEventListener("cut", this.handleCut);
|
|
@@ -19531,7 +19556,12 @@ var ScreenRecorder = class {
|
|
|
19531
19556
|
});
|
|
19532
19557
|
let finalBlob = rawBlob;
|
|
19533
19558
|
if (typeof fixWebmDuration2 === "function") {
|
|
19534
|
-
|
|
19559
|
+
try {
|
|
19560
|
+
finalBlob = await fixWebmDuration2(rawBlob, this.duration);
|
|
19561
|
+
} catch (e3) {
|
|
19562
|
+
console.warn("Erro ao corrigir a dura\xE7\xE3o do v\xEDdeo", e3);
|
|
19563
|
+
finalBlob = rawBlob;
|
|
19564
|
+
}
|
|
19535
19565
|
} else {
|
|
19536
19566
|
console.warn("fixWebmDuration n\xE3o dispon\xEDvel");
|
|
19537
19567
|
}
|
package/index.js
CHANGED
|
@@ -30868,7 +30868,7 @@ var proctoringId;
|
|
|
30868
30868
|
function setRecorderProctoringId(id) {
|
|
30869
30869
|
proctoringId = id;
|
|
30870
30870
|
}
|
|
30871
|
-
function recorder(stream4, buffer, onBufferSizeError = false, onBufferSizeErrorCallback, audio = false) {
|
|
30871
|
+
function recorder(stream4, buffer, onBufferSizeError = false, onBufferSizeErrorCallback, audio = false, recorderOpts) {
|
|
30872
30872
|
let resolvePromise;
|
|
30873
30873
|
let onBufferSizeInterval;
|
|
30874
30874
|
let lastEvent;
|
|
@@ -30876,6 +30876,7 @@ function recorder(stream4, buffer, onBufferSizeError = false, onBufferSizeErrorC
|
|
|
30876
30876
|
bufferSize = 0;
|
|
30877
30877
|
let startTime;
|
|
30878
30878
|
let duration = 0;
|
|
30879
|
+
let chunkIndex = 0;
|
|
30879
30880
|
let recorderOptions = {
|
|
30880
30881
|
// eslint-disable-next-line no-useless-escape
|
|
30881
30882
|
mimeType: "video/webm",
|
|
@@ -30910,6 +30911,10 @@ function recorder(stream4, buffer, onBufferSizeError = false, onBufferSizeErrorC
|
|
|
30910
30911
|
mediaRecorder2.ondataavailable = (e3) => {
|
|
30911
30912
|
bufferSize = bufferSize + e3.data.size;
|
|
30912
30913
|
if (e3.data.size > 0) {
|
|
30914
|
+
if (recorderOpts == null ? void 0 : recorderOpts.onChunkAvailable) {
|
|
30915
|
+
recorderOpts.onChunkAvailable(e3.data, chunkIndex);
|
|
30916
|
+
chunkIndex++;
|
|
30917
|
+
}
|
|
30913
30918
|
buffer.push(e3.data);
|
|
30914
30919
|
}
|
|
30915
30920
|
};
|
|
@@ -30941,7 +30946,13 @@ function recorder(stream4, buffer, onBufferSizeError = false, onBufferSizeErrorC
|
|
|
30941
30946
|
};
|
|
30942
30947
|
try {
|
|
30943
30948
|
console.log("State antes do start:", recorder2.state);
|
|
30944
|
-
|
|
30949
|
+
chunkIndex = 0;
|
|
30950
|
+
if ((recorderOpts == null ? void 0 : recorderOpts.timeslice) && (recorderOpts == null ? void 0 : recorderOpts.timeslice) > 0) {
|
|
30951
|
+
recorder2.start(recorderOpts.timeslice);
|
|
30952
|
+
} else {
|
|
30953
|
+
recorder2.start(1e4);
|
|
30954
|
+
}
|
|
30955
|
+
bufferSize = 0;
|
|
30945
30956
|
startTime = new Date(Date.now());
|
|
30946
30957
|
} catch (e3) {
|
|
30947
30958
|
console.error("Recorder erro ao chamar start event:", e3);
|
|
@@ -31355,9 +31366,6 @@ var ObjectDetection = class extends BaseDetection {
|
|
|
31355
31366
|
}
|
|
31356
31367
|
};
|
|
31357
31368
|
|
|
31358
|
-
// src/new-flow/recorders/CameraRecorder.ts
|
|
31359
|
-
var import_jszip_min = __toESM(require_jszip_min());
|
|
31360
|
-
|
|
31361
31369
|
// src/new-flow/chunk/ChunkStorageService.ts
|
|
31362
31370
|
var _ChunkStorageService = class _ChunkStorageService {
|
|
31363
31371
|
constructor() {
|
|
@@ -31969,6 +31977,7 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
31969
31977
|
};
|
|
31970
31978
|
|
|
31971
31979
|
// src/new-flow/recorders/CameraRecorder.ts
|
|
31980
|
+
var import_jszip_min = __toESM(require_jszip_min());
|
|
31972
31981
|
var pkg = require_fix_webm_duration();
|
|
31973
31982
|
var fixWebmDuration = pkg.default || pkg;
|
|
31974
31983
|
var _CameraRecorder = class _CameraRecorder {
|
|
@@ -32041,11 +32050,11 @@ var _CameraRecorder = class _CameraRecorder {
|
|
|
32041
32050
|
paramsConfig && (this.paramsConfig = paramsConfig);
|
|
32042
32051
|
}
|
|
32043
32052
|
/**
|
|
32044
|
-
|
|
32045
|
-
|
|
32046
|
-
|
|
32047
|
-
|
|
32048
|
-
|
|
32053
|
+
* Determina se o fluxo de chunks e lifecycle deve estar ativo.
|
|
32054
|
+
* Retorna true se:
|
|
32055
|
+
* 1. O proctoringId já foi definido (ou seja, estamos em uma sessão real, NÃO no checkDevices)
|
|
32056
|
+
* 2. E (`useChunkRecording` foi explicitamente setado como true OU o dispositivo é mobile)
|
|
32057
|
+
*/
|
|
32049
32058
|
get isChunkEnabled() {
|
|
32050
32059
|
return !!this.proctoringId && this.options.proctoringType === "REALTIME" && !isSafeBrowser();
|
|
32051
32060
|
}
|
|
@@ -32308,9 +32317,15 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32308
32317
|
await new Promise((r3) => setTimeout(r3, 300));
|
|
32309
32318
|
}
|
|
32310
32319
|
async startRecording() {
|
|
32311
|
-
var _a2, _b, _c2, _d, _e3, _f, _g;
|
|
32320
|
+
var _a2, _b, _c2, _d, _e3, _f, _g, _h;
|
|
32312
32321
|
await this.startStream();
|
|
32313
32322
|
await this.attachAndWarmup(this.cameraStream);
|
|
32323
|
+
const recorderOpts = this.isChunkEnabled ? {
|
|
32324
|
+
timeslice: _CameraRecorder.CHUNK_TIMESLICE_MS,
|
|
32325
|
+
onChunkAvailable: (blob, idx) => {
|
|
32326
|
+
this.handleNewChunk(blob, idx);
|
|
32327
|
+
}
|
|
32328
|
+
} : {};
|
|
32314
32329
|
const {
|
|
32315
32330
|
startRecording,
|
|
32316
32331
|
stopRecording,
|
|
@@ -32326,7 +32341,8 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32326
32341
|
this.blobs,
|
|
32327
32342
|
this.options.onBufferSizeError,
|
|
32328
32343
|
(e3) => this.bufferError(e3),
|
|
32329
|
-
false
|
|
32344
|
+
false,
|
|
32345
|
+
recorderOpts
|
|
32330
32346
|
);
|
|
32331
32347
|
this.recordingStart = startRecording;
|
|
32332
32348
|
this.recordingStop = stopRecording;
|
|
@@ -32336,13 +32352,18 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32336
32352
|
this.getBufferSize = getBufferSize;
|
|
32337
32353
|
this.getStartTime = getStartTime;
|
|
32338
32354
|
this.getDuration = getDuration;
|
|
32355
|
+
this.chunkIndex = 0;
|
|
32356
|
+
if (this.isChunkEnabled) {
|
|
32357
|
+
(_a2 = this.backgroundUpload) == null ? void 0 : _a2.start();
|
|
32358
|
+
this.setupLifecycleListeners();
|
|
32359
|
+
}
|
|
32339
32360
|
try {
|
|
32340
32361
|
await new Promise((r3) => setTimeout(r3, 500));
|
|
32341
32362
|
await this.recordingStart();
|
|
32342
32363
|
} catch (error) {
|
|
32343
32364
|
console.log("Camera Recorder error", error);
|
|
32344
32365
|
this.stopRecording();
|
|
32345
|
-
const maxRetries = ((
|
|
32366
|
+
const maxRetries = ((_b = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _b.maxRetries) || 3;
|
|
32346
32367
|
if (this.currentRetries < maxRetries) {
|
|
32347
32368
|
console.log("Camera Recorder retry", this.currentRetries);
|
|
32348
32369
|
this.currentRetries++;
|
|
@@ -32352,13 +32373,13 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32352
32373
|
}
|
|
32353
32374
|
}
|
|
32354
32375
|
this.stopped = false;
|
|
32355
|
-
if (((
|
|
32376
|
+
if (((_c2 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _c2.detectPerson) || ((_d = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _d.detectCellPhone) || ((_e3 = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _e3.detectFace)) {
|
|
32356
32377
|
await this.initializeDetectors();
|
|
32357
32378
|
}
|
|
32358
|
-
if ((
|
|
32379
|
+
if ((_f = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _f.detectFace) {
|
|
32359
32380
|
await this.faceDetection.enableCam(this.cameraStream);
|
|
32360
32381
|
}
|
|
32361
|
-
if (((
|
|
32382
|
+
if (((_g = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _g.detectPerson) || ((_h = this.paramsConfig.videoBehaviourParameters) == null ? void 0 : _h.detectCellPhone)) {
|
|
32362
32383
|
await this.objectDetection.enableCam(this.cameraStream);
|
|
32363
32384
|
}
|
|
32364
32385
|
this.filesToUpload = [];
|
|
@@ -32597,7 +32618,7 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32597
32618
|
if (this.blobs != null)
|
|
32598
32619
|
trackers.registerSaveOnSession(
|
|
32599
32620
|
this.proctoringId,
|
|
32600
|
-
`Blobs Length: ${this.blobs.length} Buffer Size: ${this.getBufferSize()} `
|
|
32621
|
+
`Blobs Length: ${this.blobs.length} Buffer Size: ${this.getBufferSize()} ChunkEnabled: ${this.isChunkEnabled}`
|
|
32601
32622
|
);
|
|
32602
32623
|
const settings = this.cameraStream.getVideoTracks()[0].getSettings();
|
|
32603
32624
|
const settingsAudio = this.cameraStream.getAudioTracks()[0].getSettings();
|
|
@@ -32617,7 +32638,12 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32617
32638
|
});
|
|
32618
32639
|
let finalBlob = rawBlob;
|
|
32619
32640
|
if (typeof fixWebmDuration === "function") {
|
|
32620
|
-
|
|
32641
|
+
try {
|
|
32642
|
+
finalBlob = await fixWebmDuration(rawBlob, this.duration);
|
|
32643
|
+
} catch (e3) {
|
|
32644
|
+
console.warn("Erro ao corrigir a dura\xE7\xE3o do v\xEDdeo", e3);
|
|
32645
|
+
finalBlob = rawBlob;
|
|
32646
|
+
}
|
|
32621
32647
|
} else {
|
|
32622
32648
|
console.warn("fixWebmDuration n\xE3o dispon\xEDvel");
|
|
32623
32649
|
}
|
|
@@ -34763,19 +34789,9 @@ var ProctoringUploader = class {
|
|
|
34763
34789
|
}
|
|
34764
34790
|
toFile(rec) {
|
|
34765
34791
|
const suffix = rec.origin === "Screen" /* Screen */ ? "screen" : rec.origin === "Camera" /* Camera */ ? "camera" : "audio";
|
|
34766
|
-
const name = `EP_${this.
|
|
34792
|
+
const name = `EP_${this.session.id}_${suffix}_0.webm`;
|
|
34767
34793
|
return new File([rec.arrayBuffer], name, { type: "video/webm" });
|
|
34768
34794
|
}
|
|
34769
|
-
getFileType(origin2) {
|
|
34770
|
-
switch (origin2) {
|
|
34771
|
-
case "Camera" /* Camera */:
|
|
34772
|
-
return "Camera";
|
|
34773
|
-
case "Screen" /* Screen */:
|
|
34774
|
-
return "Screen";
|
|
34775
|
-
case "Mic" /* Mic */:
|
|
34776
|
-
return "Audio";
|
|
34777
|
-
}
|
|
34778
|
-
}
|
|
34779
34795
|
async uploadFile(rec, token, onProgress) {
|
|
34780
34796
|
const file = this.toFile(rec);
|
|
34781
34797
|
for await (const uploadService of this.uploadServices) {
|
|
@@ -34787,24 +34803,23 @@ var ProctoringUploader = class {
|
|
|
34787
34803
|
}
|
|
34788
34804
|
},
|
|
34789
34805
|
token
|
|
34790
|
-
).catch(
|
|
34791
|
-
|
|
34792
|
-
this.proctoringId,
|
|
34793
|
-
`Upload File
|
|
34806
|
+
).catch(
|
|
34807
|
+
async (e3) => {
|
|
34808
|
+
console.log("Upload File Error", e3), trackers.registerError(this.proctoringId, `Upload File
|
|
34794
34809
|
Name: ${file.name}
|
|
34795
34810
|
Error: ${e3.message}
|
|
34796
|
-
Size: ${e3.error}`
|
|
34797
|
-
|
|
34798
|
-
|
|
34799
|
-
|
|
34800
|
-
|
|
34801
|
-
|
|
34802
|
-
|
|
34803
|
-
}
|
|
34804
|
-
|
|
34805
|
-
|
|
34806
|
-
|
|
34807
|
-
|
|
34811
|
+
Size: ${e3.error}`);
|
|
34812
|
+
await uploadService.upload(
|
|
34813
|
+
{
|
|
34814
|
+
file,
|
|
34815
|
+
onProgress: (progress) => {
|
|
34816
|
+
if (onProgress) onProgress(progress);
|
|
34817
|
+
}
|
|
34818
|
+
},
|
|
34819
|
+
token
|
|
34820
|
+
);
|
|
34821
|
+
}
|
|
34822
|
+
);
|
|
34808
34823
|
if (result) {
|
|
34809
34824
|
let fileType = "";
|
|
34810
34825
|
if (rec.origin === "Camera" /* Camera */) {
|
|
@@ -34843,8 +34858,9 @@ var AlertRecorder = class {
|
|
|
34843
34858
|
this.handleLostFocus();
|
|
34844
34859
|
}
|
|
34845
34860
|
};
|
|
34861
|
+
this.lastLostFocusTime = Date.now();
|
|
34846
34862
|
this.handleLostFocus = () => {
|
|
34847
|
-
if (this.getRelativeTime() > 1e4) {
|
|
34863
|
+
if (this.getRelativeTime() > 1e4 && Date.now() - this.lastLostFocusTime > 1e3) {
|
|
34848
34864
|
const alertPayload = {
|
|
34849
34865
|
begin: this.getRelativeTime(),
|
|
34850
34866
|
end: 0,
|
|
@@ -34853,9 +34869,13 @@ var AlertRecorder = class {
|
|
|
34853
34869
|
};
|
|
34854
34870
|
this.onLostFocusCallback(alertPayload);
|
|
34855
34871
|
this.alerts.push(alertPayload);
|
|
34872
|
+
this.lastLostFocusTime = Date.now();
|
|
34856
34873
|
}
|
|
34857
34874
|
};
|
|
34875
|
+
this.lastReturnFocusTime = Date.now();
|
|
34858
34876
|
this.handleReturnFocus = () => {
|
|
34877
|
+
const diffTime = Date.now() - this.lastReturnFocusTime;
|
|
34878
|
+
if (diffTime < 1e3) return;
|
|
34859
34879
|
const lastAlert = this.alerts[this.alerts.length - 1];
|
|
34860
34880
|
if (lastAlert) {
|
|
34861
34881
|
this.onFocusCallback({
|
|
@@ -34866,6 +34886,7 @@ var AlertRecorder = class {
|
|
|
34866
34886
|
});
|
|
34867
34887
|
lastAlert.end = this.getRelativeTime();
|
|
34868
34888
|
}
|
|
34889
|
+
this.lastReturnFocusTime = Date.now();
|
|
34869
34890
|
};
|
|
34870
34891
|
// 2. SPLIT SCREEN DETECTION
|
|
34871
34892
|
this.handleResize = () => {
|
|
@@ -34950,6 +34971,8 @@ var AlertRecorder = class {
|
|
|
34950
34971
|
attachListeners() {
|
|
34951
34972
|
if (this.optionsProctoring.captureScreen) {
|
|
34952
34973
|
window.addEventListener("visibilitychange", this.handleVisibilityChange);
|
|
34974
|
+
window.addEventListener("blur", this.handleLostFocus);
|
|
34975
|
+
window.addEventListener("focus", this.handleReturnFocus);
|
|
34953
34976
|
window.addEventListener("resize", this.handleResize);
|
|
34954
34977
|
window.document.addEventListener("copy", this.handleCopy);
|
|
34955
34978
|
window.document.addEventListener("cut", this.handleCut);
|
|
@@ -34958,6 +34981,8 @@ var AlertRecorder = class {
|
|
|
34958
34981
|
}
|
|
34959
34982
|
detachListeners() {
|
|
34960
34983
|
window.removeEventListener("visibilitychange", this.handleVisibilityChange);
|
|
34984
|
+
window.removeEventListener("blur", this.handleLostFocus);
|
|
34985
|
+
window.removeEventListener("focus", this.handleReturnFocus);
|
|
34961
34986
|
window.removeEventListener("resize", this.handleResize);
|
|
34962
34987
|
window.document.removeEventListener("copy", this.handleCopy);
|
|
34963
34988
|
window.document.removeEventListener("cut", this.handleCut);
|
|
@@ -37628,7 +37653,12 @@ var ScreenRecorder = class {
|
|
|
37628
37653
|
});
|
|
37629
37654
|
let finalBlob = rawBlob;
|
|
37630
37655
|
if (typeof fixWebmDuration2 === "function") {
|
|
37631
|
-
|
|
37656
|
+
try {
|
|
37657
|
+
finalBlob = await fixWebmDuration2(rawBlob, this.duration);
|
|
37658
|
+
} catch (e3) {
|
|
37659
|
+
console.warn("Erro ao corrigir a dura\xE7\xE3o do v\xEDdeo", e3);
|
|
37660
|
+
finalBlob = rawBlob;
|
|
37661
|
+
}
|
|
37632
37662
|
} else {
|
|
37633
37663
|
console.warn("fixWebmDuration n\xE3o dispon\xEDvel");
|
|
37634
37664
|
}
|
|
@@ -25,7 +25,9 @@ export declare class AlertRecorder implements IRecorder {
|
|
|
25
25
|
private attachListeners;
|
|
26
26
|
private detachListeners;
|
|
27
27
|
private handleVisibilityChange;
|
|
28
|
+
lastLostFocusTime: number;
|
|
28
29
|
private handleLostFocus;
|
|
30
|
+
lastReturnFocusTime: number;
|
|
29
31
|
private handleReturnFocus;
|
|
30
32
|
private handleResize;
|
|
31
33
|
private handleUserActivity;
|
package/package.json
CHANGED
package/plugins/recorder.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export declare function setRecorderProctoringId(id: string): void;
|
|
2
|
-
export
|
|
2
|
+
export interface RecorderOptions {
|
|
3
|
+
timeslice?: number;
|
|
4
|
+
onChunkAvailable?: (blob: Blob, chunkIndex: number) => void;
|
|
5
|
+
}
|
|
6
|
+
export default function recorder(stream: MediaStream, buffer: Blob[], onBufferSizeError?: boolean, onBufferSizeErrorCallback?: (e?: any) => void, audio?: boolean, recorderOpts?: RecorderOptions): {
|
|
3
7
|
startRecording: () => Promise<void>;
|
|
4
8
|
stopRecording: () => Promise<void>;
|
|
5
9
|
pauseRecording: () => Promise<void>;
|