@jaak.ai/stamps 2.5.3 → 2.5.4-dev.2
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/{index-D6NBn_qu.js → index-ucw61xdq.js} +9 -2
- package/dist/cjs/{index-D6NBn_qu.js.map → index-ucw61xdq.js.map} +1 -1
- package/dist/cjs/jaak-stamps-webcomponent.cjs.js +1 -1
- package/dist/cjs/jaak-stamps.cjs.entry.js +295 -31
- package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
- package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/assets/powered-by-jaak.png +0 -0
- package/dist/collection/components/my-component/my-component.js +295 -13
- package/dist/collection/components/my-component/my-component.js.map +1 -1
- package/dist/collection/services/DetectionService.js +0 -18
- package/dist/collection/services/DetectionService.js.map +1 -1
- package/dist/components/jaak-stamps.js +295 -31
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/{index-BCfAsrzL.js → index-CqdAwiLj.js} +9 -3
- package/dist/esm/{index-BCfAsrzL.js.map → index-CqdAwiLj.js.map} +1 -1
- package/dist/esm/jaak-stamps-webcomponent.js +2 -2
- package/dist/esm/jaak-stamps.entry.js +295 -31
- package/dist/esm/jaak-stamps.entry.js.map +1 -1
- package/dist/esm/loader.js +2 -2
- 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-178aea65.entry.js +7 -0
- package/dist/jaak-stamps-webcomponent/p-178aea65.entry.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/p-CqdAwiLj.js +3 -0
- package/dist/jaak-stamps-webcomponent/{p-BCfAsrzL.js.map → p-CqdAwiLj.js.map} +1 -1
- package/dist/types/components/my-component/my-component.d.ts +10 -0
- package/package.json +1 -1
- package/dist/jaak-stamps-webcomponent/p-BCfAsrzL.js +0 -3
- package/dist/jaak-stamps-webcomponent/p-adece4d2.entry.js +0 -7
- package/dist/jaak-stamps-webcomponent/p-adece4d2.entry.js.map +0 -1
package/dist/cjs/loader.cjs.js
CHANGED
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { h } from "@stencil/core";
|
|
1
|
+
import { h, getAssetPath } from "@stencil/core";
|
|
2
2
|
import { ServiceContainer } from "../../services/ServiceContainer";
|
|
3
3
|
import { LicenseValidationService } from "../../services/LicenseValidationService";
|
|
4
4
|
export class JaakStamps {
|
|
@@ -124,6 +124,18 @@ export class JaakStamps {
|
|
|
124
124
|
processedFramesCount = 0; // Contador total de frames procesados
|
|
125
125
|
hasAutoSwitchedToManual = false;
|
|
126
126
|
_manualModeLoggedOnce = false;
|
|
127
|
+
VIDEO_DIAGNOSTIC_EVENTS = [
|
|
128
|
+
'loadstart',
|
|
129
|
+
'loadedmetadata',
|
|
130
|
+
'loadeddata',
|
|
131
|
+
'canplay',
|
|
132
|
+
'playing',
|
|
133
|
+
'pause',
|
|
134
|
+
'stalled',
|
|
135
|
+
'suspend',
|
|
136
|
+
'abort',
|
|
137
|
+
'emptied',
|
|
138
|
+
];
|
|
127
139
|
// Canvas pool for optimized screenshot capture
|
|
128
140
|
canvasPool = [];
|
|
129
141
|
MAX_CANVAS_POOL_SIZE = 3;
|
|
@@ -852,6 +864,130 @@ export class JaakStamps {
|
|
|
852
864
|
memoryMB: deviceMemory ? deviceMemory * 1024 : null
|
|
853
865
|
};
|
|
854
866
|
}
|
|
867
|
+
debugLog(message, details) {
|
|
868
|
+
if (!this.debug) {
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
if (typeof details === 'undefined') {
|
|
872
|
+
console.log(`[jaak-stamps][diag] ${message}`);
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
console.log(`[jaak-stamps][diag] ${message}`, details);
|
|
876
|
+
}
|
|
877
|
+
debugWarn(message, details) {
|
|
878
|
+
if (!this.debug) {
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
if (typeof details === 'undefined') {
|
|
882
|
+
console.warn(`[jaak-stamps][diag] ${message}`);
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
console.warn(`[jaak-stamps][diag] ${message}`, details);
|
|
886
|
+
}
|
|
887
|
+
summarizeId(id) {
|
|
888
|
+
if (!id) {
|
|
889
|
+
return null;
|
|
890
|
+
}
|
|
891
|
+
return id.length <= 8 ? id : `${id.slice(0, 8)}...`;
|
|
892
|
+
}
|
|
893
|
+
getCameraDevicesSnapshot() {
|
|
894
|
+
return this.cameraService.getAvailableCameras().map(camera => ({
|
|
895
|
+
label: camera.label || '(sin label)',
|
|
896
|
+
deviceId: this.summarizeId(camera.deviceId),
|
|
897
|
+
groupId: this.summarizeId(camera.groupId),
|
|
898
|
+
kind: camera.kind,
|
|
899
|
+
}));
|
|
900
|
+
}
|
|
901
|
+
sanitizeTrackSettings(settings) {
|
|
902
|
+
if (!settings) {
|
|
903
|
+
return null;
|
|
904
|
+
}
|
|
905
|
+
return {
|
|
906
|
+
...settings,
|
|
907
|
+
deviceId: this.summarizeId(settings.deviceId),
|
|
908
|
+
groupId: this.summarizeId(settings.groupId),
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
sanitizeTrackConstraints(track) {
|
|
912
|
+
if (!track) {
|
|
913
|
+
return null;
|
|
914
|
+
}
|
|
915
|
+
const constraints = track.getConstraints ? track.getConstraints() : {};
|
|
916
|
+
const sanitizedConstraints = { ...constraints };
|
|
917
|
+
if (typeof sanitizedConstraints.deviceId === 'string') {
|
|
918
|
+
sanitizedConstraints.deviceId = this.summarizeId(sanitizedConstraints.deviceId);
|
|
919
|
+
}
|
|
920
|
+
return sanitizedConstraints;
|
|
921
|
+
}
|
|
922
|
+
getStreamSnapshot(stream) {
|
|
923
|
+
if (!stream) {
|
|
924
|
+
return { hasStream: false };
|
|
925
|
+
}
|
|
926
|
+
const videoTrack = stream.getVideoTracks()[0];
|
|
927
|
+
if (!videoTrack) {
|
|
928
|
+
return {
|
|
929
|
+
hasStream: true,
|
|
930
|
+
streamActive: stream.active,
|
|
931
|
+
trackCount: stream.getTracks().length,
|
|
932
|
+
hasVideoTrack: false,
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
return {
|
|
936
|
+
hasStream: true,
|
|
937
|
+
streamActive: stream.active,
|
|
938
|
+
trackCount: stream.getTracks().length,
|
|
939
|
+
trackLabel: videoTrack.label || '(sin label)',
|
|
940
|
+
trackEnabled: videoTrack.enabled,
|
|
941
|
+
trackMuted: videoTrack.muted,
|
|
942
|
+
trackReadyState: videoTrack.readyState,
|
|
943
|
+
settings: this.sanitizeTrackSettings(videoTrack.getSettings ? videoTrack.getSettings() : undefined),
|
|
944
|
+
constraints: this.sanitizeTrackConstraints(videoTrack),
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
getVideoElementSnapshot() {
|
|
948
|
+
if (!this.videoRef) {
|
|
949
|
+
return { hasVideoRef: false };
|
|
950
|
+
}
|
|
951
|
+
const computedStyle = this.el.ownerDocument?.defaultView?.getComputedStyle(this.videoRef);
|
|
952
|
+
return {
|
|
953
|
+
hasVideoRef: true,
|
|
954
|
+
isConnected: this.videoRef.isConnected,
|
|
955
|
+
readyState: this.videoRef.readyState,
|
|
956
|
+
networkState: this.videoRef.networkState,
|
|
957
|
+
paused: this.videoRef.paused,
|
|
958
|
+
muted: this.videoRef.muted,
|
|
959
|
+
autoplay: this.videoRef.autoplay,
|
|
960
|
+
playsInline: this.videoRef.playsInline,
|
|
961
|
+
currentTime: Number.isFinite(this.videoRef.currentTime)
|
|
962
|
+
? Number(this.videoRef.currentTime.toFixed(3))
|
|
963
|
+
: this.videoRef.currentTime,
|
|
964
|
+
videoWidth: this.videoRef.videoWidth,
|
|
965
|
+
videoHeight: this.videoRef.videoHeight,
|
|
966
|
+
clientWidth: this.videoRef.clientWidth,
|
|
967
|
+
clientHeight: this.videoRef.clientHeight,
|
|
968
|
+
hasSrcObject: !!this.videoRef.srcObject,
|
|
969
|
+
display: computedStyle?.display ?? 'unknown',
|
|
970
|
+
visibility: computedStyle?.visibility ?? 'unknown',
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
attachVideoDiagnosticListeners() {
|
|
974
|
+
if (!this.debug || !this.videoRef) {
|
|
975
|
+
return () => undefined;
|
|
976
|
+
}
|
|
977
|
+
const video = this.videoRef;
|
|
978
|
+
const listeners = this.VIDEO_DIAGNOSTIC_EVENTS.map(eventName => {
|
|
979
|
+
const handler = () => {
|
|
980
|
+
this.debugLog(`video event "${eventName}"`, this.getVideoElementSnapshot());
|
|
981
|
+
};
|
|
982
|
+
video.addEventListener(eventName, handler);
|
|
983
|
+
return { eventName, handler };
|
|
984
|
+
});
|
|
985
|
+
return () => {
|
|
986
|
+
listeners.forEach(({ eventName, handler }) => {
|
|
987
|
+
video.removeEventListener(eventName, handler);
|
|
988
|
+
});
|
|
989
|
+
};
|
|
990
|
+
}
|
|
855
991
|
// DETECTION METHODS
|
|
856
992
|
async startDetection() {
|
|
857
993
|
try {
|
|
@@ -938,12 +1074,19 @@ export class JaakStamps {
|
|
|
938
1074
|
this.updateStatus('Configurando cámara...', 'Buscando dispositivos disponibles', 'loading');
|
|
939
1075
|
try {
|
|
940
1076
|
await this.cameraService.enumerateDevices();
|
|
1077
|
+
this.debugLog('step 2/5 enumerateDevices()', {
|
|
1078
|
+
cameras: this.getCameraDevicesSnapshot(),
|
|
1079
|
+
selectedCameraId: this.summarizeId(this.cameraService.getSelectedCameraId() || undefined),
|
|
1080
|
+
});
|
|
941
1081
|
}
|
|
942
1082
|
catch (enumerateError) {
|
|
943
1083
|
throw new Error(`Error al enumerar dispositivos: ${enumerateError.message}`);
|
|
944
1084
|
}
|
|
945
1085
|
try {
|
|
946
1086
|
await this.updateCameraInfoWithAutofocus();
|
|
1087
|
+
this.debugLog('step 2/5 updateCameraInfoWithAutofocus()', {
|
|
1088
|
+
cameraInfo: this.cameraInfoWithAutofocus,
|
|
1089
|
+
});
|
|
947
1090
|
}
|
|
948
1091
|
catch (cameraInfoError) {
|
|
949
1092
|
throw new Error(`Error al actualizar información de cámara: ${cameraInfoError.message}`);
|
|
@@ -953,6 +1096,10 @@ export class JaakStamps {
|
|
|
953
1096
|
let stream;
|
|
954
1097
|
try {
|
|
955
1098
|
stream = await this.cameraService.setupCamera();
|
|
1099
|
+
this.debugLog('step 3/5 setupCamera() resolved', {
|
|
1100
|
+
stream: this.getStreamSnapshot(stream),
|
|
1101
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1102
|
+
});
|
|
956
1103
|
}
|
|
957
1104
|
catch (setupError) {
|
|
958
1105
|
throw new Error(`Error al configurar cámara: ${setupError.message}`);
|
|
@@ -965,7 +1112,15 @@ export class JaakStamps {
|
|
|
965
1112
|
this.updateStatus('Captura activa', 'Posicione su documento y use el botón para capturar', 'active');
|
|
966
1113
|
}
|
|
967
1114
|
try {
|
|
1115
|
+
this.debugLog('step 4/5 initializeVideoStream() start', {
|
|
1116
|
+
stream: this.getStreamSnapshot(stream),
|
|
1117
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1118
|
+
});
|
|
968
1119
|
await this.initializeVideoStream(stream);
|
|
1120
|
+
this.debugLog('step 4/5 initializeVideoStream() completed', {
|
|
1121
|
+
stream: this.getStreamSnapshot(stream),
|
|
1122
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1123
|
+
});
|
|
969
1124
|
}
|
|
970
1125
|
catch (videoError) {
|
|
971
1126
|
throw new Error(`Error al inicializar video: ${videoError.message}`);
|
|
@@ -983,9 +1138,19 @@ export class JaakStamps {
|
|
|
983
1138
|
if (!this.useDocumentDetector) {
|
|
984
1139
|
this.showManualCaptureButton = true;
|
|
985
1140
|
}
|
|
1141
|
+
this.debugLog('step 5/5 capture loop ready', {
|
|
1142
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1143
|
+
stream: this.getStreamSnapshot(this.videoStream),
|
|
1144
|
+
useDocumentDetector: this.useDocumentDetector,
|
|
1145
|
+
});
|
|
986
1146
|
this.detectFrame();
|
|
987
1147
|
}
|
|
988
1148
|
catch (err) {
|
|
1149
|
+
this.debugWarn('startDetection() failed', {
|
|
1150
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1151
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1152
|
+
stream: this.getStreamSnapshot(this.videoStream),
|
|
1153
|
+
});
|
|
989
1154
|
console.error('[jaak-stamps] Error al preparar captura:', err);
|
|
990
1155
|
this.updateStatus('Error al iniciar', 'No se pudo preparar la captura', 'error');
|
|
991
1156
|
this.stateManager.updateCaptureState({ isLoading: false });
|
|
@@ -995,11 +1160,93 @@ export class JaakStamps {
|
|
|
995
1160
|
if (!this.videoRef) {
|
|
996
1161
|
throw new Error('Video element not available');
|
|
997
1162
|
}
|
|
1163
|
+
const detachVideoDiagnosticListeners = this.attachVideoDiagnosticListeners();
|
|
1164
|
+
this.debugLog('initializeVideoStream() pre-assign', {
|
|
1165
|
+
stream: this.getStreamSnapshot(stream),
|
|
1166
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1167
|
+
});
|
|
998
1168
|
this.videoRef.srcObject = stream;
|
|
999
1169
|
this.videoStream = stream;
|
|
1170
|
+
this.debugLog('initializeVideoStream() post-srcObject assignment', {
|
|
1171
|
+
stream: this.getStreamSnapshot(stream),
|
|
1172
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1173
|
+
});
|
|
1000
1174
|
const isRear = this.cameraService.isRearCamera(stream);
|
|
1001
1175
|
this.shouldMirrorVideo = !isRear;
|
|
1002
1176
|
const LOAD_METADATA_TIMEOUT_MS = 10000;
|
|
1177
|
+
// Diagnostic instrumentation: when the timeout fires we need enough
|
|
1178
|
+
// context to distinguish between "OS muted the track", "permission
|
|
1179
|
+
// revoked mid-flight", "device never produced frames" and other modes
|
|
1180
|
+
// that all surface as the same generic timeout error.
|
|
1181
|
+
const track = stream.getVideoTracks()[0];
|
|
1182
|
+
const waitStart = performance.now();
|
|
1183
|
+
const trackEvents = [];
|
|
1184
|
+
const recordTrackEvent = (event) => {
|
|
1185
|
+
trackEvents.push({
|
|
1186
|
+
at: Math.round(performance.now() - waitStart),
|
|
1187
|
+
event,
|
|
1188
|
+
state: track?.readyState,
|
|
1189
|
+
});
|
|
1190
|
+
};
|
|
1191
|
+
const onTrackMute = () => recordTrackEvent('mute');
|
|
1192
|
+
const onTrackUnmute = () => recordTrackEvent('unmute');
|
|
1193
|
+
const onTrackEnded = () => recordTrackEvent('ended');
|
|
1194
|
+
if (track) {
|
|
1195
|
+
track.addEventListener('mute', onTrackMute);
|
|
1196
|
+
track.addEventListener('unmute', onTrackUnmute);
|
|
1197
|
+
track.addEventListener('ended', onTrackEnded);
|
|
1198
|
+
}
|
|
1199
|
+
const cleanupTrackListeners = () => {
|
|
1200
|
+
if (!track)
|
|
1201
|
+
return;
|
|
1202
|
+
track.removeEventListener('mute', onTrackMute);
|
|
1203
|
+
track.removeEventListener('unmute', onTrackUnmute);
|
|
1204
|
+
track.removeEventListener('ended', onTrackEnded);
|
|
1205
|
+
};
|
|
1206
|
+
const captureDiagnostics = () => {
|
|
1207
|
+
const settings = track?.getSettings?.();
|
|
1208
|
+
const computed = this.videoRef ? getComputedStyle(this.videoRef) : null;
|
|
1209
|
+
return {
|
|
1210
|
+
reason: 'VIDEO_METADATA_TIMEOUT',
|
|
1211
|
+
waitedMs: Math.round(performance.now() - waitStart),
|
|
1212
|
+
stream: {
|
|
1213
|
+
videoTrackCount: stream.getVideoTracks().length,
|
|
1214
|
+
audioTrackCount: stream.getAudioTracks().length,
|
|
1215
|
+
},
|
|
1216
|
+
track: track ? {
|
|
1217
|
+
readyState: track.readyState,
|
|
1218
|
+
muted: track.muted,
|
|
1219
|
+
enabled: track.enabled,
|
|
1220
|
+
label: track.label,
|
|
1221
|
+
kind: track.kind,
|
|
1222
|
+
settings: settings ? {
|
|
1223
|
+
width: settings.width,
|
|
1224
|
+
height: settings.height,
|
|
1225
|
+
frameRate: settings.frameRate,
|
|
1226
|
+
deviceId: settings.deviceId,
|
|
1227
|
+
facingMode: settings.facingMode,
|
|
1228
|
+
} : null,
|
|
1229
|
+
} : null,
|
|
1230
|
+
video: this.videoRef ? {
|
|
1231
|
+
readyState: this.videoRef.readyState,
|
|
1232
|
+
networkState: this.videoRef.networkState,
|
|
1233
|
+
error: this.videoRef.error ? { code: this.videoRef.error.code, message: this.videoRef.error.message } : null,
|
|
1234
|
+
paused: this.videoRef.paused,
|
|
1235
|
+
offsetWidth: this.videoRef.offsetWidth,
|
|
1236
|
+
offsetHeight: this.videoRef.offsetHeight,
|
|
1237
|
+
videoWidth: this.videoRef.videoWidth,
|
|
1238
|
+
videoHeight: this.videoRef.videoHeight,
|
|
1239
|
+
display: computed?.display,
|
|
1240
|
+
visibility: computed?.visibility,
|
|
1241
|
+
} : null,
|
|
1242
|
+
document: {
|
|
1243
|
+
visibilityState: document.visibilityState,
|
|
1244
|
+
hasFocus: document.hasFocus(),
|
|
1245
|
+
},
|
|
1246
|
+
trackEvents,
|
|
1247
|
+
userAgent: navigator.userAgent,
|
|
1248
|
+
};
|
|
1249
|
+
};
|
|
1003
1250
|
const finalizeStreamInitialization = async () => {
|
|
1004
1251
|
try {
|
|
1005
1252
|
await this.videoRef.play();
|
|
@@ -1014,24 +1261,39 @@ export class JaakStamps {
|
|
|
1014
1261
|
const rect = container.getBoundingClientRect();
|
|
1015
1262
|
this.updateMaskDimensions(rect);
|
|
1016
1263
|
}
|
|
1264
|
+
this.debugLog('initializeVideoStream() finalized after play()', {
|
|
1265
|
+
stream: this.getStreamSnapshot(stream),
|
|
1266
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1267
|
+
});
|
|
1017
1268
|
};
|
|
1018
1269
|
// If metadata is already available (readyState >= HAVE_METADATA = 1),
|
|
1019
1270
|
// the 'loadedmetadata' event will not fire again. Handle both cases.
|
|
1020
1271
|
if (this.videoRef.readyState >= 1) {
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
}
|
|
1272
|
+
this.debugLog('video metadata already available, skipping event wait', this.getVideoElementSnapshot());
|
|
1273
|
+
cleanupTrackListeners();
|
|
1024
1274
|
await finalizeStreamInitialization();
|
|
1275
|
+
detachVideoDiagnosticListeners();
|
|
1025
1276
|
return;
|
|
1026
1277
|
}
|
|
1027
1278
|
return new Promise((resolve, reject) => {
|
|
1028
1279
|
let settled = false;
|
|
1280
|
+
const cleanup = () => {
|
|
1281
|
+
this.videoRef.onloadedmetadata = null;
|
|
1282
|
+
this.videoRef.onerror = null;
|
|
1283
|
+
detachVideoDiagnosticListeners();
|
|
1284
|
+
};
|
|
1029
1285
|
const timeoutId = setTimeout(() => {
|
|
1030
1286
|
if (settled)
|
|
1031
1287
|
return;
|
|
1032
1288
|
settled = true;
|
|
1033
|
-
|
|
1034
|
-
this.
|
|
1289
|
+
const diagnostics = captureDiagnostics();
|
|
1290
|
+
this.debugWarn(`initializeVideoStream() timeout after ${LOAD_METADATA_TIMEOUT_MS}ms`, {
|
|
1291
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1292
|
+
stream: this.getStreamSnapshot(stream),
|
|
1293
|
+
});
|
|
1294
|
+
console.error('[jaak-stamps] Video metadata timeout diagnostics (json):', JSON.stringify(diagnostics));
|
|
1295
|
+
cleanup();
|
|
1296
|
+
cleanupTrackListeners();
|
|
1035
1297
|
reject(new Error(`Video metadata load timeout after ${LOAD_METADATA_TIMEOUT_MS}ms`));
|
|
1036
1298
|
}, LOAD_METADATA_TIMEOUT_MS);
|
|
1037
1299
|
this.videoRef.onloadedmetadata = async () => {
|
|
@@ -1039,13 +1301,18 @@ export class JaakStamps {
|
|
|
1039
1301
|
return;
|
|
1040
1302
|
settled = true;
|
|
1041
1303
|
clearTimeout(timeoutId);
|
|
1042
|
-
this.
|
|
1043
|
-
|
|
1304
|
+
this.debugLog('initializeVideoStream() onloadedmetadata fired', {
|
|
1305
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1306
|
+
stream: this.getStreamSnapshot(stream),
|
|
1307
|
+
});
|
|
1308
|
+
cleanupTrackListeners();
|
|
1044
1309
|
try {
|
|
1045
1310
|
await finalizeStreamInitialization();
|
|
1311
|
+
cleanup();
|
|
1046
1312
|
resolve();
|
|
1047
1313
|
}
|
|
1048
1314
|
catch (err) {
|
|
1315
|
+
cleanup();
|
|
1049
1316
|
reject(err);
|
|
1050
1317
|
}
|
|
1051
1318
|
};
|
|
@@ -1054,8 +1321,13 @@ export class JaakStamps {
|
|
|
1054
1321
|
return;
|
|
1055
1322
|
settled = true;
|
|
1056
1323
|
clearTimeout(timeoutId);
|
|
1057
|
-
this.
|
|
1058
|
-
|
|
1324
|
+
this.debugWarn('initializeVideoStream() video element emitted error', {
|
|
1325
|
+
event,
|
|
1326
|
+
videoRef: this.getVideoElementSnapshot(),
|
|
1327
|
+
stream: this.getStreamSnapshot(stream),
|
|
1328
|
+
});
|
|
1329
|
+
cleanup();
|
|
1330
|
+
cleanupTrackListeners();
|
|
1059
1331
|
reject(new Error(`Video element error: ${event}`));
|
|
1060
1332
|
};
|
|
1061
1333
|
});
|
|
@@ -1281,7 +1553,16 @@ export class JaakStamps {
|
|
|
1281
1553
|
isCapturing: false
|
|
1282
1554
|
};
|
|
1283
1555
|
const cameraInfo = this.cameraInfoWithAutofocus;
|
|
1284
|
-
return (h("div", { key: '
|
|
1556
|
+
return (h("div", { key: '20689d87a0b2f3ec851837a57f97b4bb79ecf10a', class: "detector-container" }, !this.licenseValid && this.licenseError && (h("div", { key: '3dccc3f6fd3ed0db2c2e7034d5cb0940625bade1', class: "license-error-container" }, h("div", { key: '5f39d0762dc5fea0f5d5402cd61f696090e96865', class: "license-error-card" }, h("svg", { key: '34d8290684decfe194328eba1b4af1b582f02518', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { key: '2cc8b54522b550f127c1b05a6f8069b78156f84a', d: "M12 22C12 22 20 18 20 12V5L12 2L4 5V12C4 18 12 22 12 22Z", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }), h("path", { key: 'b3c7918292661cfc92fbc0d3ec237acb80364fa5', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), h("circle", { key: '86a258f69cdf26588436cba2056bdf7c92d08244', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), h("h2", { key: '06e4fbde528663e485ae9a3b04945e6c95595ab2', class: "license-error-title" }, "Licencia Requerida"), h("p", { key: '7466b075c8cf31d67535512e4bdaa1473e89ed47', class: "license-error-message" }, this.licenseError), h("p", { key: 'ba4d06029ef7e896e51ad5c6e2dd72a9a162ef08', class: "license-error-help" }, "Contacte a soporte: ", h("a", { key: '177832433d66cf581743d8774a055405fa1f83fc', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), h("div", { key: 'ce1b33ae5289689c3e07cbb2a68f4411aa3ed2d2', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (h("div", { key: '394ee2b3c487c9673c1df3b483900720beb42ea5', class: "video-container" }, h("video", { key: '50ba3fb80f05ed35bdc58f9d75538d083cd7af32', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: {
|
|
1557
|
+
// Keep the element rendered (display: block) so the browser
|
|
1558
|
+
// loads stream metadata and fires 'loadedmetadata'. Hiding it
|
|
1559
|
+
// with display:none prevents metadata loading in Chrome and
|
|
1560
|
+
// causes initializeVideoStream to hang waiting for the event.
|
|
1561
|
+
// Use opacity + visibility to hide visually while keeping the
|
|
1562
|
+
// render context alive.
|
|
1563
|
+
opacity: captureState.isVideoActive ? '1' : '0',
|
|
1564
|
+
visibility: captureState.isVideoActive ? 'visible' : 'hidden',
|
|
1565
|
+
} }), h("div", { key: 'a4ff51674115afeeb2c36aedbbbdf3769bf0af96', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
|
|
1285
1566
|
position: 'absolute',
|
|
1286
1567
|
left: `${box.x}px`,
|
|
1287
1568
|
top: `${box.y}px`,
|
|
@@ -1290,9 +1571,9 @@ export class JaakStamps {
|
|
|
1290
1571
|
border: '2px solid #32406C',
|
|
1291
1572
|
pointerEvents: 'none',
|
|
1292
1573
|
boxSizing: 'border-box'
|
|
1293
|
-
} })))), this.isMaskReady && (h("div", { key: '
|
|
1574
|
+
} })))), this.isMaskReady && (h("div", { key: '6c4e710e25971692bd933486f05a231b56150e5a', class: "overlay-mask" }, h("div", { key: 'd7ec408535cd68a5a9c12e51061f3fd61745b566', class: "card-outline" }, h("div", { key: '0e4c6066cf35cdb13843e54500db8e94603203fa', class: "side side-top" }), h("div", { key: '0c61ebf0940a01b09d509675d021051ac433ba1b', class: "side side-right" }), h("div", { key: 'e1c113fa666ba1ab0b77bac98ac4b08d99bea3af', class: "side side-bottom" }), h("div", { key: '666527c49665fe1d9d04a5d3620686b7471b8d44', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '71eae3c5e89eeaffd95bc32d7ed9139a5b741cc6', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'b4d6abc22c58eabd5afb6f440701f5b909bf949e', class: "back-capture-section" }, h("div", { key: '6d4bf99ff92829efb64d6dbc7d2d14c16b7c691c', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (h("button", { key: 'f8965079e936e32722b5eb1f8dfb63a84160aa5d', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (h("span", { key: '7defab9f244899e188659fd07bf114897737bd48', class: "button-spinner" })), "Capturar Reverso")), h("button", { key: 'd5a501876ce24f25d21df5e8d47183e80be602f3', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (h("span", { key: '54e08bed19e50abdd5f5faf9e0a21d8c2cb6a368', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
|
|
1294
1575
|
? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
|
|
1295
|
-
: 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: '
|
|
1576
|
+
: 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: '85998cae72d19792d41f94b3fa08fd7054e25c5e', class: "camera-controls" }, h("button", { key: 'fe0471dad8bdc5b45327da52af8b47f94fe2531a', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: 'de26a8eda76aeec8e7095f793750b2336e2ff6c6', class: "camera-selector-dropdown" }, h("div", { key: '9b4085d7be39ab227a33d02b55dd46e96a68d330', class: "camera-selector-header" }, h("span", { key: '84104fb85d91ccd258c78365cad2e66b62d787b0' }, "Seleccionar C\u00E1mara"), h("button", { key: 'ad1d2b52e64ab8f0028e2cb083f495c2b432c054', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: 'e9f56e92ed01afac36ad0986dc78bfc816e60520', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '6fa215b5f99d33272cd96a27b2295c95113bc257', class: "device-info" }, h("small", { key: 'f8399e02a4f2a288c09df9065e138ab8def9be5f' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '4a169ae520fd5ca67716f0fe190889ace448044e', class: "manual-capture-section" }, h("button", { key: '7d7808f0d1017f6eb4c701a8582152905a228e85', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (h("span", { key: '89ee5a34898a8ba78777177001fa4406531dac3e', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (h("div", { key: '0711e1cb5619acbade20f63f6d46bdfdf827ed12', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '720c0b1dcdb85646b4973ae15abeaef0f3a91a95', class: "flip-animation" }, h("div", { key: 'a31a9500ee6f2f35f762e2f5135219ed869c6188', class: "id-card-icon" }), h("div", { key: '7237f4284d4a5b8fb471d8a568a9c3dd2eae6409', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: '94a28257187330f5aaca2302840300460f288f71', class: "success-animation" }, h("div", { key: 'ef9d9072507faac3ae29c31b87c9439f67576c14', class: "check-icon" }), h("div", { key: '7f1c077a2b3b67ebba5d12c9b69ff943b74936e9', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: 'b9cae83d9d9717728a27bd969293fe28702befe3', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '59382426b18de9f04dcfb179acd9a49b68af45ed', class: "status-spinner" })), h("div", { key: 'baa1972a55d439a95b3f91f38f91d9f35eecd7bd', class: "status-content" }, h("div", { key: '3fac24107d04a2b0abcbe6a3a0bff6d395c096b6', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '196c12a4fc3e8f213b17bdd366da9e61c594a0b1', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: 'd5c36522d3bd46f434b19e8323a30f441d69c67c', class: "performance-monitor" }, h("div", { key: 'ccc8ae6b27be8d5d89e2722319cfc66a92c3a32f', class: "performance-expanded" }, h("div", { key: 'd7bed7384567663fafe4fa49dd24da4bdd05c9a3', class: "metrics-row" }, h("div", { key: 'a4409744d7d9e8a6288caf077ba5ebdc6aaa5371', class: "metric-compact" }, h("span", { key: '939e03d6aa0138c2b0c1cce16bebf158b9b74bd6', class: "metric-label" }, "FPS"), h("span", { key: '76c20f96b11725d41493b627e7a6b0fb0d594d60', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: 'fafe6b165149f1f590a0b7e26b4001b09a5c70c5', class: "metric-compact" }, h("span", { key: 'a7e99f9c05aced0cb951297ce3a6011500445421', class: "metric-label" }, "MEM"), h("span", { key: '68bd733671a9664c4533e0b24b04ad0422053f77', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: 'a53f1ac37527de249425529aff022858c8d924c5', class: "metrics-row" }, h("div", { key: '2213e3646b22056999d29107bb32e43c61dd202f', class: "metric-compact" }, h("span", { key: '31d84002498094f88f71858a91828f42b7157d23', class: "metric-label" }, "INF"), h("span", { key: 'f0ed4e90a338a05bd5193992e7f004df9d31239a', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '1288cf2f5a119f146886c08f8b7f036425ead78e', class: "metric-compact" }, h("span", { key: 'db75cca343f7c6ea588e9b62da04fc5d444604a6', class: "metric-label" }, "FRAME"), h("span", { key: '40aee793f30a9cf175be6372981ce7b7be82ed07', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: 'd193a9b4c56c6a712213a779dbc6ee161b82e828', class: "metrics-row" }, h("div", { key: '89d060083973e1931232aac0d0c0f813b8aab7ef', class: "metric-compact" }, h("span", { key: '35808d7a448e3f4c6dc27b2b325adf628b9aee16', class: "metric-label" }, "DET"), h("span", { key: 'b60da4f5a4d56e738a65fd0bc480626d4839a048', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: 'da779be083f58be8e914d062379b565fdbf7333d', class: "metric-compact" }, h("span", { key: '44645db15818eab212bc5b966213dda67f461d14', class: "metric-label" }, "RATE"), h("span", { key: '39209bdf5a5fa7c74718492218ff4fa404e94879', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: 'bb0fb66ffefa86eb6e4b72215acb930c81cb6b01', class: "watermark" }, h("img", { key: '93a1812ab9a1c91c4a81cdc939ef8410170dd6b9', src: "https://static.jaak.ai/commons/powered-by-jaak.png", alt: "Powered by Jaak", onError: (e) => { e.target.src = getAssetPath('/assets/powered-by-jaak.png'); } }))))));
|
|
1296
1577
|
}
|
|
1297
1578
|
// Utility methods
|
|
1298
1579
|
updateDetectionBoxes(boxes) {
|
|
@@ -2120,6 +2401,7 @@ export class JaakStamps {
|
|
|
2120
2401
|
"$": ["my-component.css"]
|
|
2121
2402
|
};
|
|
2122
2403
|
}
|
|
2404
|
+
static get assetsDirs() { return ["../../assets"]; }
|
|
2123
2405
|
static get properties() {
|
|
2124
2406
|
return {
|
|
2125
2407
|
"debug": {
|