@jaak.ai/stamps 2.0.0-dev.27 → 2.0.0-dev.29
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/dist/cjs/jaak-stamps.cjs.entry.js +252 -72
- package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
- package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
- package/dist/collection/components/my-component/my-component.js +252 -72
- package/dist/collection/components/my-component/my-component.js.map +1 -1
- package/dist/components/jaak-stamps.js +252 -72
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/jaak-stamps.entry.js +252 -72
- package/dist/esm/jaak-stamps.entry.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/p-28adb830.entry.js +2 -0
- package/dist/jaak-stamps-webcomponent/p-28adb830.entry.js.map +1 -0
- package/dist/types/components/my-component/my-component.d.ts +2 -1
- package/package.json +1 -1
- package/dist/jaak-stamps-webcomponent/p-eb318f43.entry.js +0 -2
- package/dist/jaak-stamps-webcomponent/p-eb318f43.entry.js.map +0 -1
|
@@ -78,34 +78,65 @@ const JaakStamps = class {
|
|
|
78
78
|
CONFIDENCE_THRESHOLD = 0.6;
|
|
79
79
|
// ISO/IEC 7810 ID-1 standard dimensions (85.60mm x 53.98mm)
|
|
80
80
|
ID1_ASPECT_RATIO = 85.60 / 53.98; // 1.5863320574...
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
logger = {
|
|
82
|
+
info: (...args) => {
|
|
83
|
+
if (this.debug) {
|
|
84
|
+
console.log(`[JAAK-STAMPS] [INFO] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
warn: (...args) => {
|
|
88
|
+
if (this.debug) {
|
|
89
|
+
console.warn(`[JAAK-STAMPS] [WARN] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
error: (...args) => {
|
|
93
|
+
if (this.debug) {
|
|
94
|
+
console.error(`[JAAK-STAMPS] [ERROR] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
debug: (...args) => {
|
|
98
|
+
if (this.debug) {
|
|
99
|
+
console.debug(`[JAAK-STAMPS] [DEBUG] [${new Date().toLocaleTimeString()}]`, ...args);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
state: (state, data) => {
|
|
103
|
+
if (this.debug) {
|
|
104
|
+
console.log(`[JAAK-STAMPS] [STATE] [${new Date().toLocaleTimeString()}] ${state}`, data || '');
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
performance: (operation, duration) => {
|
|
108
|
+
if (this.debug) {
|
|
109
|
+
console.log(`[JAAK-STAMPS] [PERF] [${new Date().toLocaleTimeString()}] ${operation}: ${duration}ms`);
|
|
110
|
+
}
|
|
84
111
|
}
|
|
85
|
-
}
|
|
112
|
+
};
|
|
86
113
|
validateMaskSize() {
|
|
87
114
|
if (this.maskSize < 50 || this.maskSize > 100) {
|
|
88
|
-
|
|
115
|
+
this.logger.warn(`Propiedad maskSize inválida. Valor: ${this.maskSize}, esperado: 50-100. Usando valor por defecto: 90`);
|
|
89
116
|
this.maskSize = 90;
|
|
90
117
|
}
|
|
91
118
|
}
|
|
92
119
|
validateCropMargin() {
|
|
93
120
|
if (this.cropMargin < 0 || this.cropMargin > 100) {
|
|
94
|
-
|
|
121
|
+
this.logger.warn(`Propiedad cropMargin inválida. Valor: ${this.cropMargin}, esperado: 0-100. Usando valor por defecto: 0`);
|
|
95
122
|
this.cropMargin = 0;
|
|
96
123
|
}
|
|
97
124
|
}
|
|
98
125
|
validatePreferredCamera() {
|
|
99
126
|
const validOptions = ['auto', 'front', 'back'];
|
|
100
127
|
if (!validOptions.includes(this.preferredCamera)) {
|
|
101
|
-
|
|
128
|
+
this.logger.warn(`Propiedad preferredCamera inválida. Valor: ${this.preferredCamera}, esperado: ${validOptions.join(', ')}. Usando valor por defecto: 'auto'`);
|
|
102
129
|
this.preferredCamera = 'auto';
|
|
103
130
|
}
|
|
104
131
|
}
|
|
105
132
|
emitReadyEvent() {
|
|
106
133
|
const isDocumentReady = !!window.ort && this.isModelPreloaded;
|
|
107
134
|
this.isReady.emit(isDocumentReady);
|
|
108
|
-
this.
|
|
135
|
+
this.logger.state('COMPONENTE_LISTO', {
|
|
136
|
+
ortLibraryLoaded: !!window.ort,
|
|
137
|
+
modelPreloaded: this.isModelPreloaded,
|
|
138
|
+
isReady: isDocumentReady
|
|
139
|
+
});
|
|
109
140
|
}
|
|
110
141
|
isRearCamera(stream) {
|
|
111
142
|
const videoTrack = stream.getVideoTracks()[0];
|
|
@@ -128,7 +159,11 @@ const JaakStamps = class {
|
|
|
128
159
|
else {
|
|
129
160
|
this.deviceType = 'desktop';
|
|
130
161
|
}
|
|
131
|
-
this.
|
|
162
|
+
this.logger.state('DISPOSITIVO_DETECTADO', {
|
|
163
|
+
deviceType: this.deviceType,
|
|
164
|
+
userAgent: navigator.userAgent,
|
|
165
|
+
screenDimensions: { width: window.innerWidth, height: window.innerHeight }
|
|
166
|
+
});
|
|
132
167
|
// Enumerate available cameras
|
|
133
168
|
await this.enumerateAndDetectCameras();
|
|
134
169
|
// Load user preference
|
|
@@ -139,7 +174,7 @@ const JaakStamps = class {
|
|
|
139
174
|
// First, check if we have permission to enumerate devices
|
|
140
175
|
const permissionStatus = await this.checkCameraPermission();
|
|
141
176
|
if (permissionStatus === 'denied') {
|
|
142
|
-
this.
|
|
177
|
+
this.logger.error('Permiso de cámara denegado por el usuario');
|
|
143
178
|
this.statusMessage = "Permiso de cámara denegado";
|
|
144
179
|
this.statusColor = "#ff6b6b";
|
|
145
180
|
return;
|
|
@@ -153,7 +188,7 @@ const JaakStamps = class {
|
|
|
153
188
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
154
189
|
this.availableCameras = devices.filter(device => device.kind === 'videoinput');
|
|
155
190
|
this.isMultipleCamerasAvailable = this.availableCameras.length > 1;
|
|
156
|
-
this.
|
|
191
|
+
this.logger.state('CAMARAS_DETECTADAS', {
|
|
157
192
|
count: this.availableCameras.length,
|
|
158
193
|
isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
|
|
159
194
|
cameras: this.availableCameras.map(cam => ({
|
|
@@ -165,7 +200,7 @@ const JaakStamps = class {
|
|
|
165
200
|
this.setInitialCameraPreference();
|
|
166
201
|
}
|
|
167
202
|
catch (error) {
|
|
168
|
-
this.
|
|
203
|
+
this.logger.error('Error al enumerar cámaras disponibles:', error);
|
|
169
204
|
this.handleCameraPermissionError(error);
|
|
170
205
|
}
|
|
171
206
|
}
|
|
@@ -178,7 +213,7 @@ const JaakStamps = class {
|
|
|
178
213
|
return permission.state;
|
|
179
214
|
}
|
|
180
215
|
catch (error) {
|
|
181
|
-
this.
|
|
216
|
+
this.logger.warn('No se pudo verificar permisos de cámara:', error);
|
|
182
217
|
return 'prompt';
|
|
183
218
|
}
|
|
184
219
|
}
|
|
@@ -221,11 +256,11 @@ const JaakStamps = class {
|
|
|
221
256
|
!camera.label.toLowerCase().includes('back') && !camera.label.toLowerCase().includes('rear'));
|
|
222
257
|
if (frontCamera) {
|
|
223
258
|
this.selectedCameraId = frontCamera.deviceId;
|
|
224
|
-
this.
|
|
259
|
+
this.logger.state('CAMARA_FRONTAL_SELECCIONADA', { label: frontCamera.label, deviceId: frontCamera.deviceId });
|
|
225
260
|
}
|
|
226
261
|
else {
|
|
227
262
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
228
|
-
this.
|
|
263
|
+
this.logger.warn('Cámara frontal no encontrada, usando primera disponible:', this.availableCameras[0].label);
|
|
229
264
|
}
|
|
230
265
|
}
|
|
231
266
|
else if (this.preferredCamera === 'back') {
|
|
@@ -236,11 +271,11 @@ const JaakStamps = class {
|
|
|
236
271
|
camera.label.toLowerCase().includes('environment'));
|
|
237
272
|
if (backCamera) {
|
|
238
273
|
this.selectedCameraId = backCamera.deviceId;
|
|
239
|
-
this.
|
|
274
|
+
this.logger.state('CAMARA_TRASERA_SELECCIONADA', { label: backCamera.label, deviceId: backCamera.deviceId });
|
|
240
275
|
}
|
|
241
276
|
else {
|
|
242
277
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
243
|
-
this.
|
|
278
|
+
this.logger.warn('Cámara trasera no encontrada, usando primera disponible:', this.availableCameras[0].label);
|
|
244
279
|
}
|
|
245
280
|
}
|
|
246
281
|
else {
|
|
@@ -253,17 +288,17 @@ const JaakStamps = class {
|
|
|
253
288
|
camera.label.toLowerCase().includes('environment'));
|
|
254
289
|
if (rearCamera) {
|
|
255
290
|
this.selectedCameraId = rearCamera.deviceId;
|
|
256
|
-
this.
|
|
291
|
+
this.logger.state('CAMARA_AUTO_SELECCIONADA_MOBILE', { type: 'rear', label: rearCamera.label, deviceId: rearCamera.deviceId });
|
|
257
292
|
}
|
|
258
293
|
else {
|
|
259
294
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
260
|
-
this.
|
|
295
|
+
this.logger.warn('Cámara trasera no encontrada en mobile, usando primera disponible:', this.availableCameras[0].label);
|
|
261
296
|
}
|
|
262
297
|
}
|
|
263
298
|
else {
|
|
264
299
|
// For desktop, use first available camera (usually the only one)
|
|
265
300
|
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
266
|
-
this.
|
|
301
|
+
this.logger.state('CAMARA_AUTO_SELECCIONADA_DESKTOP', { label: this.availableCameras[0].label, deviceId: this.availableCameras[0].deviceId });
|
|
267
302
|
}
|
|
268
303
|
}
|
|
269
304
|
}
|
|
@@ -277,12 +312,12 @@ const JaakStamps = class {
|
|
|
277
312
|
if (isStillAvailable) {
|
|
278
313
|
this.selectedCameraId = preference.cameraId;
|
|
279
314
|
this.preferredCameraFacing = preference.facing;
|
|
280
|
-
this.
|
|
315
|
+
this.logger.state('PREFERENCIA_CAMARA_CARGADA', preference);
|
|
281
316
|
}
|
|
282
317
|
}
|
|
283
318
|
}
|
|
284
319
|
catch (error) {
|
|
285
|
-
this.
|
|
320
|
+
this.logger.warn('Error al cargar preferencia de cámara:', error);
|
|
286
321
|
}
|
|
287
322
|
}
|
|
288
323
|
saveCameraPreference() {
|
|
@@ -293,10 +328,10 @@ const JaakStamps = class {
|
|
|
293
328
|
timestamp: Date.now()
|
|
294
329
|
};
|
|
295
330
|
localStorage.setItem('jaak-stamps-camera-preference', JSON.stringify(preference));
|
|
296
|
-
this.
|
|
331
|
+
this.logger.state('PREFERENCIA_CAMARA_GUARDADA', preference);
|
|
297
332
|
}
|
|
298
333
|
catch (error) {
|
|
299
|
-
this.
|
|
334
|
+
this.logger.warn('Error al guardar preferencia de cámara:', error);
|
|
300
335
|
}
|
|
301
336
|
}
|
|
302
337
|
async switchCamera(cameraId) {
|
|
@@ -306,7 +341,7 @@ const JaakStamps = class {
|
|
|
306
341
|
// Check if the selected camera is still available
|
|
307
342
|
const selectedCamera = this.availableCameras.find(cam => cam.deviceId === cameraId);
|
|
308
343
|
if (!selectedCamera) {
|
|
309
|
-
this.
|
|
344
|
+
this.logger.warn('Cámara seleccionada no encontrada, re-enumerando dispositivos...');
|
|
310
345
|
await this.enumerateAndDetectCameras();
|
|
311
346
|
return;
|
|
312
347
|
}
|
|
@@ -330,10 +365,10 @@ const JaakStamps = class {
|
|
|
330
365
|
this.saveCameraPreference();
|
|
331
366
|
// Setup new camera with error handling
|
|
332
367
|
await this.setupCameraWithRetry();
|
|
333
|
-
this.
|
|
368
|
+
this.logger.state('CAMARA_CAMBIADA', { label: selectedCamera.label, deviceId: selectedCamera.deviceId });
|
|
334
369
|
}
|
|
335
370
|
catch (error) {
|
|
336
|
-
this.
|
|
371
|
+
this.logger.error('Error al cambiar de cámara:', error);
|
|
337
372
|
this.handleCameraPermissionError(error);
|
|
338
373
|
}
|
|
339
374
|
}
|
|
@@ -348,7 +383,7 @@ const JaakStamps = class {
|
|
|
348
383
|
return; // Success
|
|
349
384
|
}
|
|
350
385
|
catch (error) {
|
|
351
|
-
this.
|
|
386
|
+
this.logger.error(`Intento ${attempt} de configuración de cámara fallido:`, error);
|
|
352
387
|
if (attempt === maxRetries) {
|
|
353
388
|
// Last attempt failed, handle the error
|
|
354
389
|
this.statusMessage = "Error al configurar la cámara";
|
|
@@ -368,7 +403,7 @@ const JaakStamps = class {
|
|
|
368
403
|
}
|
|
369
404
|
toggleCameraSelector() {
|
|
370
405
|
this.showCameraSelector = !this.showCameraSelector;
|
|
371
|
-
this.
|
|
406
|
+
this.logger.state('SELECTOR_CAMARA_TOGGLE', {
|
|
372
407
|
showCameraSelector: this.showCameraSelector,
|
|
373
408
|
isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
|
|
374
409
|
availableCameras: this.availableCameras.length,
|
|
@@ -384,6 +419,13 @@ const JaakStamps = class {
|
|
|
384
419
|
await this.switchCamera(nextCamera.deviceId);
|
|
385
420
|
}
|
|
386
421
|
async componentDidLoad() {
|
|
422
|
+
this.logger.state('COMPONENTE_INICIALIZANDO', {
|
|
423
|
+
debug: this.debug,
|
|
424
|
+
maskSize: this.maskSize,
|
|
425
|
+
cropMargin: this.cropMargin,
|
|
426
|
+
useDocumentClassification: this.useDocumentClassification,
|
|
427
|
+
preferredCamera: this.preferredCamera
|
|
428
|
+
});
|
|
387
429
|
if (this.debug) {
|
|
388
430
|
// Show detailed initialization loading state only in debug mode
|
|
389
431
|
this.isLoading = true;
|
|
@@ -448,7 +490,7 @@ const JaakStamps = class {
|
|
|
448
490
|
this.canvasRef.height = rect.height;
|
|
449
491
|
// Update mask positioning based on container and video dimensions
|
|
450
492
|
this.updateMaskDimensions(rect);
|
|
451
|
-
this.
|
|
493
|
+
this.logger.debug('Canvas redimensionado:', { width: rect.width, height: rect.height });
|
|
452
494
|
}
|
|
453
495
|
}
|
|
454
496
|
updateMaskDimensions(containerRect) {
|
|
@@ -508,7 +550,7 @@ const JaakStamps = class {
|
|
|
508
550
|
this.el.style.setProperty('--mask-center-y', `${videoCenterYPercent}%`);
|
|
509
551
|
// Mark mask as ready now that dimensions are calculated
|
|
510
552
|
this.isMaskReady = true;
|
|
511
|
-
this.
|
|
553
|
+
this.logger.state('DIMENSIONES_MASCARA_ACTUALIZADAS', {
|
|
512
554
|
video: { width: videoWidth, height: videoHeight },
|
|
513
555
|
displayed: { width: displayedVideoWidth, height: displayedVideoHeight },
|
|
514
556
|
mask: { widthPercent: maskWidthPercent, heightPercent: maskHeightPercent },
|
|
@@ -530,7 +572,7 @@ const JaakStamps = class {
|
|
|
530
572
|
this.captureCtx = this.captureCanvas.getContext('2d', {
|
|
531
573
|
alpha: false
|
|
532
574
|
});
|
|
533
|
-
this.
|
|
575
|
+
this.logger.state('CANVAS_POOL_INICIALIZADO', { preprocessCanvasSize: this.INPUT_SIZE });
|
|
534
576
|
}
|
|
535
577
|
disconnectedCallback() {
|
|
536
578
|
this.cleanup();
|
|
@@ -578,7 +620,7 @@ const JaakStamps = class {
|
|
|
578
620
|
}
|
|
579
621
|
async preloadModel() {
|
|
580
622
|
if (this.isModelPreloaded || this.session) {
|
|
581
|
-
this.
|
|
623
|
+
this.logger.state('MODELO_YA_PRECARGADO', { sessionExists: !!this.session, modelPreloaded: this.isModelPreloaded });
|
|
582
624
|
return { success: true, message: 'Model already loaded' };
|
|
583
625
|
}
|
|
584
626
|
try {
|
|
@@ -586,12 +628,39 @@ const JaakStamps = class {
|
|
|
586
628
|
this.statusMessage = "Precargando modelos...";
|
|
587
629
|
this.statusColor = "#007bff";
|
|
588
630
|
const modelPath = this.MODEL_PATH;
|
|
589
|
-
this.
|
|
631
|
+
this.logger.state('PRECARGANDO_MODELO_DETECCION', { modelPath });
|
|
590
632
|
// Configure ONNX Runtime with device-specific optimizations
|
|
591
633
|
const sessionOptions = this.getSessionOptions();
|
|
592
|
-
|
|
634
|
+
const deviceInfo = this.getDeviceMemoryInfo();
|
|
635
|
+
try {
|
|
636
|
+
this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
|
|
637
|
+
}
|
|
638
|
+
catch (error) {
|
|
639
|
+
if (error.message.includes('failed to allocate a buffer')) {
|
|
640
|
+
this.logger.warn('Fallo en asignación de buffer durante precarga, intentando con configuración mínima');
|
|
641
|
+
const fallbackOptions = {
|
|
642
|
+
executionProviders: ['wasm'],
|
|
643
|
+
graphOptimizationLevel: 'disabled',
|
|
644
|
+
logSeverityLevel: 4,
|
|
645
|
+
enableCpuMemArena: false,
|
|
646
|
+
enableMemPattern: false,
|
|
647
|
+
executionMode: 'sequential',
|
|
648
|
+
interOpNumThreads: 1,
|
|
649
|
+
intraOpNumThreads: 1,
|
|
650
|
+
};
|
|
651
|
+
this.session = await window.ort.InferenceSession.create(modelPath, fallbackOptions);
|
|
652
|
+
}
|
|
653
|
+
else {
|
|
654
|
+
throw error;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
593
657
|
// Preload MobileNet model and classes only if classification is enabled
|
|
658
|
+
// For low memory devices, load sequentially to avoid memory pressure
|
|
594
659
|
if (this.useDocumentClassification) {
|
|
660
|
+
if (deviceInfo.isLowMemory) {
|
|
661
|
+
this.logger.state('CARGA_SECUENCIAL_MODELOS', { reason: 'low memory device' });
|
|
662
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
663
|
+
}
|
|
595
664
|
await this.loadMobileNetModel();
|
|
596
665
|
}
|
|
597
666
|
this.isModelPreloaded = true;
|
|
@@ -599,11 +668,15 @@ const JaakStamps = class {
|
|
|
599
668
|
this.statusMessage = "Modelos precargados. Listo para comenzar detección";
|
|
600
669
|
this.statusColor = "#28a745";
|
|
601
670
|
this.emitReadyEvent();
|
|
602
|
-
this.
|
|
671
|
+
this.logger.state('MODELOS_PRECARGADOS_EXITOSAMENTE', {
|
|
672
|
+
detectionModel: !!this.session,
|
|
673
|
+
classificationModel: !!this.mobileNetSession,
|
|
674
|
+
useClassification: this.useDocumentClassification
|
|
675
|
+
});
|
|
603
676
|
return { success: true, message: 'Models preloaded successfully' };
|
|
604
677
|
}
|
|
605
678
|
catch (error) {
|
|
606
|
-
this.
|
|
679
|
+
this.logger.error('Error al precargar modelos:', error);
|
|
607
680
|
this.isLoading = false;
|
|
608
681
|
this.statusMessage = "Error al precargar los modelos";
|
|
609
682
|
this.statusColor = "#ff6b6b";
|
|
@@ -631,7 +704,7 @@ const JaakStamps = class {
|
|
|
631
704
|
}
|
|
632
705
|
async setPreferredCamera(camera) {
|
|
633
706
|
this.preferredCamera = camera;
|
|
634
|
-
this.
|
|
707
|
+
this.logger.state('PREFERENCIA_CAMARA_CAMBIADA', { newPreference: camera });
|
|
635
708
|
// Re-detect and apply new camera preference
|
|
636
709
|
await this.enumerateAndDetectCameras();
|
|
637
710
|
// If video is active, switch to the new preferred camera
|
|
@@ -646,21 +719,42 @@ const JaakStamps = class {
|
|
|
646
719
|
}
|
|
647
720
|
async loadMobileNetModel() {
|
|
648
721
|
try {
|
|
649
|
-
this.
|
|
722
|
+
this.logger.state('CARGANDO_MODELO_MOBILENET', { path: this.MOBILENET_MODEL_PATH });
|
|
650
723
|
// Load class map
|
|
651
724
|
const classResponse = await fetch(this.MOBILENET_CLASSES_PATH);
|
|
652
725
|
if (!classResponse.ok) {
|
|
653
726
|
throw new Error(`Failed to load class map: ${this.MOBILENET_CLASSES_PATH}`);
|
|
654
727
|
}
|
|
655
728
|
this.mobileNetClassMap = await classResponse.json();
|
|
656
|
-
this.
|
|
729
|
+
this.logger.state('CLASES_MOBILENET_CARGADAS', { classCount: Object.keys(this.mobileNetClassMap).length });
|
|
657
730
|
// Load model
|
|
658
731
|
const sessionOptions = this.getSessionOptions();
|
|
659
|
-
|
|
660
|
-
|
|
732
|
+
try {
|
|
733
|
+
this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, sessionOptions);
|
|
734
|
+
}
|
|
735
|
+
catch (error) {
|
|
736
|
+
if (error.message.includes('failed to allocate a buffer')) {
|
|
737
|
+
this.logger.warn('Fallo en asignación de buffer de MobileNet, intentando con configuración mínima');
|
|
738
|
+
const fallbackOptions = {
|
|
739
|
+
executionProviders: ['wasm'],
|
|
740
|
+
graphOptimizationLevel: 'disabled',
|
|
741
|
+
logSeverityLevel: 4,
|
|
742
|
+
enableCpuMemArena: false,
|
|
743
|
+
enableMemPattern: false,
|
|
744
|
+
executionMode: 'sequential',
|
|
745
|
+
interOpNumThreads: 1,
|
|
746
|
+
intraOpNumThreads: 1,
|
|
747
|
+
};
|
|
748
|
+
this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, fallbackOptions);
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
751
|
+
throw error;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
this.logger.state('MODELO_MOBILENET_CARGADO_EXITOSAMENTE', { sessionCreated: !!this.mobileNetSession });
|
|
661
755
|
}
|
|
662
756
|
catch (error) {
|
|
663
|
-
this.
|
|
757
|
+
this.logger.error('Error al cargar modelo MobileNet:', error);
|
|
664
758
|
throw error;
|
|
665
759
|
}
|
|
666
760
|
}
|
|
@@ -687,11 +781,11 @@ const JaakStamps = class {
|
|
|
687
781
|
}
|
|
688
782
|
async classifyDocument(canvas) {
|
|
689
783
|
if (!this.mobileNetSession || !this.mobileNetClassMap) {
|
|
690
|
-
this.
|
|
784
|
+
this.logger.warn('Modelo MobileNet no está cargado, saltando clasificación');
|
|
691
785
|
return null;
|
|
692
786
|
}
|
|
693
787
|
try {
|
|
694
|
-
this.
|
|
788
|
+
this.logger.state('CLASIFICANDO_DOCUMENTO', { timestamp: Date.now() });
|
|
695
789
|
// Preprocess image for MobileNet
|
|
696
790
|
const inputTensor = this.preprocessMobileNet(canvas);
|
|
697
791
|
// Run inference
|
|
@@ -702,10 +796,11 @@ const JaakStamps = class {
|
|
|
702
796
|
const maxIdx = output.reduce((bestIdx, val, idx, arr) => val > arr[bestIdx] ? idx : bestIdx, 0);
|
|
703
797
|
const confidence = output[maxIdx];
|
|
704
798
|
const className = this.mobileNetClassMap[maxIdx.toString()] || "unknown";
|
|
705
|
-
this.
|
|
799
|
+
this.logger.state('DOCUMENTO_CLASIFICADO', {
|
|
706
800
|
class: className,
|
|
707
801
|
confidence: confidence.toFixed(3),
|
|
708
|
-
classIndex: maxIdx
|
|
802
|
+
classIndex: maxIdx,
|
|
803
|
+
timestamp: Date.now()
|
|
709
804
|
});
|
|
710
805
|
return {
|
|
711
806
|
class: className,
|
|
@@ -714,7 +809,7 @@ const JaakStamps = class {
|
|
|
714
809
|
};
|
|
715
810
|
}
|
|
716
811
|
catch (error) {
|
|
717
|
-
this.
|
|
812
|
+
this.logger.error('Error al clasificar documento:', error);
|
|
718
813
|
return null;
|
|
719
814
|
}
|
|
720
815
|
}
|
|
@@ -756,7 +851,7 @@ const JaakStamps = class {
|
|
|
756
851
|
}
|
|
757
852
|
this.mobileNetClassMap = undefined;
|
|
758
853
|
this.isModelPreloaded = false;
|
|
759
|
-
this.
|
|
854
|
+
this.logger.state('CANVAS_POOL_LIMPIADO', { timestamp: Date.now() });
|
|
760
855
|
}
|
|
761
856
|
async getMaxResolution() {
|
|
762
857
|
try {
|
|
@@ -805,18 +900,19 @@ const JaakStamps = class {
|
|
|
805
900
|
constraints.width = { ideal: maxWidth };
|
|
806
901
|
constraints.height = { ideal: maxHeight };
|
|
807
902
|
}
|
|
808
|
-
this.
|
|
903
|
+
this.logger.state('CAPACIDADES_RESOLUCION_DETECTADAS', {
|
|
809
904
|
maxWidth: capabilities.width.max,
|
|
810
905
|
maxHeight: capabilities.height.max,
|
|
811
906
|
selectedWidth: constraints.width.ideal,
|
|
812
907
|
selectedHeight: constraints.height.ideal,
|
|
813
|
-
isTablet
|
|
908
|
+
isTablet,
|
|
909
|
+
deviceType: this.deviceType
|
|
814
910
|
});
|
|
815
911
|
}
|
|
816
912
|
return constraints;
|
|
817
913
|
}
|
|
818
914
|
catch (err) {
|
|
819
|
-
this.
|
|
915
|
+
this.logger.warn('No se pudieron obtener capacidades de cámara, usando configuración de respaldo');
|
|
820
916
|
// Optimized fallback for tablets
|
|
821
917
|
const isTablet = /iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768;
|
|
822
918
|
const fallbackConstraints = {
|
|
@@ -849,8 +945,11 @@ const JaakStamps = class {
|
|
|
849
945
|
// Determine if video should be mirrored
|
|
850
946
|
const isRear = this.isRearCamera(stream);
|
|
851
947
|
this.shouldMirrorVideo = !isRear;
|
|
852
|
-
this.
|
|
853
|
-
|
|
948
|
+
this.logger.state('CAMARA_CONFIGURADA', {
|
|
949
|
+
isRearCamera: isRear,
|
|
950
|
+
shouldMirrorVideo: this.shouldMirrorVideo,
|
|
951
|
+
videoActive: this.isVideoActive
|
|
952
|
+
});
|
|
854
953
|
return new Promise((resolve) => {
|
|
855
954
|
this.videoRef.onloadedmetadata = async () => {
|
|
856
955
|
await this.videoRef.play();
|
|
@@ -867,7 +966,7 @@ const JaakStamps = class {
|
|
|
867
966
|
}
|
|
868
967
|
}
|
|
869
968
|
catch (err) {
|
|
870
|
-
this.
|
|
969
|
+
this.logger.error('No se pudo acceder a la cámara:', err);
|
|
871
970
|
this.handleCameraPermissionError(err);
|
|
872
971
|
}
|
|
873
972
|
}
|
|
@@ -891,15 +990,39 @@ const JaakStamps = class {
|
|
|
891
990
|
const transposedData = new Float32Array(R.concat(G, B));
|
|
892
991
|
return new window.ort.Tensor("float32", transposedData, [1, 3, this.INPUT_SIZE, this.INPUT_SIZE]);
|
|
893
992
|
}
|
|
993
|
+
getDeviceMemoryInfo() {
|
|
994
|
+
const nav = navigator;
|
|
995
|
+
const memory = nav.deviceMemory || nav.hardwareConcurrency || 4;
|
|
996
|
+
const connection = nav.connection || nav.mozConnection || nav.webkitConnection;
|
|
997
|
+
const isSlowConnection = connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g');
|
|
998
|
+
return {
|
|
999
|
+
estimatedRAM: memory,
|
|
1000
|
+
isLowMemory: memory <= 4,
|
|
1001
|
+
isSlowConnection: isSlowConnection
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
894
1004
|
getSessionOptions() {
|
|
1005
|
+
const deviceInfo = this.getDeviceMemoryInfo();
|
|
1006
|
+
if (deviceInfo.isLowMemory) {
|
|
1007
|
+
return {
|
|
1008
|
+
executionProviders: ['wasm'],
|
|
1009
|
+
graphOptimizationLevel: 'basic',
|
|
1010
|
+
logSeverityLevel: 4,
|
|
1011
|
+
logVerbosityLevel: 0,
|
|
1012
|
+
enableCpuMemArena: false,
|
|
1013
|
+
enableMemPattern: false,
|
|
1014
|
+
executionMode: 'sequential',
|
|
1015
|
+
interOpNumThreads: 1,
|
|
1016
|
+
intraOpNumThreads: 1,
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
895
1019
|
return {
|
|
896
1020
|
executionProviders: [
|
|
897
|
-
// Try WebGL first for GPU acceleration, fallback to WASM
|
|
898
1021
|
'webgl',
|
|
899
1022
|
'wasm'
|
|
900
1023
|
],
|
|
901
|
-
graphOptimizationLevel: 'all',
|
|
902
|
-
logSeverityLevel: this.debug ? 2 : 4,
|
|
1024
|
+
graphOptimizationLevel: 'all',
|
|
1025
|
+
logSeverityLevel: this.debug ? 2 : 4,
|
|
903
1026
|
logVerbosityLevel: 0,
|
|
904
1027
|
enableCpuMemArena: true,
|
|
905
1028
|
enableMemPattern: true,
|
|
@@ -909,6 +1032,12 @@ const JaakStamps = class {
|
|
|
909
1032
|
};
|
|
910
1033
|
}
|
|
911
1034
|
async startDetection() {
|
|
1035
|
+
this.logger.state('INICIANDO_DETECCION', {
|
|
1036
|
+
sessionExists: !!this.session,
|
|
1037
|
+
modelPreloaded: this.isModelPreloaded,
|
|
1038
|
+
videoActive: this.isVideoActive,
|
|
1039
|
+
captureStep: this.captureStep
|
|
1040
|
+
});
|
|
912
1041
|
try {
|
|
913
1042
|
// Check if model is already preloaded
|
|
914
1043
|
if (!this.session) {
|
|
@@ -922,9 +1051,30 @@ const JaakStamps = class {
|
|
|
922
1051
|
this.statusColor = "#007bff";
|
|
923
1052
|
}
|
|
924
1053
|
const modelPath = this.MODEL_PATH;
|
|
925
|
-
this.
|
|
1054
|
+
this.logger.state('CARGANDO_MODELO_DETECCION', { modelPath });
|
|
926
1055
|
const sessionOptions = this.getSessionOptions();
|
|
927
|
-
|
|
1056
|
+
try {
|
|
1057
|
+
this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
|
|
1058
|
+
}
|
|
1059
|
+
catch (error) {
|
|
1060
|
+
if (error.message.includes('failed to allocate a buffer')) {
|
|
1061
|
+
this.logger.warn('Fallo en asignación de buffer, intentando con configuración mínima');
|
|
1062
|
+
const fallbackOptions = {
|
|
1063
|
+
executionProviders: ['wasm'],
|
|
1064
|
+
graphOptimizationLevel: 'disabled',
|
|
1065
|
+
logSeverityLevel: 4,
|
|
1066
|
+
enableCpuMemArena: false,
|
|
1067
|
+
enableMemPattern: false,
|
|
1068
|
+
executionMode: 'sequential',
|
|
1069
|
+
interOpNumThreads: 1,
|
|
1070
|
+
intraOpNumThreads: 1,
|
|
1071
|
+
};
|
|
1072
|
+
this.session = await window.ort.InferenceSession.create(modelPath, fallbackOptions);
|
|
1073
|
+
}
|
|
1074
|
+
else {
|
|
1075
|
+
throw error;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
928
1078
|
// Load MobileNet model if classification is enabled and not already loaded
|
|
929
1079
|
if (this.useDocumentClassification && !this.mobileNetSession) {
|
|
930
1080
|
if (this.debug) {
|
|
@@ -939,7 +1089,7 @@ const JaakStamps = class {
|
|
|
939
1089
|
this.emitReadyEvent();
|
|
940
1090
|
}
|
|
941
1091
|
else {
|
|
942
|
-
this.
|
|
1092
|
+
this.logger.state('USANDO_MODELOS_PRECARGADOS', { sessionExists: !!this.session, modelPreloaded: this.isModelPreloaded });
|
|
943
1093
|
if (this.debug) {
|
|
944
1094
|
this.statusMessage = "Usando modelos precargados...";
|
|
945
1095
|
this.statusColor = "#007bff";
|
|
@@ -958,7 +1108,7 @@ const JaakStamps = class {
|
|
|
958
1108
|
this.detectFrame();
|
|
959
1109
|
}
|
|
960
1110
|
catch (err) {
|
|
961
|
-
this.
|
|
1111
|
+
this.logger.error('Error al inicializar detección:', err);
|
|
962
1112
|
this.statusMessage = "Error al inicializar el detector";
|
|
963
1113
|
this.statusColor = "#ff6b6b";
|
|
964
1114
|
this.isLoading = false;
|
|
@@ -1040,7 +1190,7 @@ const JaakStamps = class {
|
|
|
1040
1190
|
}
|
|
1041
1191
|
}
|
|
1042
1192
|
catch (e) {
|
|
1043
|
-
this.
|
|
1193
|
+
this.logger.error('Error en inferencia de modelo:', e);
|
|
1044
1194
|
// Solo continuar si no hemos completado el proceso
|
|
1045
1195
|
if (this.captureStep !== 'completed') {
|
|
1046
1196
|
// On error, wait longer before retrying
|
|
@@ -1168,7 +1318,7 @@ const JaakStamps = class {
|
|
|
1168
1318
|
if (!this.hasScreenshotTaken) {
|
|
1169
1319
|
this.lastDetectedBox = bestBox;
|
|
1170
1320
|
this.takeScreenshot().catch(error => {
|
|
1171
|
-
this.
|
|
1321
|
+
this.logger.error('Error al tomar captura de pantalla:', error);
|
|
1172
1322
|
});
|
|
1173
1323
|
this.hasScreenshotTaken = true;
|
|
1174
1324
|
// Reset para permitir segunda captura
|
|
@@ -1186,6 +1336,7 @@ const JaakStamps = class {
|
|
|
1186
1336
|
if (boxes.length === 0) {
|
|
1187
1337
|
this.statusMessage = "Posicione la identificación dentro del marco";
|
|
1188
1338
|
this.statusColor = "#ff6b6b";
|
|
1339
|
+
this.logger.debug('Sin detección de documento en el frame');
|
|
1189
1340
|
}
|
|
1190
1341
|
else {
|
|
1191
1342
|
const bestBox = boxes.reduce((best, current) => current.score > best.score ? current : best);
|
|
@@ -1195,6 +1346,11 @@ const JaakStamps = class {
|
|
|
1195
1346
|
if (allSidesAligned) {
|
|
1196
1347
|
this.statusMessage = "Identificación perfectamente alineada. Mantenga inmóvil";
|
|
1197
1348
|
this.statusColor = "#00ff00";
|
|
1349
|
+
this.logger.state('DOCUMENTO_PERFECTAMENTE_ALINEADO', {
|
|
1350
|
+
score: bestBox.score,
|
|
1351
|
+
boxDimensions: { width: bestBox.w, height: bestBox.h },
|
|
1352
|
+
alignedSides: 4
|
|
1353
|
+
});
|
|
1198
1354
|
}
|
|
1199
1355
|
else if (alignedSides > 0) {
|
|
1200
1356
|
this.statusMessage = `Alinee los lados restantes (${alignedSides}/4 lados correctos)`;
|
|
@@ -1255,6 +1411,14 @@ const JaakStamps = class {
|
|
|
1255
1411
|
async takeScreenshot() {
|
|
1256
1412
|
if (!this.videoRef || !this.lastDetectedBox)
|
|
1257
1413
|
return;
|
|
1414
|
+
this.logger.state('INICIANDO_CAPTURA', {
|
|
1415
|
+
captureStep: this.captureStep,
|
|
1416
|
+
detectedBox: this.lastDetectedBox,
|
|
1417
|
+
videoResolution: {
|
|
1418
|
+
width: this.videoRef.videoWidth,
|
|
1419
|
+
height: this.videoRef.videoHeight
|
|
1420
|
+
}
|
|
1421
|
+
});
|
|
1258
1422
|
// Activar animación
|
|
1259
1423
|
this.triggerCaptureAnimation();
|
|
1260
1424
|
// OPTIMIZATION: Reuse capture canvas for full frame
|
|
@@ -1294,7 +1458,7 @@ const JaakStamps = class {
|
|
|
1294
1458
|
await this.loadMobileNetModel();
|
|
1295
1459
|
}
|
|
1296
1460
|
catch (error) {
|
|
1297
|
-
this.
|
|
1461
|
+
this.logger.warn('Fallo al cargar modelo de clasificación, continuando sin clasificación:', error);
|
|
1298
1462
|
}
|
|
1299
1463
|
}
|
|
1300
1464
|
// Classify the cropped document if model is available
|
|
@@ -1302,7 +1466,7 @@ const JaakStamps = class {
|
|
|
1302
1466
|
const classification = await this.classifyDocument(croppedCanvas);
|
|
1303
1467
|
if (classification && classification.class === 'passport') {
|
|
1304
1468
|
// If it's a passport, skip back capture since passports don't have a back side
|
|
1305
|
-
this.
|
|
1469
|
+
this.logger.state('PASAPORTE_DETECTADO_SALTANDO_REVERSO', { classification: classification?.class });
|
|
1306
1470
|
this.completeProcess(true);
|
|
1307
1471
|
return;
|
|
1308
1472
|
}
|
|
@@ -1323,14 +1487,23 @@ const JaakStamps = class {
|
|
|
1323
1487
|
this.isDetectionPaused = false;
|
|
1324
1488
|
}, 3000);
|
|
1325
1489
|
}, 800);
|
|
1326
|
-
this.
|
|
1490
|
+
this.logger.state('CAPTURA_FRENTE_COMPLETADA', {
|
|
1491
|
+
captureStep: this.captureStep,
|
|
1492
|
+
hasFullFrame: !!this.capturedFullFrame,
|
|
1493
|
+
hasCroppedId: !!this.capturedCroppedId
|
|
1494
|
+
});
|
|
1327
1495
|
}
|
|
1328
1496
|
else if (this.captureStep === 'back') {
|
|
1329
1497
|
// Captura de la trasera usando canvas reutilizado
|
|
1330
1498
|
this.capturedBackFullFrame = this.captureCanvas.toDataURL('image/png');
|
|
1331
1499
|
this.capturedBackCroppedId = croppedCanvas.toDataURL('image/png');
|
|
1332
1500
|
this.completeProcess(false);
|
|
1333
|
-
this.
|
|
1501
|
+
this.logger.state('CAPTURA_TRASERA_COMPLETADA', {
|
|
1502
|
+
captureStep: this.captureStep,
|
|
1503
|
+
hasBackFullFrame: !!this.capturedBackFullFrame,
|
|
1504
|
+
hasBackCroppedId: !!this.capturedBackCroppedId,
|
|
1505
|
+
processCompleted: true
|
|
1506
|
+
});
|
|
1334
1507
|
}
|
|
1335
1508
|
}
|
|
1336
1509
|
triggerCaptureAnimation() {
|
|
@@ -1354,7 +1527,7 @@ const JaakStamps = class {
|
|
|
1354
1527
|
const ctx = this.canvasRef.getContext("2d");
|
|
1355
1528
|
ctx.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height);
|
|
1356
1529
|
}
|
|
1357
|
-
this.
|
|
1530
|
+
this.logger.state('DETECTOR_DETENIDO', { timestamp: Date.now() });
|
|
1358
1531
|
}
|
|
1359
1532
|
resetDetection() {
|
|
1360
1533
|
this.bestScore = 0;
|
|
@@ -1393,6 +1566,13 @@ const JaakStamps = class {
|
|
|
1393
1566
|
"Proceso completado (solo frente capturado)" :
|
|
1394
1567
|
"Proceso de captura completado exitosamente";
|
|
1395
1568
|
this.statusColor = "#28a745";
|
|
1569
|
+
this.logger.state('PROCESO_COMPLETADO', {
|
|
1570
|
+
skippedBack,
|
|
1571
|
+
hasFrontImages: !!(this.capturedFullFrame && this.capturedCroppedId),
|
|
1572
|
+
hasBackImages: !!(this.capturedBackFullFrame && this.capturedBackCroppedId),
|
|
1573
|
+
totalImages: skippedBack ? 2 : 4,
|
|
1574
|
+
timestamp: new Date().toISOString()
|
|
1575
|
+
});
|
|
1396
1576
|
// Detener el detector
|
|
1397
1577
|
this.stopDetection();
|
|
1398
1578
|
// Emitir evento con las imágenes capturadas
|
|
@@ -1444,7 +1624,7 @@ const JaakStamps = class {
|
|
|
1444
1624
|
this.cleanup();
|
|
1445
1625
|
}
|
|
1446
1626
|
render() {
|
|
1447
|
-
return (index.h("div", { key: '
|
|
1627
|
+
return (index.h("div", { key: '87e2e2065012b5792b52b18349490492b5bdc80c', class: "detector-container" }, index.h("div", { key: '04b8bba38297d39c84ddc01f5a9bf72c65b9bef4', class: "video-container" }, index.h("video", { key: '905b99e1670fccb2ff5555818f91d0b0241fa29d', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: this.isVideoActive ? 'block' : 'none' } }), index.h("canvas", { key: '3f219b649b8d4f961b15256b8586451c2a737eb8', ref: el => this.canvasRef = el, class: this.shouldMirrorVideo ? 'mirror' : '' }), this.isMaskReady && (index.h("div", { key: 'f8d6742689d4446897ca48c2407cb3d3fab643e9', class: "overlay-mask" }, index.h("div", { key: '630a06c530f168cc0b71286adbf48fd922eb710d', class: "card-outline" }, index.h("div", { key: 'ce8c043ad41d5574cd0c4d737dec08b9f7fee927', class: "side side-top" }), index.h("div", { key: 'e90ead592f84e5df98143bc88714e70f32684204', class: "side side-right" }), index.h("div", { key: '31d6778c5036e42a3addb26c732149abc5a18ef7', class: "side side-bottom" }), index.h("div", { key: 'f85c31e77f024f9070c706b06b91d62a7fdbc357', class: "side side-left" }), index.h("div", { key: '27b362711bc53019483c0d36742d97e10ae9b9ce', class: "corner corner-tl" }), index.h("div", { key: '03b55893610684d690987c2eacf3c4e5d0c3bbe5', class: "corner corner-tr" }), index.h("div", { key: 'b6bf31327925c45a7fa8e1fd5ab2f25b824a03a2', class: "corner corner-bl" }), index.h("div", { key: '0737e0c82f8ad9703ce2546f3e594db6d50cafde', class: "corner corner-br" }), !this.showFlipAnimation && !this.showSuccessAnimation && (index.h("div", { key: '145f8383c496e151bd6ef4f5841292adeba083c4', class: "guide-text" }, this.statusMessage))), this.captureStep === 'back' && !this.showFlipAnimation && !this.showSuccessAnimation && (index.h("button", { key: 'fcdedebc31eddd21b978dd63e93c348d324b47da', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), this.isVideoActive && (index.h("div", { key: 'dc9157bf7bed3b6439db742055201e2c4eddec84', class: "camera-controls" }, this.isMultipleCamerasAvailable && (index.h("button", { key: '6b052562ccb203dbf3cc8b627f31ed2435559f80', class: "flip-camera-button", onClick: () => this.flipCamera(), type: "button", title: "Cambiar c\u00E1mara" }, "Girar c\u00E1mara")), index.h("button", { key: 'f9fad1757d01f0cb45f65bb2088bd1f0bc0e4e8d', class: "camera-selector-button", onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara" }, "C\u00E1maras"), this.debug && (index.h("div", { key: '5362fb33508c7f903b09f65fdb449b608804260d', style: {
|
|
1448
1628
|
position: 'absolute',
|
|
1449
1629
|
top: '50px',
|
|
1450
1630
|
right: '0',
|
|
@@ -1454,10 +1634,10 @@ const JaakStamps = class {
|
|
|
1454
1634
|
fontSize: '10px',
|
|
1455
1635
|
borderRadius: '4px',
|
|
1456
1636
|
whiteSpace: 'nowrap'
|
|
1457
|
-
} }, "C\u00E1maras: ", this.availableCameras.length, index.h("br", { key: '
|
|
1637
|
+
} }, "C\u00E1maras: ", this.availableCameras.length, index.h("br", { key: '5ead451a54a59c885f62740d0a0ce43ba8b674e4' }), "M\u00FAltiples: ", this.isMultipleCamerasAvailable ? 'Sí' : 'No', index.h("br", { key: '9a92514d07576ed7052eaa3a418c00013ef7c479' }), "Selector: ", this.showCameraSelector ? 'Visible' : 'Oculto', index.h("br", { key: 'd06abebad3b2e3c19aa22e511e0c4cfd4425b8b2' }), "Video: ", this.isVideoActive ? 'Activo' : 'Inactivo')))), this.showCameraSelector && this.availableCameras.length > 0 && (index.h("div", { key: '93a09ce3bb108175b55944a71c21e86e58de55be', class: "camera-selector-dropdown" }, index.h("div", { key: '7ceb4c8826945ab2a9da106a88a44cbb5490e92a', class: "camera-selector-header" }, index.h("span", { key: 'fa98621700584d8021ff57eca6f804b6eb792c5b' }, "Seleccionar C\u00E1mara"), index.h("button", { key: 'ce6477a1494f58fb5974dd7c9e62bd7d041572c5', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), index.h("div", { key: 'eff226b006c95fafce2566947155e13ee68f9a02', class: "camera-list" }, this.availableCameras.map((camera) => (index.h("button", { key: camera.deviceId, class: `camera-option ${this.selectedCameraId === camera.deviceId ? 'selected' : ''}`, onClick: () => {
|
|
1458
1638
|
this.switchCamera(camera.deviceId);
|
|
1459
1639
|
this.toggleCameraSelector();
|
|
1460
|
-
}, type: "button" }, index.h("span", { class: "camera-label" }, camera.label || `Cámara ${this.availableCameras.indexOf(camera) + 1}`), this.selectedCameraId === camera.deviceId && (index.h("span", { class: "selected-indicator" }, "\u2713")))))), index.h("div", { key: '
|
|
1640
|
+
}, type: "button" }, index.h("span", { class: "camera-label" }, camera.label || `Cámara ${this.availableCameras.indexOf(camera) + 1}`), this.selectedCameraId === camera.deviceId && (index.h("span", { class: "selected-indicator" }, "\u2713")))))), index.h("div", { key: '617d33caa5d3b3e6dca56d479b27c0ac7ed19c2c', class: "device-info" }, index.h("small", { key: 'fba56ac1238c33864f8dba1d8bd9a5661e11d770' }, "Dispositivo: ", this.deviceType)))))), this.isCapturing && (index.h("div", { key: 'b46982a0b949ee9d50d0a819c59b24dceec9d7b2', class: "capture-animation" })), this.showFlipAnimation && (index.h("div", { key: 'c82773fffca8ec53949197a105e1e11bf0f9b294', class: "flip-animation" }, index.h("div", { key: 'ad52c9ec91132bf5ed94e36f621489a66b0bf680', class: "id-card-icon" }), index.h("div", { key: '2be407ee84beddc5ce968a9a94d9014f416cde54', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), this.showSuccessAnimation && (index.h("div", { key: 'f20b6be925178a123de99e535e893b7c09391dee', class: "success-animation" }, index.h("div", { key: 'd3ae65d40943f73bc92e9529764ded454adc5dbf', class: "check-icon" }), index.h("div", { key: 'f2b03082a106c69f09d384ba3b1cb4a636d3a189', class: "success-text" }, "\u00A1Proceso completado!"))), this.isLoading && (index.h("div", { key: '65736e303d9eb1c3f6f2dccb5cc0d27c571ac9c8', class: "loading-overlay" }, index.h("div", { key: '5863d855d1caea9202a9f3d0a29919985ddbb926', class: "loading-spinner" }), index.h("div", { key: 'aa5a16c96ac6bfa43846ba06346fad6dce39dfbb', class: "loading-text" }, this.statusMessage))), this.debug && (index.h("div", { key: '308c664b07d2c2427c38f766fc9eb78d27843f67', class: "status-bar" }, index.h("div", { key: '3884b311710d7f373a508eb492771e503e68f648', class: "status-message", style: { 'color': this.statusColor } }, this.statusMessage))), index.h("div", { key: '3125cfecda03d3ab9e80e0d9d5674f1cc167e2f8', class: "watermark" }, index.h("img", { key: '5ef43a18aea74f570db0d61f4fd86c3becf1d23e', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
|
|
1461
1641
|
}
|
|
1462
1642
|
};
|
|
1463
1643
|
JaakStamps.style = myComponentCss;
|