@ekyc_qoobiss/qbs-ect-cmp 4.7.24 → 4.7.25

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.
@@ -80,88 +80,93 @@ export class IdAutoCapture {
80
80
  // Method for continuous video frame processing with OpenCV
81
81
  this.processVideoFrame = () => {
82
82
  if (this.videoElement && this.processingCanvasElement && this.opencvReady && this.isDetecting) {
83
- console.log('Processing frame. cv.Mat is a constructor:', typeof cv.Mat === 'function');
84
- const video = this.videoElement;
85
- const processingCanvas = this.processingCanvasElement;
86
- const context = processingCanvas.getContext('2d');
87
- processingCanvas.width = video.videoWidth;
88
- processingCanvas.height = video.videoHeight;
89
- context.drawImage(video, 0, 0, processingCanvas.width, processingCanvas.height);
90
- const imageData = context.getImageData(0, 0, processingCanvas.width, processingCanvas.height);
91
- // --- OpenCV.js processing starts here ---
92
- let src = new cv.Mat(processingCanvas.height, processingCanvas.width, cv.CV_8UC4);
93
- src.data.set(imageData.data);
94
- let gray = new cv.Mat();
95
- let blurred = new cv.Mat();
96
- let edges = new cv.Mat();
97
- let contours = new cv.MatVector();
98
- let hierarchy = new cv.Mat();
99
83
  try {
100
- cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
101
- cv.GaussianBlur(gray, blurred, new cv.Size(5, 5), 0, 0, cv.BORDER_DEFAULT);
102
- cv.Canny(blurred, edges, 75, 200, 3, false);
103
- cv.findContours(edges, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);
104
- let idDetected = false;
105
- let maxArea = 0;
106
- //let bestRect = null;
107
- for (let i = 0; i < contours.size(); ++i) {
108
- let contour = contours.get(i);
109
- let area = cv.contourArea(contour);
110
- if (area > 1000 && area > maxArea) {
111
- let peri = cv.arcLength(contour, true);
112
- let approx = new cv.Mat();
113
- cv.approxPolyDP(contour, approx, 0.02 * peri, true);
114
- if (approx.rows === 4) {
115
- let rect = cv.boundingRect(approx);
116
- const aspectRatio = rect.width / rect.height;
117
- if (aspectRatio > 1.4 && aspectRatio < 1.8) {
118
- if (rect.width > video.videoWidth * 0.3 && rect.height > video.videoHeight * 0.3) {
119
- idDetected = true;
120
- maxArea = area;
121
- //bestRect = rect;
84
+ console.log('Processing frame. cv.Mat is a constructor:', typeof cv.Mat === 'function');
85
+ const video = this.videoElement;
86
+ const processingCanvas = this.processingCanvasElement;
87
+ const context = processingCanvas.getContext('2d');
88
+ processingCanvas.width = video.videoWidth;
89
+ processingCanvas.height = video.videoHeight;
90
+ context.drawImage(video, 0, 0, processingCanvas.width, processingCanvas.height);
91
+ const imageData = context.getImageData(0, 0, processingCanvas.width, processingCanvas.height);
92
+ // --- OpenCV.js processing starts here ---
93
+ let src = new cv.Mat(processingCanvas.height, processingCanvas.width, cv.CV_8UC4);
94
+ src.data.set(imageData.data);
95
+ let gray = new cv.Mat();
96
+ let blurred = new cv.Mat();
97
+ let edges = new cv.Mat();
98
+ let contours = new cv.MatVector();
99
+ let hierarchy = new cv.Mat();
100
+ try {
101
+ cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
102
+ cv.GaussianBlur(gray, blurred, new cv.Size(5, 5), 0, 0, cv.BORDER_DEFAULT);
103
+ cv.Canny(blurred, edges, 75, 200, 3, false);
104
+ cv.findContours(edges, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);
105
+ let idDetected = false;
106
+ let maxArea = 0;
107
+ //let bestRect = null;
108
+ for (let i = 0; i < contours.size(); ++i) {
109
+ let contour = contours.get(i);
110
+ let area = cv.contourArea(contour);
111
+ if (area > 1000 && area > maxArea) {
112
+ let peri = cv.arcLength(contour, true);
113
+ let approx = new cv.Mat();
114
+ cv.approxPolyDP(contour, approx, 0.02 * peri, true);
115
+ if (approx.rows === 4) {
116
+ let rect = cv.boundingRect(approx);
117
+ const aspectRatio = rect.width / rect.height;
118
+ if (aspectRatio > 1.4 && aspectRatio < 1.8) {
119
+ if (rect.width > video.videoWidth * 0.3 && rect.height > video.videoHeight * 0.3) {
120
+ idDetected = true;
121
+ maxArea = area;
122
+ //bestRect = rect;
123
+ }
122
124
  }
123
125
  }
126
+ approx.delete();
127
+ }
128
+ contour.delete();
129
+ }
130
+ if (idDetected) {
131
+ console.log('ID document detected! Starting countdown...');
132
+ this.countdown = 3;
133
+ if (this.animationFrameId !== null) {
134
+ cancelAnimationFrame(this.animationFrameId); // Stop continuous frame processing
135
+ this.animationFrameId = null;
124
136
  }
125
- approx.delete();
137
+ const timer = setInterval(() => {
138
+ this.countdown--;
139
+ if (this.countdown <= 0) {
140
+ clearInterval(timer);
141
+ this.capture();
142
+ this.stopRecording();
143
+ this.isDetecting = false;
144
+ console.log('Picture taken. You can now stop recording.');
145
+ this.countdown = 0; // Ensure countdown is 0
146
+ }
147
+ }, 1000);
126
148
  }
127
- contour.delete();
128
149
  }
129
- if (idDetected) {
130
- console.log('ID document detected! Starting countdown...');
131
- this.countdown = 3;
150
+ catch (error) {
151
+ console.error('OpenCV processing error:', error);
152
+ this.isDetecting = false; // Stop detection on error
132
153
  if (this.animationFrameId !== null) {
133
- cancelAnimationFrame(this.animationFrameId); // Stop continuous frame processing
154
+ cancelAnimationFrame(this.animationFrameId);
134
155
  this.animationFrameId = null;
135
156
  }
136
- const timer = setInterval(() => {
137
- this.countdown--;
138
- if (this.countdown <= 0) {
139
- clearInterval(timer);
140
- this.capture();
141
- this.stopRecording();
142
- this.isDetecting = false;
143
- console.log('Picture taken. You can now stop recording.');
144
- this.countdown = 0; // Ensure countdown is 0
145
- }
146
- }, 1000);
147
157
  }
148
- }
149
- catch (error) {
150
- console.error('OpenCV processing error:', error);
151
- this.isDetecting = false; // Stop detection on error
152
- if (this.animationFrameId !== null) {
153
- cancelAnimationFrame(this.animationFrameId);
154
- this.animationFrameId = null;
158
+ finally {
159
+ // Crucial: Release memory allocated by OpenCV Mat objects
160
+ src.delete();
161
+ gray.delete();
162
+ blurred.delete();
163
+ edges.delete();
164
+ contours.delete();
165
+ hierarchy.delete();
155
166
  }
156
167
  }
157
- finally {
158
- // Crucial: Release memory allocated by OpenCV Mat objects
159
- src.delete();
160
- gray.delete();
161
- blurred.delete();
162
- edges.delete();
163
- contours.delete();
164
- hierarchy.delete();
168
+ catch (error) {
169
+ console.error('Error processing video frame with OpenCV:', error);
165
170
  }
166
171
  // --- OpenCV.js processing ends here ---
167
172
  }
@@ -279,7 +284,7 @@ export class IdAutoCapture {
279
284
  if (store.device.isDesktop) {
280
285
  cameraVideoClass = 'cameraVideoSelfieDesk';
281
286
  }
282
- return (h("div", { key: '0b0333b5c7b20a216319cf081a9f49111012596e', class: "container flex center" }, h("div", { key: 'e7980ea76bddf47ac73f865b3c4cb609d4597cbd', class: "px-2 w-100" }, h("h1", { key: 'd5a97b44269a80d3a3cee564ff48cf543d3bfc04', class: this.titleStyle, innerHTML: this.titleMesage }), h("div", { key: 'e52e5f59f446be42bba3ae25377fbbe7e2b87d87', hidden: this.verified }, h("div", { key: 'f680400952063d743350a607e2f503bc57fdcdff', class: "w-100 h-100 rounded" }, h("div", { key: '237debd548236f0a12c71ac73b61ff420bd91203', class: "camera rounded" }, h("video", { key: 'db25e8012fc4639d785a175a449ac4ec5130d113', id: "video", loop: true, autoplay: true, playsinline: true, muted: true, class: cameraVideoClass, ref: el => (this.videoElement = el) }), h("canvas", { key: 'd2c08faa9f71bf7c8b5f161fd76d49a99960a73e', id: "output", ref: el => (this.canvasElement = el), style: { display: 'none' } }), h("canvas", { key: '1882ca42f1716dd6573e28ffb289958000d8e23a', id: "processingCanvasElement", ref: el => (this.processingCanvasElement = el), style: { display: 'none' } }), h("div", { key: 'ed29e8ff7706909244dfc6ef8ef2a3529e010628', class: "id-guide-rectangle" }), this.isCapturing && h("div", { key: '4df9ad4556cd2d57b0a5e18d0fe18b10b61cd55b', class: "capture-flash-overlay" }), this.countdown > 0 && (h("div", { key: 'c06a98f7a785bdefeba161a39a701eb7257a90d6', class: "absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center" }, h("span", { key: '63407cf0373b92248eef073d863b12536c6f9cfc', class: "text-white text-9xl font-bold animate-bounce" }, this.countdown)))))), h("div", { key: '047ebeeb0b61d05f95f51b23e48a14eed82dbb31', class: "footer text-center" }, h("img", { key: 'deeea20a5acf6618ee24fbfa6919b8a5a38bb1d0', src: logoOntrace })))));
287
+ return (h("div", { key: 'deb2d35a50823fa5c222c6049a4119a371194870', class: "container flex center" }, h("div", { key: '449a0fef911f14d3611a1d7e83ed1bfc02c0553f', class: "px-2 w-100" }, h("h1", { key: '8d9f8b3684e58ba57f4ec0467efa0d9af62c5a98', class: this.titleStyle, innerHTML: this.titleMesage }), h("div", { key: '701aeecc148bdd00ef9cd38b165f0628adfe827c', hidden: this.verified }, h("div", { key: 'cbe89cf4ddc15c46b595929ecaf4fb8cc20136b5', class: "w-100 h-100 rounded" }, h("div", { key: '78f52a0a77c3dd8218115253bbcb79ee0a9a6d4b', class: "camera rounded" }, h("video", { key: '6ee76764205ce855fedd7b8c86be4394b2cad7bb', id: "video", loop: true, autoplay: true, playsinline: true, muted: true, class: cameraVideoClass, ref: el => (this.videoElement = el) }), h("canvas", { key: '5574b79a997d3ca06afa99faa61cb9bace755e91', id: "output", ref: el => (this.canvasElement = el), style: { display: 'none' } }), h("canvas", { key: 'e25df7ef70206d5544adade008cd612f1fee550a', id: "processingCanvasElement", ref: el => (this.processingCanvasElement = el), style: { display: 'none' } }), h("div", { key: '8ac6db08f2d1e44d04f2827f29e08787b853812e', class: "id-guide-rectangle" }), this.isCapturing && h("div", { key: '900ddcc0d2bf371d7ad4e593eaf0e9b60b6d2810', class: "capture-flash-overlay" }), this.countdown > 0 && (h("div", { key: 'd5f05c1b3dcbd02977462c6b9d816c2835698c2f', class: "absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center" }, h("span", { key: '7b85d36f1b609360c8214a29e220f6f80effffca', class: "text-white text-9xl font-bold animate-bounce" }, this.countdown)))))), h("div", { key: '9b653ebb92ce731ddb235d85db4a7fa99aaa4c64', class: "footer text-center" }, h("img", { key: 'f085d8f1698e66448cf749ec4cc45b496fbd55a1', src: logoOntrace })))));
283
288
  }
284
289
  static get is() { return "id-auto-capture"; }
285
290
  static get originalStyleUrls() {
@@ -1 +1 @@
1
- {"version":3,"file":"id-auto-capture.js","sourceRoot":"","sources":["../../../../../src/components/common/id-auto-capture/id-auto-capture.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, h, Element, Event, EventEmitter, State } from '@stencil/core';\r\n\r\nimport logoOntrace from '../../../assets/logo-ontrace.svg';\r\nimport store from '../../../helpers/store';\r\nimport { Cameras } from '../../../helpers/Cameras';\r\nimport { Browser, MobileOS } from '../../../models/IDevice';\r\n\r\ndeclare const cv: any;\r\n\r\n@Component({\r\n tag: 'id-auto-capture',\r\n styleUrl: 'id-auto-capture.css',\r\n shadow: false,\r\n})\r\nexport class IdAutoCapture {\r\n @Element() el: HTMLElement;\r\n private videoElement: HTMLVideoElement;\r\n private canvasElement: HTMLCanvasElement;\r\n private processingCanvasElement: HTMLCanvasElement; // For OpenCV frame processing\r\n private mediaRecorder: MediaRecorder | null = null;\r\n private mediaStream: MediaStream | null = null;\r\n private animationFrameId: number | null = null; // To manage requestAnimationFrame\r\n private opencvScriptElement: HTMLScriptElement | null = null;\r\n\r\n @State() private verified: boolean;\r\n @State() private titleMesage: string;\r\n @State() private titleStyle: string;\r\n @State() recordedChunks: Blob[] = [];\r\n @State() countdown: number = 0;\r\n @State() capturedImage: string | null = null;\r\n @State() isRecording: boolean = false;\r\n @State() recordedVideoUrl: string | null = null;\r\n @State() isDetecting: boolean = false;\r\n @State() opencvReady: boolean = false;\r\n @State() isCapturing: boolean = false;\r\n\r\n @Event({\r\n eventName: 'photoIdCapture',\r\n })\r\n eventPhotoCapture: EventEmitter;\r\n\r\n @Event({\r\n eventName: 'recordingIdCapture',\r\n })\r\n eventRecordingIdReady: EventEmitter;\r\n\r\n constructor() {\r\n this.verified = false;\r\n }\r\n\r\n // Lifecycle method: Called once after the component is first connected to the DOM\r\n async componentWillLoad() {\r\n // Initialize DOM element references after the component's render method\r\n // has placed them in the DOM. This should ideally be done in componentDidLoad\r\n // but can be set up to ensure elements are available for setup.\r\n }\r\n\r\n // Lifecycle method: Called once after the component has loaded and rendered\r\n async componentDidLoad() {\r\n console.log('Loading OpenCV.js...');\r\n this.loadOpenCVScript();\r\n\r\n // Listen for the custom event dispatched by global.ts (ensures global.ts sets up window.Module)\r\n document.addEventListener('opencv:ready', this.handleOpencvReady);\r\n }\r\n\r\n disconnectedCallback() {\r\n if (this.mediaStream) {\r\n this.mediaStream.getTracks().forEach(track => track.stop());\r\n }\r\n if (this.animationFrameId !== null) {\r\n cancelAnimationFrame(this.animationFrameId);\r\n this.animationFrameId = null;\r\n }\r\n if (this.recordedVideoUrl) {\r\n URL.revokeObjectURL(this.recordedVideoUrl);\r\n }\r\n document.removeEventListener('opencv:ready', this.handleOpencvReady);\r\n\r\n // NEW: Clean up the dynamically added script element\r\n if (this.opencvScriptElement && this.opencvScriptElement.parentNode) {\r\n this.opencvScriptElement.parentNode.removeChild(this.opencvScriptElement);\r\n this.opencvScriptElement = null;\r\n }\r\n }\r\n\r\n private loadOpenCVScript() {\r\n if (!document.querySelector('script[src=\"https://docs.opencv.org/4.x/opencv.js\"]')) {\r\n // Only load if not already loaded\r\n this.opencvScriptElement = document.createElement('script');\r\n this.opencvScriptElement.type = 'text/javascript';\r\n this.opencvScriptElement.async = true;\r\n this.opencvScriptElement.src = 'https://docs.opencv.org/4.x/opencv.js';\r\n document.body.appendChild(this.opencvScriptElement); // Append to body or head\r\n console.log('Dynamically loaded opencv.js');\r\n } else {\r\n console.log('OpenCV.js script already present in the DOM.');\r\n }\r\n }\r\n\r\n private handleOpencvReady = async () => {\r\n this.opencvReady = true;\r\n console.log('OpenCV.js loaded. Ready to start detection.');\r\n await this.getMedia(); // Get camera media once OpenCV is ready\r\n await this.handleStartDetection(); // Start processing video frames\r\n };\r\n\r\n // Method to get user media (camera stream)\r\n private async getMedia() {\r\n try {\r\n if (!store.cameraId) {\r\n await Cameras.InitCameras(store.device);\r\n }\r\n const constraints = Cameras.GetConstraints(store.cameraId, store.device);\r\n\r\n const mediaStream = await navigator.mediaDevices.getUserMedia(constraints);\r\n if (this.videoElement) {\r\n this.videoElement.srcObject = mediaStream;\r\n this.videoElement.play();\r\n }\r\n this.mediaStream = mediaStream;\r\n } catch (err) {\r\n console.error('Error accessing camera:', err);\r\n }\r\n }\r\n\r\n // Method to start video recording\r\n private startRecording = () => {\r\n if (this.mediaStream && this.videoElement) {\r\n this.recordedChunks = []; // Clear previous chunks\r\n\r\n var options = { mimeType: Cameras.webmMimeType.mime, videoBitsPerSecond: 1300000 };\r\n\r\n if (!MediaRecorder.isTypeSupported(options.mimeType)) {\r\n if (store.device.mobileOS == MobileOS.iOS || store.device.browser == Browser.Safari) options.mimeType = Cameras.mp4MimeType.mime;\r\n }\r\n\r\n this.mediaRecorder = new MediaRecorder(this.mediaStream, { mimeType: 'video/webm' });\r\n\r\n this.mediaRecorder.ondataavailable = ({ data }) => {\r\n if (data.size > 0) {\r\n this.recordedChunks = [...this.recordedChunks, data];\r\n }\r\n };\r\n\r\n this.mediaRecorder.onstop = () => {\r\n if (this.recordedChunks.length > 0) {\r\n const blob = new Blob(this.recordedChunks, { type: 'video/webm' });\r\n this.recordedVideoUrl = URL.createObjectURL(blob);\r\n }\r\n };\r\n\r\n this.mediaRecorder.start();\r\n this.isRecording = true;\r\n console.log('Recording started...');\r\n }\r\n };\r\n\r\n // Method to stop video recording\r\n private stopRecording = () => {\r\n if (this.mediaRecorder && this.mediaRecorder.state === 'recording') {\r\n this.mediaRecorder.stop();\r\n this.isRecording = false;\r\n console.log('Recording stopped.');\r\n this.eventRecordingIdReady.emit(this.recordedVideoUrl);\r\n }\r\n };\r\n\r\n // Method to capture an image from the video stream\r\n private capture = () => {\r\n if (this.videoElement && this.canvasElement) {\r\n const video = this.videoElement;\r\n const canvas = this.canvasElement;\r\n const context = canvas.getContext('2d');\r\n\r\n canvas.width = video.videoWidth;\r\n canvas.height = video.videoHeight;\r\n\r\n context.drawImage(video, 0, 0, canvas.width, canvas.height);\r\n\r\n this.capturedImage = canvas.toDataURL('image/png');\r\n console.log('Image captured!');\r\n this.verified = true;\r\n\r\n this.isCapturing = true;\r\n setTimeout(() => {\r\n this.isCapturing = false;\r\n }, 200); // Flash for 200ms\r\n\r\n this.eventPhotoCapture.emit(this.capturedImage);\r\n }\r\n };\r\n\r\n // Method for continuous video frame processing with OpenCV\r\n private processVideoFrame = () => {\r\n if (this.videoElement && this.processingCanvasElement && this.opencvReady && this.isDetecting) {\r\n console.log('Processing frame. cv.Mat is a constructor:', typeof cv.Mat === 'function');\r\n const video = this.videoElement;\r\n const processingCanvas = this.processingCanvasElement;\r\n const context = processingCanvas.getContext('2d');\r\n\r\n processingCanvas.width = video.videoWidth;\r\n processingCanvas.height = video.videoHeight;\r\n\r\n context.drawImage(video, 0, 0, processingCanvas.width, processingCanvas.height);\r\n\r\n const imageData = context.getImageData(0, 0, processingCanvas.width, processingCanvas.height);\r\n\r\n // --- OpenCV.js processing starts here ---\r\n let src = new cv.Mat(processingCanvas.height, processingCanvas.width, cv.CV_8UC4);\r\n src.data.set(imageData.data);\r\n let gray = new cv.Mat();\r\n let blurred = new cv.Mat();\r\n let edges = new cv.Mat();\r\n let contours = new cv.MatVector();\r\n let hierarchy = new cv.Mat();\r\n\r\n try {\r\n cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);\r\n cv.GaussianBlur(gray, blurred, new cv.Size(5, 5), 0, 0, cv.BORDER_DEFAULT);\r\n cv.Canny(blurred, edges, 75, 200, 3, false);\r\n cv.findContours(edges, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);\r\n\r\n let idDetected = false;\r\n let maxArea = 0;\r\n //let bestRect = null;\r\n\r\n for (let i = 0; i < contours.size(); ++i) {\r\n let contour = contours.get(i);\r\n let area = cv.contourArea(contour);\r\n\r\n if (area > 1000 && area > maxArea) {\r\n let peri = cv.arcLength(contour, true);\r\n let approx = new cv.Mat();\r\n cv.approxPolyDP(contour, approx, 0.02 * peri, true);\r\n\r\n if (approx.rows === 4) {\r\n let rect = cv.boundingRect(approx);\r\n const aspectRatio = rect.width / rect.height;\r\n\r\n if (aspectRatio > 1.4 && aspectRatio < 1.8) {\r\n if (rect.width > video.videoWidth * 0.3 && rect.height > video.videoHeight * 0.3) {\r\n idDetected = true;\r\n maxArea = area;\r\n //bestRect = rect;\r\n }\r\n }\r\n }\r\n approx.delete();\r\n }\r\n contour.delete();\r\n }\r\n\r\n if (idDetected) {\r\n console.log('ID document detected! Starting countdown...');\r\n this.countdown = 3;\r\n if (this.animationFrameId !== null) {\r\n cancelAnimationFrame(this.animationFrameId); // Stop continuous frame processing\r\n this.animationFrameId = null;\r\n }\r\n\r\n const timer = setInterval(() => {\r\n this.countdown--;\r\n if (this.countdown <= 0) {\r\n clearInterval(timer);\r\n this.capture();\r\n this.stopRecording();\r\n this.isDetecting = false;\r\n console.log('Picture taken. You can now stop recording.');\r\n this.countdown = 0; // Ensure countdown is 0\r\n }\r\n }, 1000);\r\n }\r\n } catch (error) {\r\n console.error('OpenCV processing error:', error);\r\n this.isDetecting = false; // Stop detection on error\r\n if (this.animationFrameId !== null) {\r\n cancelAnimationFrame(this.animationFrameId);\r\n this.animationFrameId = null;\r\n }\r\n } finally {\r\n // Crucial: Release memory allocated by OpenCV Mat objects\r\n src.delete();\r\n gray.delete();\r\n blurred.delete();\r\n edges.delete();\r\n contours.delete();\r\n hierarchy.delete();\r\n }\r\n // --- OpenCV.js processing ends here ---\r\n }\r\n\r\n if (this.isDetecting && this.animationFrameId !== null) {\r\n // Ensure loop continues only if still detecting\r\n this.animationFrameId = requestAnimationFrame(this.processVideoFrame);\r\n }\r\n };\r\n\r\n // Method to start the OpenCV frame processing loop\r\n private startFrameProcessing = () => {\r\n if (this.opencvReady && this.videoElement && this.videoElement.readyState >= 2) {\r\n if (this.animationFrameId === null) {\r\n // Only start if not already running\r\n this.animationFrameId = requestAnimationFrame(this.processVideoFrame);\r\n }\r\n }\r\n };\r\n\r\n // Handler for starting the ID detection process\r\n private handleStartDetection = async () => {\r\n if (!this.mediaStream) {\r\n console.log('Camera not ready. Please allow camera access.');\r\n return;\r\n }\r\n if (!this.opencvReady) {\r\n console.log('OpenCV.js is not loaded yet. Please wait.');\r\n return;\r\n }\r\n\r\n console.log('Starting ID detection...');\r\n this.isDetecting = true;\r\n this.capturedImage = null; // Clear previous image\r\n this.recordedChunks = []; // Clear previous video chunks\r\n this.recordedVideoUrl = null; // Clear previous video URL\r\n\r\n this.startRecording();\r\n\r\n if (this.videoElement && this.videoElement.readyState < 3) {\r\n // Use readyState 3 (HAVE_FUTURE_DATA) or 4 (HAVE_ENOUGH_DATA) for more robust readiness\r\n console.log('Waiting for video stream to fully load...');\r\n await new Promise<void>(resolve => {\r\n const onCanPlayThrough = () => {\r\n this.videoElement.removeEventListener('canplaythrough', onCanPlayThrough);\r\n resolve();\r\n };\r\n this.videoElement.addEventListener('canplaythrough', onCanPlayThrough);\r\n });\r\n console.log('Video stream ready. Starting detection.');\r\n }\r\n\r\n this.startFrameProcessing(); // Start the OpenCV frame processing loop\r\n };\r\n\r\n render() {\r\n let cameraVideoClass = 'cameraVideo';\r\n\r\n if (store.device.isDesktop) {\r\n cameraVideoClass = 'cameraVideoSelfieDesk';\r\n }\r\n\r\n return (\r\n <div class=\"container flex center\">\r\n <div class=\"px-2 w-100\">\r\n <h1 class={this.titleStyle} innerHTML={this.titleMesage}></h1>\r\n\r\n <div hidden={this.verified}>\r\n <div class=\"w-100 h-100 rounded\">\r\n <div class=\"camera rounded\">\r\n <video id=\"video\" loop autoplay playsinline muted class={cameraVideoClass} ref={el => (this.videoElement = el)} />\r\n <canvas id=\"output\" ref={el => (this.canvasElement = el)} style={{ display: 'none' }} />\r\n <canvas id=\"processingCanvasElement\" ref={el => (this.processingCanvasElement = el)} style={{ display: 'none' }} />\r\n <div class=\"id-guide-rectangle\"></div>\r\n {this.isCapturing && <div class=\"capture-flash-overlay\"></div>}\r\n {this.countdown > 0 && (\r\n <div class=\"absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center\">\r\n <span class=\"text-white text-9xl font-bold animate-bounce\">{this.countdown}</span>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"footer text-center\">\r\n <img src={logoOntrace}></img>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"id-auto-capture.js","sourceRoot":"","sources":["../../../../../src/components/common/id-auto-capture/id-auto-capture.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, h, Element, Event, EventEmitter, State } from '@stencil/core';\r\n\r\nimport logoOntrace from '../../../assets/logo-ontrace.svg';\r\nimport store from '../../../helpers/store';\r\nimport { Cameras } from '../../../helpers/Cameras';\r\nimport { Browser, MobileOS } from '../../../models/IDevice';\r\n\r\ndeclare const cv: any;\r\n\r\n@Component({\r\n tag: 'id-auto-capture',\r\n styleUrl: 'id-auto-capture.css',\r\n shadow: false,\r\n})\r\nexport class IdAutoCapture {\r\n @Element() el: HTMLElement;\r\n private videoElement: HTMLVideoElement;\r\n private canvasElement: HTMLCanvasElement;\r\n private processingCanvasElement: HTMLCanvasElement; // For OpenCV frame processing\r\n private mediaRecorder: MediaRecorder | null = null;\r\n private mediaStream: MediaStream | null = null;\r\n private animationFrameId: number | null = null; // To manage requestAnimationFrame\r\n private opencvScriptElement: HTMLScriptElement | null = null;\r\n\r\n @State() private verified: boolean;\r\n @State() private titleMesage: string;\r\n @State() private titleStyle: string;\r\n @State() recordedChunks: Blob[] = [];\r\n @State() countdown: number = 0;\r\n @State() capturedImage: string | null = null;\r\n @State() isRecording: boolean = false;\r\n @State() recordedVideoUrl: string | null = null;\r\n @State() isDetecting: boolean = false;\r\n @State() opencvReady: boolean = false;\r\n @State() isCapturing: boolean = false;\r\n\r\n @Event({\r\n eventName: 'photoIdCapture',\r\n })\r\n eventPhotoCapture: EventEmitter;\r\n\r\n @Event({\r\n eventName: 'recordingIdCapture',\r\n })\r\n eventRecordingIdReady: EventEmitter;\r\n\r\n constructor() {\r\n this.verified = false;\r\n }\r\n\r\n // Lifecycle method: Called once after the component is first connected to the DOM\r\n async componentWillLoad() {\r\n // Initialize DOM element references after the component's render method\r\n // has placed them in the DOM. This should ideally be done in componentDidLoad\r\n // but can be set up to ensure elements are available for setup.\r\n }\r\n\r\n // Lifecycle method: Called once after the component has loaded and rendered\r\n async componentDidLoad() {\r\n console.log('Loading OpenCV.js...');\r\n this.loadOpenCVScript();\r\n\r\n // Listen for the custom event dispatched by global.ts (ensures global.ts sets up window.Module)\r\n document.addEventListener('opencv:ready', this.handleOpencvReady);\r\n }\r\n\r\n disconnectedCallback() {\r\n if (this.mediaStream) {\r\n this.mediaStream.getTracks().forEach(track => track.stop());\r\n }\r\n if (this.animationFrameId !== null) {\r\n cancelAnimationFrame(this.animationFrameId);\r\n this.animationFrameId = null;\r\n }\r\n if (this.recordedVideoUrl) {\r\n URL.revokeObjectURL(this.recordedVideoUrl);\r\n }\r\n document.removeEventListener('opencv:ready', this.handleOpencvReady);\r\n\r\n // NEW: Clean up the dynamically added script element\r\n if (this.opencvScriptElement && this.opencvScriptElement.parentNode) {\r\n this.opencvScriptElement.parentNode.removeChild(this.opencvScriptElement);\r\n this.opencvScriptElement = null;\r\n }\r\n }\r\n\r\n private loadOpenCVScript() {\r\n if (!document.querySelector('script[src=\"https://docs.opencv.org/4.x/opencv.js\"]')) {\r\n // Only load if not already loaded\r\n this.opencvScriptElement = document.createElement('script');\r\n this.opencvScriptElement.type = 'text/javascript';\r\n this.opencvScriptElement.async = true;\r\n this.opencvScriptElement.src = 'https://docs.opencv.org/4.x/opencv.js';\r\n document.body.appendChild(this.opencvScriptElement); // Append to body or head\r\n console.log('Dynamically loaded opencv.js');\r\n } else {\r\n console.log('OpenCV.js script already present in the DOM.');\r\n }\r\n }\r\n\r\n private handleOpencvReady = async () => {\r\n this.opencvReady = true;\r\n console.log('OpenCV.js loaded. Ready to start detection.');\r\n await this.getMedia(); // Get camera media once OpenCV is ready\r\n await this.handleStartDetection(); // Start processing video frames\r\n };\r\n\r\n // Method to get user media (camera stream)\r\n private async getMedia() {\r\n try {\r\n if (!store.cameraId) {\r\n await Cameras.InitCameras(store.device);\r\n }\r\n const constraints = Cameras.GetConstraints(store.cameraId, store.device);\r\n\r\n const mediaStream = await navigator.mediaDevices.getUserMedia(constraints);\r\n if (this.videoElement) {\r\n this.videoElement.srcObject = mediaStream;\r\n this.videoElement.play();\r\n }\r\n this.mediaStream = mediaStream;\r\n } catch (err) {\r\n console.error('Error accessing camera:', err);\r\n }\r\n }\r\n\r\n // Method to start video recording\r\n private startRecording = () => {\r\n if (this.mediaStream && this.videoElement) {\r\n this.recordedChunks = []; // Clear previous chunks\r\n\r\n var options = { mimeType: Cameras.webmMimeType.mime, videoBitsPerSecond: 1300000 };\r\n\r\n if (!MediaRecorder.isTypeSupported(options.mimeType)) {\r\n if (store.device.mobileOS == MobileOS.iOS || store.device.browser == Browser.Safari) options.mimeType = Cameras.mp4MimeType.mime;\r\n }\r\n\r\n this.mediaRecorder = new MediaRecorder(this.mediaStream, { mimeType: 'video/webm' });\r\n\r\n this.mediaRecorder.ondataavailable = ({ data }) => {\r\n if (data.size > 0) {\r\n this.recordedChunks = [...this.recordedChunks, data];\r\n }\r\n };\r\n\r\n this.mediaRecorder.onstop = () => {\r\n if (this.recordedChunks.length > 0) {\r\n const blob = new Blob(this.recordedChunks, { type: 'video/webm' });\r\n this.recordedVideoUrl = URL.createObjectURL(blob);\r\n }\r\n };\r\n\r\n this.mediaRecorder.start();\r\n this.isRecording = true;\r\n console.log('Recording started...');\r\n }\r\n };\r\n\r\n // Method to stop video recording\r\n private stopRecording = () => {\r\n if (this.mediaRecorder && this.mediaRecorder.state === 'recording') {\r\n this.mediaRecorder.stop();\r\n this.isRecording = false;\r\n console.log('Recording stopped.');\r\n this.eventRecordingIdReady.emit(this.recordedVideoUrl);\r\n }\r\n };\r\n\r\n // Method to capture an image from the video stream\r\n private capture = () => {\r\n if (this.videoElement && this.canvasElement) {\r\n const video = this.videoElement;\r\n const canvas = this.canvasElement;\r\n const context = canvas.getContext('2d');\r\n\r\n canvas.width = video.videoWidth;\r\n canvas.height = video.videoHeight;\r\n\r\n context.drawImage(video, 0, 0, canvas.width, canvas.height);\r\n\r\n this.capturedImage = canvas.toDataURL('image/png');\r\n console.log('Image captured!');\r\n this.verified = true;\r\n\r\n this.isCapturing = true;\r\n setTimeout(() => {\r\n this.isCapturing = false;\r\n }, 200); // Flash for 200ms\r\n\r\n this.eventPhotoCapture.emit(this.capturedImage);\r\n }\r\n };\r\n\r\n // Method for continuous video frame processing with OpenCV\r\n private processVideoFrame = () => {\r\n if (this.videoElement && this.processingCanvasElement && this.opencvReady && this.isDetecting) {\r\n try {\r\n console.log('Processing frame. cv.Mat is a constructor:', typeof cv.Mat === 'function');\r\n const video = this.videoElement;\r\n const processingCanvas = this.processingCanvasElement;\r\n const context = processingCanvas.getContext('2d');\r\n\r\n processingCanvas.width = video.videoWidth;\r\n processingCanvas.height = video.videoHeight;\r\n\r\n context.drawImage(video, 0, 0, processingCanvas.width, processingCanvas.height);\r\n\r\n const imageData = context.getImageData(0, 0, processingCanvas.width, processingCanvas.height);\r\n\r\n // --- OpenCV.js processing starts here ---\r\n let src = new cv.Mat(processingCanvas.height, processingCanvas.width, cv.CV_8UC4);\r\n src.data.set(imageData.data);\r\n let gray = new cv.Mat();\r\n let blurred = new cv.Mat();\r\n let edges = new cv.Mat();\r\n let contours = new cv.MatVector();\r\n let hierarchy = new cv.Mat();\r\n\r\n try {\r\n cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);\r\n cv.GaussianBlur(gray, blurred, new cv.Size(5, 5), 0, 0, cv.BORDER_DEFAULT);\r\n cv.Canny(blurred, edges, 75, 200, 3, false);\r\n cv.findContours(edges, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);\r\n\r\n let idDetected = false;\r\n let maxArea = 0;\r\n //let bestRect = null;\r\n\r\n for (let i = 0; i < contours.size(); ++i) {\r\n let contour = contours.get(i);\r\n let area = cv.contourArea(contour);\r\n\r\n if (area > 1000 && area > maxArea) {\r\n let peri = cv.arcLength(contour, true);\r\n let approx = new cv.Mat();\r\n cv.approxPolyDP(contour, approx, 0.02 * peri, true);\r\n\r\n if (approx.rows === 4) {\r\n let rect = cv.boundingRect(approx);\r\n const aspectRatio = rect.width / rect.height;\r\n\r\n if (aspectRatio > 1.4 && aspectRatio < 1.8) {\r\n if (rect.width > video.videoWidth * 0.3 && rect.height > video.videoHeight * 0.3) {\r\n idDetected = true;\r\n maxArea = area;\r\n //bestRect = rect;\r\n }\r\n }\r\n }\r\n approx.delete();\r\n }\r\n contour.delete();\r\n }\r\n\r\n if (idDetected) {\r\n console.log('ID document detected! Starting countdown...');\r\n this.countdown = 3;\r\n if (this.animationFrameId !== null) {\r\n cancelAnimationFrame(this.animationFrameId); // Stop continuous frame processing\r\n this.animationFrameId = null;\r\n }\r\n\r\n const timer = setInterval(() => {\r\n this.countdown--;\r\n if (this.countdown <= 0) {\r\n clearInterval(timer);\r\n this.capture();\r\n this.stopRecording();\r\n this.isDetecting = false;\r\n console.log('Picture taken. You can now stop recording.');\r\n this.countdown = 0; // Ensure countdown is 0\r\n }\r\n }, 1000);\r\n }\r\n } catch (error) {\r\n console.error('OpenCV processing error:', error);\r\n this.isDetecting = false; // Stop detection on error\r\n if (this.animationFrameId !== null) {\r\n cancelAnimationFrame(this.animationFrameId);\r\n this.animationFrameId = null;\r\n }\r\n } finally {\r\n // Crucial: Release memory allocated by OpenCV Mat objects\r\n src.delete();\r\n gray.delete();\r\n blurred.delete();\r\n edges.delete();\r\n contours.delete();\r\n hierarchy.delete();\r\n }\r\n } catch (error) {\r\n console.error('Error processing video frame with OpenCV:', error);\r\n }\r\n // --- OpenCV.js processing ends here ---\r\n }\r\n\r\n if (this.isDetecting && this.animationFrameId !== null) {\r\n // Ensure loop continues only if still detecting\r\n this.animationFrameId = requestAnimationFrame(this.processVideoFrame);\r\n }\r\n };\r\n\r\n // Method to start the OpenCV frame processing loop\r\n private startFrameProcessing = () => {\r\n if (this.opencvReady && this.videoElement && this.videoElement.readyState >= 2) {\r\n if (this.animationFrameId === null) {\r\n // Only start if not already running\r\n this.animationFrameId = requestAnimationFrame(this.processVideoFrame);\r\n }\r\n }\r\n };\r\n\r\n // Handler for starting the ID detection process\r\n private handleStartDetection = async () => {\r\n if (!this.mediaStream) {\r\n console.log('Camera not ready. Please allow camera access.');\r\n return;\r\n }\r\n if (!this.opencvReady) {\r\n console.log('OpenCV.js is not loaded yet. Please wait.');\r\n return;\r\n }\r\n\r\n console.log('Starting ID detection...');\r\n this.isDetecting = true;\r\n this.capturedImage = null; // Clear previous image\r\n this.recordedChunks = []; // Clear previous video chunks\r\n this.recordedVideoUrl = null; // Clear previous video URL\r\n\r\n this.startRecording();\r\n\r\n if (this.videoElement && this.videoElement.readyState < 3) {\r\n // Use readyState 3 (HAVE_FUTURE_DATA) or 4 (HAVE_ENOUGH_DATA) for more robust readiness\r\n console.log('Waiting for video stream to fully load...');\r\n await new Promise<void>(resolve => {\r\n const onCanPlayThrough = () => {\r\n this.videoElement.removeEventListener('canplaythrough', onCanPlayThrough);\r\n resolve();\r\n };\r\n this.videoElement.addEventListener('canplaythrough', onCanPlayThrough);\r\n });\r\n console.log('Video stream ready. Starting detection.');\r\n }\r\n\r\n this.startFrameProcessing(); // Start the OpenCV frame processing loop\r\n };\r\n\r\n render() {\r\n let cameraVideoClass = 'cameraVideo';\r\n\r\n if (store.device.isDesktop) {\r\n cameraVideoClass = 'cameraVideoSelfieDesk';\r\n }\r\n\r\n return (\r\n <div class=\"container flex center\">\r\n <div class=\"px-2 w-100\">\r\n <h1 class={this.titleStyle} innerHTML={this.titleMesage}></h1>\r\n\r\n <div hidden={this.verified}>\r\n <div class=\"w-100 h-100 rounded\">\r\n <div class=\"camera rounded\">\r\n <video id=\"video\" loop autoplay playsinline muted class={cameraVideoClass} ref={el => (this.videoElement = el)} />\r\n <canvas id=\"output\" ref={el => (this.canvasElement = el)} style={{ display: 'none' }} />\r\n <canvas id=\"processingCanvasElement\" ref={el => (this.processingCanvasElement = el)} style={{ display: 'none' }} />\r\n <div class=\"id-guide-rectangle\"></div>\r\n {this.isCapturing && <div class=\"capture-flash-overlay\"></div>}\r\n {this.countdown > 0 && (\r\n <div class=\"absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center\">\r\n <span class=\"text-white text-9xl font-bold animate-bounce\">{this.countdown}</span>\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"footer text-center\">\r\n <img src={logoOntrace}></img>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n}\r\n"]}
@@ -590,88 +590,93 @@ const IdAutoCapture = class {
590
590
  // Method for continuous video frame processing with OpenCV
591
591
  this.processVideoFrame = () => {
592
592
  if (this.videoElement && this.processingCanvasElement && this.opencvReady && this.isDetecting) {
593
- console.log('Processing frame. cv.Mat is a constructor:', typeof cv.Mat === 'function');
594
- const video = this.videoElement;
595
- const processingCanvas = this.processingCanvasElement;
596
- const context = processingCanvas.getContext('2d');
597
- processingCanvas.width = video.videoWidth;
598
- processingCanvas.height = video.videoHeight;
599
- context.drawImage(video, 0, 0, processingCanvas.width, processingCanvas.height);
600
- const imageData = context.getImageData(0, 0, processingCanvas.width, processingCanvas.height);
601
- // --- OpenCV.js processing starts here ---
602
- let src = new cv.Mat(processingCanvas.height, processingCanvas.width, cv.CV_8UC4);
603
- src.data.set(imageData.data);
604
- let gray = new cv.Mat();
605
- let blurred = new cv.Mat();
606
- let edges = new cv.Mat();
607
- let contours = new cv.MatVector();
608
- let hierarchy = new cv.Mat();
609
593
  try {
610
- cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
611
- cv.GaussianBlur(gray, blurred, new cv.Size(5, 5), 0, 0, cv.BORDER_DEFAULT);
612
- cv.Canny(blurred, edges, 75, 200, 3, false);
613
- cv.findContours(edges, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);
614
- let idDetected = false;
615
- let maxArea = 0;
616
- //let bestRect = null;
617
- for (let i = 0; i < contours.size(); ++i) {
618
- let contour = contours.get(i);
619
- let area = cv.contourArea(contour);
620
- if (area > 1000 && area > maxArea) {
621
- let peri = cv.arcLength(contour, true);
622
- let approx = new cv.Mat();
623
- cv.approxPolyDP(contour, approx, 0.02 * peri, true);
624
- if (approx.rows === 4) {
625
- let rect = cv.boundingRect(approx);
626
- const aspectRatio = rect.width / rect.height;
627
- if (aspectRatio > 1.4 && aspectRatio < 1.8) {
628
- if (rect.width > video.videoWidth * 0.3 && rect.height > video.videoHeight * 0.3) {
629
- idDetected = true;
630
- maxArea = area;
631
- //bestRect = rect;
594
+ console.log('Processing frame. cv.Mat is a constructor:', typeof cv.Mat === 'function');
595
+ const video = this.videoElement;
596
+ const processingCanvas = this.processingCanvasElement;
597
+ const context = processingCanvas.getContext('2d');
598
+ processingCanvas.width = video.videoWidth;
599
+ processingCanvas.height = video.videoHeight;
600
+ context.drawImage(video, 0, 0, processingCanvas.width, processingCanvas.height);
601
+ const imageData = context.getImageData(0, 0, processingCanvas.width, processingCanvas.height);
602
+ // --- OpenCV.js processing starts here ---
603
+ let src = new cv.Mat(processingCanvas.height, processingCanvas.width, cv.CV_8UC4);
604
+ src.data.set(imageData.data);
605
+ let gray = new cv.Mat();
606
+ let blurred = new cv.Mat();
607
+ let edges = new cv.Mat();
608
+ let contours = new cv.MatVector();
609
+ let hierarchy = new cv.Mat();
610
+ try {
611
+ cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
612
+ cv.GaussianBlur(gray, blurred, new cv.Size(5, 5), 0, 0, cv.BORDER_DEFAULT);
613
+ cv.Canny(blurred, edges, 75, 200, 3, false);
614
+ cv.findContours(edges, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);
615
+ let idDetected = false;
616
+ let maxArea = 0;
617
+ //let bestRect = null;
618
+ for (let i = 0; i < contours.size(); ++i) {
619
+ let contour = contours.get(i);
620
+ let area = cv.contourArea(contour);
621
+ if (area > 1000 && area > maxArea) {
622
+ let peri = cv.arcLength(contour, true);
623
+ let approx = new cv.Mat();
624
+ cv.approxPolyDP(contour, approx, 0.02 * peri, true);
625
+ if (approx.rows === 4) {
626
+ let rect = cv.boundingRect(approx);
627
+ const aspectRatio = rect.width / rect.height;
628
+ if (aspectRatio > 1.4 && aspectRatio < 1.8) {
629
+ if (rect.width > video.videoWidth * 0.3 && rect.height > video.videoHeight * 0.3) {
630
+ idDetected = true;
631
+ maxArea = area;
632
+ //bestRect = rect;
633
+ }
632
634
  }
633
635
  }
636
+ approx.delete();
637
+ }
638
+ contour.delete();
639
+ }
640
+ if (idDetected) {
641
+ console.log('ID document detected! Starting countdown...');
642
+ this.countdown = 3;
643
+ if (this.animationFrameId !== null) {
644
+ cancelAnimationFrame(this.animationFrameId); // Stop continuous frame processing
645
+ this.animationFrameId = null;
634
646
  }
635
- approx.delete();
647
+ const timer = setInterval(() => {
648
+ this.countdown--;
649
+ if (this.countdown <= 0) {
650
+ clearInterval(timer);
651
+ this.capture();
652
+ this.stopRecording();
653
+ this.isDetecting = false;
654
+ console.log('Picture taken. You can now stop recording.');
655
+ this.countdown = 0; // Ensure countdown is 0
656
+ }
657
+ }, 1000);
636
658
  }
637
- contour.delete();
638
659
  }
639
- if (idDetected) {
640
- console.log('ID document detected! Starting countdown...');
641
- this.countdown = 3;
660
+ catch (error) {
661
+ console.error('OpenCV processing error:', error);
662
+ this.isDetecting = false; // Stop detection on error
642
663
  if (this.animationFrameId !== null) {
643
- cancelAnimationFrame(this.animationFrameId); // Stop continuous frame processing
664
+ cancelAnimationFrame(this.animationFrameId);
644
665
  this.animationFrameId = null;
645
666
  }
646
- const timer = setInterval(() => {
647
- this.countdown--;
648
- if (this.countdown <= 0) {
649
- clearInterval(timer);
650
- this.capture();
651
- this.stopRecording();
652
- this.isDetecting = false;
653
- console.log('Picture taken. You can now stop recording.');
654
- this.countdown = 0; // Ensure countdown is 0
655
- }
656
- }, 1000);
657
667
  }
658
- }
659
- catch (error) {
660
- console.error('OpenCV processing error:', error);
661
- this.isDetecting = false; // Stop detection on error
662
- if (this.animationFrameId !== null) {
663
- cancelAnimationFrame(this.animationFrameId);
664
- this.animationFrameId = null;
668
+ finally {
669
+ // Crucial: Release memory allocated by OpenCV Mat objects
670
+ src.delete();
671
+ gray.delete();
672
+ blurred.delete();
673
+ edges.delete();
674
+ contours.delete();
675
+ hierarchy.delete();
665
676
  }
666
677
  }
667
- finally {
668
- // Crucial: Release memory allocated by OpenCV Mat objects
669
- src.delete();
670
- gray.delete();
671
- blurred.delete();
672
- edges.delete();
673
- contours.delete();
674
- hierarchy.delete();
678
+ catch (error) {
679
+ console.error('Error processing video frame with OpenCV:', error);
675
680
  }
676
681
  // --- OpenCV.js processing ends here ---
677
682
  }
@@ -789,7 +794,7 @@ const IdAutoCapture = class {
789
794
  if (state.device.isDesktop) {
790
795
  cameraVideoClass = 'cameraVideoSelfieDesk';
791
796
  }
792
- return (h("div", { key: '0b0333b5c7b20a216319cf081a9f49111012596e', class: "container flex center" }, h("div", { key: 'e7980ea76bddf47ac73f865b3c4cb609d4597cbd', class: "px-2 w-100" }, h("h1", { key: 'd5a97b44269a80d3a3cee564ff48cf543d3bfc04', class: this.titleStyle, innerHTML: this.titleMesage }), h("div", { key: 'e52e5f59f446be42bba3ae25377fbbe7e2b87d87', hidden: this.verified }, h("div", { key: 'f680400952063d743350a607e2f503bc57fdcdff', class: "w-100 h-100 rounded" }, h("div", { key: '237debd548236f0a12c71ac73b61ff420bd91203', class: "camera rounded" }, h("video", { key: 'db25e8012fc4639d785a175a449ac4ec5130d113', id: "video", loop: true, autoplay: true, playsinline: true, muted: true, class: cameraVideoClass, ref: el => (this.videoElement = el) }), h("canvas", { key: 'd2c08faa9f71bf7c8b5f161fd76d49a99960a73e', id: "output", ref: el => (this.canvasElement = el), style: { display: 'none' } }), h("canvas", { key: '1882ca42f1716dd6573e28ffb289958000d8e23a', id: "processingCanvasElement", ref: el => (this.processingCanvasElement = el), style: { display: 'none' } }), h("div", { key: 'ed29e8ff7706909244dfc6ef8ef2a3529e010628', class: "id-guide-rectangle" }), this.isCapturing && h("div", { key: '4df9ad4556cd2d57b0a5e18d0fe18b10b61cd55b', class: "capture-flash-overlay" }), this.countdown > 0 && (h("div", { key: 'c06a98f7a785bdefeba161a39a701eb7257a90d6', class: "absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center" }, h("span", { key: '63407cf0373b92248eef073d863b12536c6f9cfc', class: "text-white text-9xl font-bold animate-bounce" }, this.countdown)))))), h("div", { key: '047ebeeb0b61d05f95f51b23e48a14eed82dbb31', class: "footer text-center" }, h("img", { key: 'deeea20a5acf6618ee24fbfa6919b8a5a38bb1d0', src: logoOntraceSvg })))));
797
+ return (h("div", { key: 'deb2d35a50823fa5c222c6049a4119a371194870', class: "container flex center" }, h("div", { key: '449a0fef911f14d3611a1d7e83ed1bfc02c0553f', class: "px-2 w-100" }, h("h1", { key: '8d9f8b3684e58ba57f4ec0467efa0d9af62c5a98', class: this.titleStyle, innerHTML: this.titleMesage }), h("div", { key: '701aeecc148bdd00ef9cd38b165f0628adfe827c', hidden: this.verified }, h("div", { key: 'cbe89cf4ddc15c46b595929ecaf4fb8cc20136b5', class: "w-100 h-100 rounded" }, h("div", { key: '78f52a0a77c3dd8218115253bbcb79ee0a9a6d4b', class: "camera rounded" }, h("video", { key: '6ee76764205ce855fedd7b8c86be4394b2cad7bb', id: "video", loop: true, autoplay: true, playsinline: true, muted: true, class: cameraVideoClass, ref: el => (this.videoElement = el) }), h("canvas", { key: '5574b79a997d3ca06afa99faa61cb9bace755e91', id: "output", ref: el => (this.canvasElement = el), style: { display: 'none' } }), h("canvas", { key: 'e25df7ef70206d5544adade008cd612f1fee550a', id: "processingCanvasElement", ref: el => (this.processingCanvasElement = el), style: { display: 'none' } }), h("div", { key: '8ac6db08f2d1e44d04f2827f29e08787b853812e', class: "id-guide-rectangle" }), this.isCapturing && h("div", { key: '900ddcc0d2bf371d7ad4e593eaf0e9b60b6d2810', class: "capture-flash-overlay" }), this.countdown > 0 && (h("div", { key: 'd5f05c1b3dcbd02977462c6b9d816c2835698c2f', class: "absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center" }, h("span", { key: '7b85d36f1b609360c8214a29e220f6f80effffca', class: "text-white text-9xl font-bold animate-bounce" }, this.countdown)))))), h("div", { key: '9b653ebb92ce731ddb235d85db4a7fa99aaa4c64', class: "footer text-center" }, h("img", { key: 'f085d8f1698e66448cf749ec4cc45b496fbd55a1', src: logoOntraceSvg })))));
793
798
  }
794
799
  get el() { return getElement(this); }
795
800
  };
@@ -854,7 +859,7 @@ const IdSelection = class {
854
859
  };
855
860
  IdSelection.style = idSelectionCss;
856
861
 
857
- const version$1 = "4.7.24";
862
+ const version$1 = "4.7.25";
858
863
  var packageJson = {
859
864
  version: version$1};
860
865