easyproctor-hml 2.7.5 → 2.7.6
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/esm/index.js +31 -101
- package/index.js +31 -101
- package/new-flow/chunk/ChunkStorageService.d.ts +1 -1
- package/package.json +1 -1
- package/unpkg/easyproctor.min.js +57 -56
- package/unpkg/easyproctor.min.js.map +0 -7
package/esm/index.js
CHANGED
|
@@ -13476,13 +13476,8 @@ var _ChunkStorageService = class _ChunkStorageService {
|
|
|
13476
13476
|
async clearAllChunks(proctoringId2) {
|
|
13477
13477
|
const db = await this.connect();
|
|
13478
13478
|
return new Promise((resolve, reject) => {
|
|
13479
|
-
const transaction = db.transaction(
|
|
13480
|
-
|
|
13481
|
-
"readwrite"
|
|
13482
|
-
);
|
|
13483
|
-
const store = transaction.objectStore(
|
|
13484
|
-
_ChunkStorageService.STORE_NAME
|
|
13485
|
-
);
|
|
13479
|
+
const transaction = db.transaction(_ChunkStorageService.STORE_NAME, "readwrite");
|
|
13480
|
+
const store = transaction.objectStore(_ChunkStorageService.STORE_NAME);
|
|
13486
13481
|
const index = store.index("proctoringId");
|
|
13487
13482
|
const range = IDBKeyRange.only(proctoringId2);
|
|
13488
13483
|
const request = index.openCursor(range);
|
|
@@ -13491,34 +13486,13 @@ var _ChunkStorageService = class _ChunkStorageService {
|
|
|
13491
13486
|
if (cursor) {
|
|
13492
13487
|
cursor.delete();
|
|
13493
13488
|
cursor.continue();
|
|
13489
|
+
} else {
|
|
13490
|
+
resolve();
|
|
13494
13491
|
}
|
|
13495
13492
|
};
|
|
13496
13493
|
request.onerror = () => {
|
|
13497
13494
|
var _a2;
|
|
13498
|
-
reject(
|
|
13499
|
-
new Error(
|
|
13500
|
-
`Erro ao limpar chunks: ${(_a2 = request.error) == null ? void 0 : _a2.message}`
|
|
13501
|
-
)
|
|
13502
|
-
);
|
|
13503
|
-
};
|
|
13504
|
-
transaction.oncomplete = () => {
|
|
13505
|
-
resolve();
|
|
13506
|
-
};
|
|
13507
|
-
transaction.onerror = () => {
|
|
13508
|
-
var _a2;
|
|
13509
|
-
reject(
|
|
13510
|
-
new Error(
|
|
13511
|
-
`Transaction error: ${(_a2 = transaction.error) == null ? void 0 : _a2.message}`
|
|
13512
|
-
)
|
|
13513
|
-
);
|
|
13514
|
-
};
|
|
13515
|
-
transaction.onabort = () => {
|
|
13516
|
-
var _a2;
|
|
13517
|
-
reject(
|
|
13518
|
-
new Error(
|
|
13519
|
-
`Transaction aborted: ${(_a2 = transaction.error) == null ? void 0 : _a2.message}`
|
|
13520
|
-
)
|
|
13521
|
-
);
|
|
13495
|
+
return reject(new Error(`Erro ao limpar todos os chunks: ${(_a2 = request.error) == null ? void 0 : _a2.message}`));
|
|
13522
13496
|
};
|
|
13523
13497
|
});
|
|
13524
13498
|
}
|
|
@@ -13577,8 +13551,8 @@ var _ChunkStorageService = class _ChunkStorageService {
|
|
|
13577
13551
|
}
|
|
13578
13552
|
};
|
|
13579
13553
|
_ChunkStorageService.DB_NAME = "EasyProctorChunksDb";
|
|
13580
|
-
/** v2
|
|
13581
|
-
_ChunkStorageService.DB_VERSION =
|
|
13554
|
+
/** Incrementado para v2 para recriar índices com tipos numéricos em vez de boolean */
|
|
13555
|
+
_ChunkStorageService.DB_VERSION = 2;
|
|
13582
13556
|
_ChunkStorageService.STORE_NAME = "chunks";
|
|
13583
13557
|
var ChunkStorageService = _ChunkStorageService;
|
|
13584
13558
|
|
|
@@ -13760,41 +13734,32 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
13760
13734
|
console.log(`[BackgroundUpload] ${pendingChunks.length} chunks pendentes encontrados. Modo final: ${isFinal}`);
|
|
13761
13735
|
let virtualStart = this.totalBytesPurged;
|
|
13762
13736
|
const chunksWithMeta = allChunks.map((c3) => {
|
|
13763
|
-
const byteLen = c3.arrayBuffer.byteLength;
|
|
13764
13737
|
const start = virtualStart;
|
|
13765
|
-
const end = start +
|
|
13766
|
-
virtualStart +=
|
|
13738
|
+
const end = start + c3.blob.size - 1;
|
|
13739
|
+
virtualStart += c3.blob.size;
|
|
13767
13740
|
return { chunk: c3, start, end };
|
|
13768
13741
|
});
|
|
13769
|
-
|
|
13742
|
+
let combinedBlobParts = [];
|
|
13770
13743
|
let lastProcessedChunkId = null;
|
|
13771
13744
|
let finalChunkIndex = 0;
|
|
13772
13745
|
let mimeType = pendingChunks[0].mimeType;
|
|
13773
13746
|
for (const meta of chunksWithMeta) {
|
|
13774
13747
|
if (this.currentOffset > meta.end) continue;
|
|
13775
13748
|
const sliceStart = Math.max(0, this.currentOffset - meta.start);
|
|
13776
|
-
const
|
|
13777
|
-
|
|
13749
|
+
const chunkSlice = meta.chunk.blob.slice(sliceStart);
|
|
13750
|
+
combinedBlobParts.push(chunkSlice);
|
|
13778
13751
|
lastProcessedChunkId = meta.chunk.id;
|
|
13779
13752
|
finalChunkIndex = meta.chunk.chunkIndex;
|
|
13780
13753
|
}
|
|
13781
|
-
if (
|
|
13754
|
+
if (combinedBlobParts.length === 0 && !isFinal) {
|
|
13782
13755
|
this.isProcessing = false;
|
|
13783
13756
|
return;
|
|
13784
13757
|
}
|
|
13785
|
-
|
|
13786
|
-
|
|
13787
|
-
{
|
|
13788
|
-
let off = 0;
|
|
13789
|
-
for (const p3 of sliceParts) {
|
|
13790
|
-
combined.set(p3, off);
|
|
13791
|
-
off += p3.length;
|
|
13792
|
-
}
|
|
13793
|
-
}
|
|
13794
|
-
let sendableSize = combined.byteLength;
|
|
13758
|
+
let fullBlob = new Blob(combinedBlobParts, { type: mimeType });
|
|
13759
|
+
let sendableSize = fullBlob.size;
|
|
13795
13760
|
let totalSizeForHeader = void 0;
|
|
13796
13761
|
if (!isFinal) {
|
|
13797
|
-
sendableSize = Math.floor(
|
|
13762
|
+
sendableSize = Math.floor(fullBlob.size / this.GCS_CHUNK_SIZE) * this.GCS_CHUNK_SIZE;
|
|
13798
13763
|
if (sendableSize === 0) {
|
|
13799
13764
|
console.log("[BackgroundUpload] Dados insuficientes para atingir 256KB. Aguardando novo chunk...");
|
|
13800
13765
|
this.isProcessing = false;
|
|
@@ -13803,14 +13768,9 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
13803
13768
|
} else {
|
|
13804
13769
|
totalSizeForHeader = virtualStart;
|
|
13805
13770
|
}
|
|
13806
|
-
const
|
|
13771
|
+
const blobToSend = fullBlob.slice(0, sendableSize);
|
|
13807
13772
|
try {
|
|
13808
|
-
await this.uploadData(
|
|
13809
|
-
payload.byteLength > 0 ? payload : null,
|
|
13810
|
-
mimeType,
|
|
13811
|
-
finalChunkIndex,
|
|
13812
|
-
totalSizeForHeader
|
|
13813
|
-
);
|
|
13773
|
+
await this.uploadData(blobToSend, mimeType, finalChunkIndex, totalSizeForHeader);
|
|
13814
13774
|
for (const meta of chunksWithMeta) {
|
|
13815
13775
|
if (meta.chunk.uploaded === 0 && meta.end < this.currentOffset) {
|
|
13816
13776
|
await this.chunkStorage.markAsUploaded(meta.chunk.id);
|
|
@@ -13821,10 +13781,7 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
13821
13781
|
}
|
|
13822
13782
|
if (this.config.cleanAfterUpload) {
|
|
13823
13783
|
const chunksToClear = chunksWithMeta.filter((meta) => meta.chunk.uploaded === 1 || meta.chunk.uploaded === 0 && meta.end < this.currentOffset);
|
|
13824
|
-
const sizePurged = chunksToClear.reduce(
|
|
13825
|
-
(acc, meta) => acc + meta.chunk.arrayBuffer.byteLength,
|
|
13826
|
-
0
|
|
13827
|
-
);
|
|
13784
|
+
const sizePurged = chunksToClear.reduce((acc, meta) => acc + meta.chunk.blob.size, 0);
|
|
13828
13785
|
await this.chunkStorage.clearUploadedChunks(this.proctoringId);
|
|
13829
13786
|
if (sizePurged > 0) {
|
|
13830
13787
|
this.totalBytesPurged += sizePurged;
|
|
@@ -13848,8 +13805,7 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
13848
13805
|
/**
|
|
13849
13806
|
* Faz o upload bruto de dados para a sessão GCS.
|
|
13850
13807
|
*/
|
|
13851
|
-
async uploadData(
|
|
13852
|
-
var _a2;
|
|
13808
|
+
async uploadData(blob, mimeType, chunkIndex, totalSize) {
|
|
13853
13809
|
const fileName = `EP_${this.proctoringId}_camera_0.webm`;
|
|
13854
13810
|
if (!this.sessionUrl) {
|
|
13855
13811
|
const initiateUrl = await this.backend.initiateUpload(this.token, `${this.proctoringId}/${fileName}`, mimeType);
|
|
@@ -13880,28 +13836,16 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
13880
13836
|
} else {
|
|
13881
13837
|
console.log(`[BackgroundUpload] Usando sess\xE3o GCS existente: ${this.sessionUrl}`);
|
|
13882
13838
|
}
|
|
13883
|
-
const size = (_a2 = body == null ? void 0 : body.byteLength) != null ? _a2 : 0;
|
|
13884
13839
|
const start = this.currentOffset;
|
|
13885
|
-
const end = start + size - 1;
|
|
13840
|
+
const end = start + blob.size - 1;
|
|
13886
13841
|
const totalHeader = totalSize !== void 0 ? totalSize.toString() : "*";
|
|
13887
|
-
const contentRangeHeader = size === 0 && totalSize !== void 0 ? `bytes */${totalHeader}` : `bytes ${start}-${end}/${totalHeader}`;
|
|
13888
|
-
console.log(
|
|
13889
|
-
`[BackgroundUpload] Enviando ${size > 0 ? "dados" : "finaliza\xE7\xE3o"}: ${contentRangeHeader} (Size: ${size})`
|
|
13890
|
-
);
|
|
13891
|
-
let uploadBody = null;
|
|
13892
|
-
if (size > 0 && body) {
|
|
13893
|
-
const raw = body.buffer;
|
|
13894
|
-
if (raw instanceof ArrayBuffer) {
|
|
13895
|
-
uploadBody = body.byteOffset === 0 && body.byteLength === raw.byteLength ? raw : raw.slice(body.byteOffset, body.byteOffset + body.byteLength);
|
|
13896
|
-
} else {
|
|
13897
|
-
uploadBody = new ArrayBuffer(body.byteLength);
|
|
13898
|
-
new Uint8Array(uploadBody).set(body);
|
|
13899
|
-
}
|
|
13900
|
-
}
|
|
13842
|
+
const contentRangeHeader = blob.size === 0 && totalSize !== void 0 ? `bytes */${totalHeader}` : `bytes ${start}-${end}/${totalHeader}`;
|
|
13843
|
+
console.log(`[BackgroundUpload] Enviando ${blob.size > 0 ? "dados" : "finaliza\xE7\xE3o"}: ${contentRangeHeader} (Size: ${blob.size})`);
|
|
13901
13844
|
const response = await fetch(this.sessionUrl, {
|
|
13902
13845
|
method: "PUT",
|
|
13903
13846
|
headers: { "Content-Range": contentRangeHeader },
|
|
13904
|
-
body:
|
|
13847
|
+
body: blob.size > 0 ? blob : null
|
|
13848
|
+
// Usa null para garantir corpo vazio se necessário
|
|
13905
13849
|
});
|
|
13906
13850
|
console.log(`[BackgroundUpload] Resposta GCS (uploadData): ${response.status}`);
|
|
13907
13851
|
if (response.status !== 200 && response.status !== 201 && response.status !== 308) {
|
|
@@ -13914,13 +13858,13 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
13914
13858
|
const lastByte = parseInt(rangeHeader.split("-")[1], 10);
|
|
13915
13859
|
this.currentOffset = lastByte + 1;
|
|
13916
13860
|
} else {
|
|
13917
|
-
this.currentOffset += size;
|
|
13861
|
+
this.currentOffset += blob.size;
|
|
13918
13862
|
}
|
|
13919
13863
|
this.saveSessionState();
|
|
13920
13864
|
trackers.registerUploadFile(
|
|
13921
13865
|
this.proctoringId,
|
|
13922
13866
|
`GCS Stream Upload
|
|
13923
|
-
Size: ${size}
|
|
13867
|
+
Size: ${blob.size}
|
|
13924
13868
|
Range: ${start}-${end}
|
|
13925
13869
|
Last Index: ${chunkIndex}`,
|
|
13926
13870
|
"CameraChunk"
|
|
@@ -14439,23 +14383,19 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14439
14383
|
}
|
|
14440
14384
|
if (this.isChunkEnabled) {
|
|
14441
14385
|
if (this.backgroundUpload) {
|
|
14442
|
-
trackers.registerError(this.proctoringId, `Flush e parada do background upload`);
|
|
14443
14386
|
try {
|
|
14444
14387
|
if (this.pendingChunkSaves.length > 0) {
|
|
14445
14388
|
console.log(`[CameraRecorder] Aguardando ${this.pendingChunkSaves.length} salvamentos de chunks pendentes...`);
|
|
14446
14389
|
await Promise.all(this.pendingChunkSaves);
|
|
14447
14390
|
}
|
|
14448
14391
|
await this.backgroundUpload.flush();
|
|
14449
|
-
this.backgroundUpload.stop();
|
|
14450
14392
|
} catch (e3) {
|
|
14451
14393
|
console.warn("[CameraRecorder] Erro ao fazer flush dos chunks:", e3);
|
|
14452
|
-
trackers.registerError(this.proctoringId, `Flush Chunks
|
|
14453
|
-
Error: ${e3}`);
|
|
14454
14394
|
}
|
|
14395
|
+
this.backgroundUpload.stop();
|
|
14455
14396
|
}
|
|
14456
14397
|
this.removeLifecycleListeners();
|
|
14457
14398
|
this.persistSessionState("FINISHED");
|
|
14458
|
-
trackers.registerError(this.proctoringId, `Finalizando flush e parada do background upload`);
|
|
14459
14399
|
}
|
|
14460
14400
|
}
|
|
14461
14401
|
/**
|
|
@@ -14467,11 +14407,10 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14467
14407
|
const savePromise = (async () => {
|
|
14468
14408
|
var _a2;
|
|
14469
14409
|
try {
|
|
14470
|
-
const arrayBuffer = await blob.arrayBuffer();
|
|
14471
14410
|
await this.chunkStorage.saveChunk({
|
|
14472
14411
|
proctoringId: this.proctoringId,
|
|
14473
14412
|
chunkIndex: this.chunkIndex,
|
|
14474
|
-
|
|
14413
|
+
blob,
|
|
14475
14414
|
timestamp: Date.now(),
|
|
14476
14415
|
uploaded: 0,
|
|
14477
14416
|
mimeType: ((_a2 = this.recorderOptions) == null ? void 0 : _a2.mimeType) || "video/webm"
|
|
@@ -14479,8 +14418,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14479
14418
|
this.chunkIndex++;
|
|
14480
14419
|
console.log(`[CameraRecorder] Chunk ${this.chunkIndex - 1} salvo no IndexedDB.`);
|
|
14481
14420
|
} catch (error) {
|
|
14482
|
-
trackers.registerError(this.proctoringId, `Save Chunk
|
|
14483
|
-
Error: ${error}`);
|
|
14484
14421
|
console.error("[CameraRecorder] Erro ao salvar chunk no IndexedDB:", error);
|
|
14485
14422
|
}
|
|
14486
14423
|
})();
|
|
@@ -14629,7 +14566,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14629
14566
|
const settingsAudio = this.cameraStream.getAudioTracks()[0].getSettings();
|
|
14630
14567
|
if (this.options.proctoringType == "VIDEO" || this.options.proctoringType == "REALTIME" || this.options.proctoringType == "IMAGE" && ((_a2 = this.paramsConfig.imageBehaviourParameters) == null ? void 0 : _a2.saveVideo)) {
|
|
14631
14568
|
let videoFile;
|
|
14632
|
-
trackers.registerError(this.proctoringId, `saveOnSession iniciando`);
|
|
14633
14569
|
if (this.isChunkEnabled) {
|
|
14634
14570
|
const isStable = await this.checkInternetStability();
|
|
14635
14571
|
if (isStable) {
|
|
@@ -14638,19 +14574,13 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14638
14574
|
const fileName = `EP_${this.proctoringId}_camera_0.webm`;
|
|
14639
14575
|
const objectName = `${this.proctoringId}/${fileName}`;
|
|
14640
14576
|
const isUploaded = await this.backend.checkUpload(this.backendToken, objectName, "video/webm");
|
|
14641
|
-
trackers.registerError(this.proctoringId, `Limpa o armazenamento local pois o v\xEDdeo j\xE1 est\xE1 no servidor`);
|
|
14642
14577
|
if (isUploaded) {
|
|
14643
|
-
|
|
14644
|
-
this.chunkStorage && await this.chunkStorage.clearAllChunks(session.id);
|
|
14645
|
-
} catch (e3) {
|
|
14646
|
-
trackers.registerError(this.proctoringId, `Erro ao limpar o armazenamento local: ${e3}`);
|
|
14647
|
-
}
|
|
14578
|
+
this.chunkStorage && await this.chunkStorage.clearAllChunks(session.id);
|
|
14648
14579
|
return;
|
|
14649
14580
|
}
|
|
14650
14581
|
}
|
|
14651
14582
|
}
|
|
14652
14583
|
}
|
|
14653
|
-
trackers.registerError(this.proctoringId, `saveOnSession gerando v\xEDdeo a partir do buffer em mem\xF3ria (\xEDntegra)`);
|
|
14654
14584
|
const rawBlob = new Blob(this.blobs, {
|
|
14655
14585
|
type: ((_b = this.recorderOptions) == null ? void 0 : _b.mimeType) || "video/webm"
|
|
14656
14586
|
});
|
|
@@ -14671,7 +14601,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
14671
14601
|
origin: "Camera" /* Camera */
|
|
14672
14602
|
});
|
|
14673
14603
|
}
|
|
14674
|
-
trackers.registerError(this.proctoringId, `saveOnSession finalizado`);
|
|
14675
14604
|
}
|
|
14676
14605
|
async getFile(file, name, type) {
|
|
14677
14606
|
return new Promise((resolve, reject) => {
|
|
@@ -23806,6 +23735,7 @@ Error: ${error}`
|
|
|
23806
23735
|
trackers.registerError(this.proctoringId, `finish sendPendingRealtimeAlerts`);
|
|
23807
23736
|
await this.sendPendingRealtimeAlerts();
|
|
23808
23737
|
trackers.registerError(this.proctoringId, `finish this.repository.save`);
|
|
23738
|
+
await this.repository.save(this.proctoringSession);
|
|
23809
23739
|
let uploader;
|
|
23810
23740
|
let uploaderServices;
|
|
23811
23741
|
trackers.registerError(this.proctoringId, `finish uploader`);
|
package/index.js
CHANGED
|
@@ -31573,13 +31573,8 @@ var _ChunkStorageService = class _ChunkStorageService {
|
|
|
31573
31573
|
async clearAllChunks(proctoringId2) {
|
|
31574
31574
|
const db = await this.connect();
|
|
31575
31575
|
return new Promise((resolve, reject) => {
|
|
31576
|
-
const transaction = db.transaction(
|
|
31577
|
-
|
|
31578
|
-
"readwrite"
|
|
31579
|
-
);
|
|
31580
|
-
const store = transaction.objectStore(
|
|
31581
|
-
_ChunkStorageService.STORE_NAME
|
|
31582
|
-
);
|
|
31576
|
+
const transaction = db.transaction(_ChunkStorageService.STORE_NAME, "readwrite");
|
|
31577
|
+
const store = transaction.objectStore(_ChunkStorageService.STORE_NAME);
|
|
31583
31578
|
const index = store.index("proctoringId");
|
|
31584
31579
|
const range = IDBKeyRange.only(proctoringId2);
|
|
31585
31580
|
const request = index.openCursor(range);
|
|
@@ -31588,34 +31583,13 @@ var _ChunkStorageService = class _ChunkStorageService {
|
|
|
31588
31583
|
if (cursor) {
|
|
31589
31584
|
cursor.delete();
|
|
31590
31585
|
cursor.continue();
|
|
31586
|
+
} else {
|
|
31587
|
+
resolve();
|
|
31591
31588
|
}
|
|
31592
31589
|
};
|
|
31593
31590
|
request.onerror = () => {
|
|
31594
31591
|
var _a2;
|
|
31595
|
-
reject(
|
|
31596
|
-
new Error(
|
|
31597
|
-
`Erro ao limpar chunks: ${(_a2 = request.error) == null ? void 0 : _a2.message}`
|
|
31598
|
-
)
|
|
31599
|
-
);
|
|
31600
|
-
};
|
|
31601
|
-
transaction.oncomplete = () => {
|
|
31602
|
-
resolve();
|
|
31603
|
-
};
|
|
31604
|
-
transaction.onerror = () => {
|
|
31605
|
-
var _a2;
|
|
31606
|
-
reject(
|
|
31607
|
-
new Error(
|
|
31608
|
-
`Transaction error: ${(_a2 = transaction.error) == null ? void 0 : _a2.message}`
|
|
31609
|
-
)
|
|
31610
|
-
);
|
|
31611
|
-
};
|
|
31612
|
-
transaction.onabort = () => {
|
|
31613
|
-
var _a2;
|
|
31614
|
-
reject(
|
|
31615
|
-
new Error(
|
|
31616
|
-
`Transaction aborted: ${(_a2 = transaction.error) == null ? void 0 : _a2.message}`
|
|
31617
|
-
)
|
|
31618
|
-
);
|
|
31592
|
+
return reject(new Error(`Erro ao limpar todos os chunks: ${(_a2 = request.error) == null ? void 0 : _a2.message}`));
|
|
31619
31593
|
};
|
|
31620
31594
|
});
|
|
31621
31595
|
}
|
|
@@ -31674,8 +31648,8 @@ var _ChunkStorageService = class _ChunkStorageService {
|
|
|
31674
31648
|
}
|
|
31675
31649
|
};
|
|
31676
31650
|
_ChunkStorageService.DB_NAME = "EasyProctorChunksDb";
|
|
31677
|
-
/** v2
|
|
31678
|
-
_ChunkStorageService.DB_VERSION =
|
|
31651
|
+
/** Incrementado para v2 para recriar índices com tipos numéricos em vez de boolean */
|
|
31652
|
+
_ChunkStorageService.DB_VERSION = 2;
|
|
31679
31653
|
_ChunkStorageService.STORE_NAME = "chunks";
|
|
31680
31654
|
var ChunkStorageService = _ChunkStorageService;
|
|
31681
31655
|
|
|
@@ -31857,41 +31831,32 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
31857
31831
|
console.log(`[BackgroundUpload] ${pendingChunks.length} chunks pendentes encontrados. Modo final: ${isFinal}`);
|
|
31858
31832
|
let virtualStart = this.totalBytesPurged;
|
|
31859
31833
|
const chunksWithMeta = allChunks.map((c3) => {
|
|
31860
|
-
const byteLen = c3.arrayBuffer.byteLength;
|
|
31861
31834
|
const start = virtualStart;
|
|
31862
|
-
const end = start +
|
|
31863
|
-
virtualStart +=
|
|
31835
|
+
const end = start + c3.blob.size - 1;
|
|
31836
|
+
virtualStart += c3.blob.size;
|
|
31864
31837
|
return { chunk: c3, start, end };
|
|
31865
31838
|
});
|
|
31866
|
-
|
|
31839
|
+
let combinedBlobParts = [];
|
|
31867
31840
|
let lastProcessedChunkId = null;
|
|
31868
31841
|
let finalChunkIndex = 0;
|
|
31869
31842
|
let mimeType = pendingChunks[0].mimeType;
|
|
31870
31843
|
for (const meta of chunksWithMeta) {
|
|
31871
31844
|
if (this.currentOffset > meta.end) continue;
|
|
31872
31845
|
const sliceStart = Math.max(0, this.currentOffset - meta.start);
|
|
31873
|
-
const
|
|
31874
|
-
|
|
31846
|
+
const chunkSlice = meta.chunk.blob.slice(sliceStart);
|
|
31847
|
+
combinedBlobParts.push(chunkSlice);
|
|
31875
31848
|
lastProcessedChunkId = meta.chunk.id;
|
|
31876
31849
|
finalChunkIndex = meta.chunk.chunkIndex;
|
|
31877
31850
|
}
|
|
31878
|
-
if (
|
|
31851
|
+
if (combinedBlobParts.length === 0 && !isFinal) {
|
|
31879
31852
|
this.isProcessing = false;
|
|
31880
31853
|
return;
|
|
31881
31854
|
}
|
|
31882
|
-
|
|
31883
|
-
|
|
31884
|
-
{
|
|
31885
|
-
let off = 0;
|
|
31886
|
-
for (const p3 of sliceParts) {
|
|
31887
|
-
combined.set(p3, off);
|
|
31888
|
-
off += p3.length;
|
|
31889
|
-
}
|
|
31890
|
-
}
|
|
31891
|
-
let sendableSize = combined.byteLength;
|
|
31855
|
+
let fullBlob = new Blob(combinedBlobParts, { type: mimeType });
|
|
31856
|
+
let sendableSize = fullBlob.size;
|
|
31892
31857
|
let totalSizeForHeader = void 0;
|
|
31893
31858
|
if (!isFinal) {
|
|
31894
|
-
sendableSize = Math.floor(
|
|
31859
|
+
sendableSize = Math.floor(fullBlob.size / this.GCS_CHUNK_SIZE) * this.GCS_CHUNK_SIZE;
|
|
31895
31860
|
if (sendableSize === 0) {
|
|
31896
31861
|
console.log("[BackgroundUpload] Dados insuficientes para atingir 256KB. Aguardando novo chunk...");
|
|
31897
31862
|
this.isProcessing = false;
|
|
@@ -31900,14 +31865,9 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
31900
31865
|
} else {
|
|
31901
31866
|
totalSizeForHeader = virtualStart;
|
|
31902
31867
|
}
|
|
31903
|
-
const
|
|
31868
|
+
const blobToSend = fullBlob.slice(0, sendableSize);
|
|
31904
31869
|
try {
|
|
31905
|
-
await this.uploadData(
|
|
31906
|
-
payload.byteLength > 0 ? payload : null,
|
|
31907
|
-
mimeType,
|
|
31908
|
-
finalChunkIndex,
|
|
31909
|
-
totalSizeForHeader
|
|
31910
|
-
);
|
|
31870
|
+
await this.uploadData(blobToSend, mimeType, finalChunkIndex, totalSizeForHeader);
|
|
31911
31871
|
for (const meta of chunksWithMeta) {
|
|
31912
31872
|
if (meta.chunk.uploaded === 0 && meta.end < this.currentOffset) {
|
|
31913
31873
|
await this.chunkStorage.markAsUploaded(meta.chunk.id);
|
|
@@ -31918,10 +31878,7 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
31918
31878
|
}
|
|
31919
31879
|
if (this.config.cleanAfterUpload) {
|
|
31920
31880
|
const chunksToClear = chunksWithMeta.filter((meta) => meta.chunk.uploaded === 1 || meta.chunk.uploaded === 0 && meta.end < this.currentOffset);
|
|
31921
|
-
const sizePurged = chunksToClear.reduce(
|
|
31922
|
-
(acc, meta) => acc + meta.chunk.arrayBuffer.byteLength,
|
|
31923
|
-
0
|
|
31924
|
-
);
|
|
31881
|
+
const sizePurged = chunksToClear.reduce((acc, meta) => acc + meta.chunk.blob.size, 0);
|
|
31925
31882
|
await this.chunkStorage.clearUploadedChunks(this.proctoringId);
|
|
31926
31883
|
if (sizePurged > 0) {
|
|
31927
31884
|
this.totalBytesPurged += sizePurged;
|
|
@@ -31945,8 +31902,7 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
31945
31902
|
/**
|
|
31946
31903
|
* Faz o upload bruto de dados para a sessão GCS.
|
|
31947
31904
|
*/
|
|
31948
|
-
async uploadData(
|
|
31949
|
-
var _a2;
|
|
31905
|
+
async uploadData(blob, mimeType, chunkIndex, totalSize) {
|
|
31950
31906
|
const fileName = `EP_${this.proctoringId}_camera_0.webm`;
|
|
31951
31907
|
if (!this.sessionUrl) {
|
|
31952
31908
|
const initiateUrl = await this.backend.initiateUpload(this.token, `${this.proctoringId}/${fileName}`, mimeType);
|
|
@@ -31977,28 +31933,16 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
31977
31933
|
} else {
|
|
31978
31934
|
console.log(`[BackgroundUpload] Usando sess\xE3o GCS existente: ${this.sessionUrl}`);
|
|
31979
31935
|
}
|
|
31980
|
-
const size = (_a2 = body == null ? void 0 : body.byteLength) != null ? _a2 : 0;
|
|
31981
31936
|
const start = this.currentOffset;
|
|
31982
|
-
const end = start + size - 1;
|
|
31937
|
+
const end = start + blob.size - 1;
|
|
31983
31938
|
const totalHeader = totalSize !== void 0 ? totalSize.toString() : "*";
|
|
31984
|
-
const contentRangeHeader = size === 0 && totalSize !== void 0 ? `bytes */${totalHeader}` : `bytes ${start}-${end}/${totalHeader}`;
|
|
31985
|
-
console.log(
|
|
31986
|
-
`[BackgroundUpload] Enviando ${size > 0 ? "dados" : "finaliza\xE7\xE3o"}: ${contentRangeHeader} (Size: ${size})`
|
|
31987
|
-
);
|
|
31988
|
-
let uploadBody = null;
|
|
31989
|
-
if (size > 0 && body) {
|
|
31990
|
-
const raw = body.buffer;
|
|
31991
|
-
if (raw instanceof ArrayBuffer) {
|
|
31992
|
-
uploadBody = body.byteOffset === 0 && body.byteLength === raw.byteLength ? raw : raw.slice(body.byteOffset, body.byteOffset + body.byteLength);
|
|
31993
|
-
} else {
|
|
31994
|
-
uploadBody = new ArrayBuffer(body.byteLength);
|
|
31995
|
-
new Uint8Array(uploadBody).set(body);
|
|
31996
|
-
}
|
|
31997
|
-
}
|
|
31939
|
+
const contentRangeHeader = blob.size === 0 && totalSize !== void 0 ? `bytes */${totalHeader}` : `bytes ${start}-${end}/${totalHeader}`;
|
|
31940
|
+
console.log(`[BackgroundUpload] Enviando ${blob.size > 0 ? "dados" : "finaliza\xE7\xE3o"}: ${contentRangeHeader} (Size: ${blob.size})`);
|
|
31998
31941
|
const response = await fetch(this.sessionUrl, {
|
|
31999
31942
|
method: "PUT",
|
|
32000
31943
|
headers: { "Content-Range": contentRangeHeader },
|
|
32001
|
-
body:
|
|
31944
|
+
body: blob.size > 0 ? blob : null
|
|
31945
|
+
// Usa null para garantir corpo vazio se necessário
|
|
32002
31946
|
});
|
|
32003
31947
|
console.log(`[BackgroundUpload] Resposta GCS (uploadData): ${response.status}`);
|
|
32004
31948
|
if (response.status !== 200 && response.status !== 201 && response.status !== 308) {
|
|
@@ -32011,13 +31955,13 @@ var BackgroundUploadService = class _BackgroundUploadService {
|
|
|
32011
31955
|
const lastByte = parseInt(rangeHeader.split("-")[1], 10);
|
|
32012
31956
|
this.currentOffset = lastByte + 1;
|
|
32013
31957
|
} else {
|
|
32014
|
-
this.currentOffset += size;
|
|
31958
|
+
this.currentOffset += blob.size;
|
|
32015
31959
|
}
|
|
32016
31960
|
this.saveSessionState();
|
|
32017
31961
|
trackers.registerUploadFile(
|
|
32018
31962
|
this.proctoringId,
|
|
32019
31963
|
`GCS Stream Upload
|
|
32020
|
-
Size: ${size}
|
|
31964
|
+
Size: ${blob.size}
|
|
32021
31965
|
Range: ${start}-${end}
|
|
32022
31966
|
Last Index: ${chunkIndex}`,
|
|
32023
31967
|
"CameraChunk"
|
|
@@ -32536,23 +32480,19 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32536
32480
|
}
|
|
32537
32481
|
if (this.isChunkEnabled) {
|
|
32538
32482
|
if (this.backgroundUpload) {
|
|
32539
|
-
trackers.registerError(this.proctoringId, `Flush e parada do background upload`);
|
|
32540
32483
|
try {
|
|
32541
32484
|
if (this.pendingChunkSaves.length > 0) {
|
|
32542
32485
|
console.log(`[CameraRecorder] Aguardando ${this.pendingChunkSaves.length} salvamentos de chunks pendentes...`);
|
|
32543
32486
|
await Promise.all(this.pendingChunkSaves);
|
|
32544
32487
|
}
|
|
32545
32488
|
await this.backgroundUpload.flush();
|
|
32546
|
-
this.backgroundUpload.stop();
|
|
32547
32489
|
} catch (e3) {
|
|
32548
32490
|
console.warn("[CameraRecorder] Erro ao fazer flush dos chunks:", e3);
|
|
32549
|
-
trackers.registerError(this.proctoringId, `Flush Chunks
|
|
32550
|
-
Error: ${e3}`);
|
|
32551
32491
|
}
|
|
32492
|
+
this.backgroundUpload.stop();
|
|
32552
32493
|
}
|
|
32553
32494
|
this.removeLifecycleListeners();
|
|
32554
32495
|
this.persistSessionState("FINISHED");
|
|
32555
|
-
trackers.registerError(this.proctoringId, `Finalizando flush e parada do background upload`);
|
|
32556
32496
|
}
|
|
32557
32497
|
}
|
|
32558
32498
|
/**
|
|
@@ -32564,11 +32504,10 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32564
32504
|
const savePromise = (async () => {
|
|
32565
32505
|
var _a2;
|
|
32566
32506
|
try {
|
|
32567
|
-
const arrayBuffer = await blob.arrayBuffer();
|
|
32568
32507
|
await this.chunkStorage.saveChunk({
|
|
32569
32508
|
proctoringId: this.proctoringId,
|
|
32570
32509
|
chunkIndex: this.chunkIndex,
|
|
32571
|
-
|
|
32510
|
+
blob,
|
|
32572
32511
|
timestamp: Date.now(),
|
|
32573
32512
|
uploaded: 0,
|
|
32574
32513
|
mimeType: ((_a2 = this.recorderOptions) == null ? void 0 : _a2.mimeType) || "video/webm"
|
|
@@ -32576,8 +32515,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32576
32515
|
this.chunkIndex++;
|
|
32577
32516
|
console.log(`[CameraRecorder] Chunk ${this.chunkIndex - 1} salvo no IndexedDB.`);
|
|
32578
32517
|
} catch (error) {
|
|
32579
|
-
trackers.registerError(this.proctoringId, `Save Chunk
|
|
32580
|
-
Error: ${error}`);
|
|
32581
32518
|
console.error("[CameraRecorder] Erro ao salvar chunk no IndexedDB:", error);
|
|
32582
32519
|
}
|
|
32583
32520
|
})();
|
|
@@ -32726,7 +32663,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32726
32663
|
const settingsAudio = this.cameraStream.getAudioTracks()[0].getSettings();
|
|
32727
32664
|
if (this.options.proctoringType == "VIDEO" || this.options.proctoringType == "REALTIME" || this.options.proctoringType == "IMAGE" && ((_a2 = this.paramsConfig.imageBehaviourParameters) == null ? void 0 : _a2.saveVideo)) {
|
|
32728
32665
|
let videoFile;
|
|
32729
|
-
trackers.registerError(this.proctoringId, `saveOnSession iniciando`);
|
|
32730
32666
|
if (this.isChunkEnabled) {
|
|
32731
32667
|
const isStable = await this.checkInternetStability();
|
|
32732
32668
|
if (isStable) {
|
|
@@ -32735,19 +32671,13 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32735
32671
|
const fileName = `EP_${this.proctoringId}_camera_0.webm`;
|
|
32736
32672
|
const objectName = `${this.proctoringId}/${fileName}`;
|
|
32737
32673
|
const isUploaded = await this.backend.checkUpload(this.backendToken, objectName, "video/webm");
|
|
32738
|
-
trackers.registerError(this.proctoringId, `Limpa o armazenamento local pois o v\xEDdeo j\xE1 est\xE1 no servidor`);
|
|
32739
32674
|
if (isUploaded) {
|
|
32740
|
-
|
|
32741
|
-
this.chunkStorage && await this.chunkStorage.clearAllChunks(session.id);
|
|
32742
|
-
} catch (e3) {
|
|
32743
|
-
trackers.registerError(this.proctoringId, `Erro ao limpar o armazenamento local: ${e3}`);
|
|
32744
|
-
}
|
|
32675
|
+
this.chunkStorage && await this.chunkStorage.clearAllChunks(session.id);
|
|
32745
32676
|
return;
|
|
32746
32677
|
}
|
|
32747
32678
|
}
|
|
32748
32679
|
}
|
|
32749
32680
|
}
|
|
32750
|
-
trackers.registerError(this.proctoringId, `saveOnSession gerando v\xEDdeo a partir do buffer em mem\xF3ria (\xEDntegra)`);
|
|
32751
32681
|
const rawBlob = new Blob(this.blobs, {
|
|
32752
32682
|
type: ((_b = this.recorderOptions) == null ? void 0 : _b.mimeType) || "video/webm"
|
|
32753
32683
|
});
|
|
@@ -32768,7 +32698,6 @@ Setting: ${JSON.stringify(settings, null, 2)}`
|
|
|
32768
32698
|
origin: "Camera" /* Camera */
|
|
32769
32699
|
});
|
|
32770
32700
|
}
|
|
32771
|
-
trackers.registerError(this.proctoringId, `saveOnSession finalizado`);
|
|
32772
32701
|
}
|
|
32773
32702
|
async getFile(file, name, type) {
|
|
32774
32703
|
return new Promise((resolve, reject) => {
|
|
@@ -39055,6 +38984,7 @@ Error: ${error}`
|
|
|
39055
38984
|
trackers.registerError(this.proctoringId, `finish sendPendingRealtimeAlerts`);
|
|
39056
38985
|
await this.sendPendingRealtimeAlerts();
|
|
39057
38986
|
trackers.registerError(this.proctoringId, `finish this.repository.save`);
|
|
38987
|
+
await this.repository.save(this.proctoringSession);
|
|
39058
38988
|
let uploader;
|
|
39059
38989
|
let uploaderServices;
|
|
39060
38990
|
trackers.registerError(this.proctoringId, `finish uploader`);
|