// /* ================================================================ // 1. WELCOME VOICE & INITIALIZATION // ================================================================ */ // window.onload = () => { // if (sessionStorage.getItem('isShuttingDown') === 'true') { // sessionStorage.removeItem('isShuttingDown'); // return; // } // // Welcome sound & speech logic // setTimeout(() => { // const nameElement = document.getElementById('user-name-data'); // let actualName = (nameElement && nameElement.innerText.trim() !== "") ? nameElement.innerText.trim() : "User"; // const message = `Welcome ${actualName} to the Voice Vision world.`; // const speech = new SpeechSynthesisUtterance(message); // speech.rate = 0.9; // window.speechSynthesis.speak(speech); // }, 1500); // }; // /* ================================================================ // 2. DASHBOARD DYNAMIC CONTROLS (POWER ON / OFF) // ================================================================ */ // let cameraOn = false; // let isDetecting = false; // async function handlePowerOn() { // const video = document.getElementById('video'); // const cameraBox = document.getElementById('cameraBox'); // const powerBtn = document.getElementById('powerBtn'); // try { // // Muted hona zaroori hai browser policy ke liye // const stream = await navigator.mediaDevices.getUserMedia({ // video: { width: 640, height: 480 } // }); // video.srcObject = stream; // cameraOn = true; // cameraBox.style.display = 'block'; // powerBtn.style.display = 'none'; // document.getElementById('startDetectBtn').style.display = 'inline-block'; // document.getElementById('powerOffBtn').style.display = 'inline-block'; // window.speechSynthesis.speak(new SpeechSynthesisUtterance("System online.")); // } catch (err) { // alert("Camera permission denied!"); // console.error(err); // } // } // function handlePowerOff() { // sessionStorage.setItem('isShuttingDown', 'true'); // window.location.reload(); // } // /* ================================================================ // 3. DETECTION LOGIC (Cloud Optimized) // ================================================================ */ // function handleStartDetection() { // isDetecting = true; // document.getElementById('modeButtonsGroup').style.display = 'flex'; // document.getElementById('startDetectBtn').style.display = 'none'; // window.speechSynthesis.speak(new SpeechSynthesisUtterance("Detection started.")); // // Detection loop shuru karein // captureAndSend(); // } // async function captureAndSend() { // if (!cameraOn || !isDetecting) return; // const video = document.getElementById('video'); // const canvas = document.createElement('canvas'); // Arzi canvas frame lene ke liye // canvas.width = 640; // canvas.height = 480; // const ctx = canvas.getContext('2d'); // ctx.drawImage(video, 0, 0, 640, 480); // const dataUrl = canvas.toDataURL('image/jpeg', 0.6); // Quality kam taake fast transfer ho // try { // const response = await fetch('/process_frame', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify({ image: dataUrl }) // }); // const result = await response.json(); // if (result.detections) { // // Screen par boxes draw karne wala function // drawDetections(result.detections); // // Agar koi object milay to bolein // if (result.detections.length > 0) { // const labels = result.detections.map(d => d.label).join(", "); // // Sirf tab bolein jab naya object aaye (optional) // // window.speechSynthesis.speak(new SpeechSynthesisUtterance("I see " + labels)); // } // } // } catch (error) { // console.log("Error sending frame:", error); // } // // Har 1 second baad agla frame bhejein (Cloud ke liye 1s safe hai) // if (isDetecting) setTimeout(captureAndSend, 1000); // } // // Canvas par Boxes draw karne ka function // function drawDetections(detections) { // const canvas = document.getElementById('detectionCanvas'); // if (!canvas) return; // const ctx = canvas.getContext('2d'); // ctx.clearRect(0, 0, canvas.width, canvas.height); // Purane boxes saaf karein // detections.forEach(det => { // const [x1, y1, x2, y2] = det.box; // // Box style // ctx.strokeStyle = "#00FF00"; // ctx.lineWidth = 3; // ctx.strokeRect(x1, y1, x2 - x1, y2 - y1); // // Label style // ctx.fillStyle = "#00FF00"; // ctx.font = "18px Arial"; // ctx.fillText(`${det.label} (${Math.round(det.confidence * 100)}%)`, x1, y1 > 20 ? y1 - 5 : y1 + 20); // }); // } // function logout() { // window.location.href = "/logout"; // } /* ================================================================ 1. GLOBAL VARIABLES & VOICE SETTINGS ================================================================ */ let cameraOn = false; let isDetecting = false; let isProcessing = false; let lastSpokenTime = 0; // Smoothness ke liye let lastMessage = ""; function speak(text, force = false) { const now = Date.now(); // Smoothness: Har 2 second se pehle dobara mat bolein (agar STOP na ho) if (!force && (now - lastSpokenTime < 2000)) return; if (text === lastMessage && !force) return; window.speechSynthesis.cancel(); let msg = new SpeechSynthesisUtterance(text); msg.rate = 0.9; // Fast se slow kar diya (insani awaz) msg.pitch = 1.0; lastSpokenTime = now; lastMessage = text; window.speechSynthesis.speak(msg); } /* ================================================================ 2. POWER OFF & LOGOUT (THE RESET FIX) ================================================================ */ async function stopSystemProperly() { isDetecting = false; cameraOn = false; // Camera Hardware Release const video = document.getElementById('video'); if (video && video.srcObject) { video.srcObject.getTracks().forEach(track => track.stop()); video.srcObject = null; } window.speechSynthesis.cancel(); } async function handlePowerOff() { speak("System shutting down. Please wait.", true); await stopSystemProperly(); setTimeout(() => { window.location.replace(window.location.href); // Hard reload }, 1000); } async function logout() { speak("Logging out. Goodbye.", true); await stopSystemProperly(); setTimeout(() => { window.location.replace("/logout"); // Server-side logout }, 1000); } /* ================================================================ 3. DETECTION LOGIC (WITH SMOOTHING) ================================================================ */ async function handlePowerOn() { const video = document.getElementById('video'); try { const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480 } }); video.srcObject = stream; cameraOn = true; document.getElementById('powerBtn').style.display = 'none'; document.getElementById('startDetectBtn').style.display = 'inline-block'; document.getElementById('powerOffBtn').style.display = 'inline-block'; speak("System Online.", true); } catch (err) { alert("Camera error. Please refresh."); } } function handleStartDetection() { isDetecting = true; document.getElementById('modeButtonsGroup').style.display = 'flex'; document.getElementById('startDetectBtn').style.display = 'none'; speak("Detection Active.", true); captureLoop(); } async function captureLoop() { if (!cameraOn || !isDetecting) return; if (isProcessing) { setTimeout(captureLoop, 200); return; } const video = document.getElementById('video'); const canvas = document.createElement('canvas'); canvas.width = 640; canvas.height = 480; canvas.getContext('2d').drawImage(video, 0, 0, 640, 480); isProcessing = true; try { const response = await fetch('/process_frame', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ image: canvas.toDataURL('image/jpeg', 0.4) }) }); const result = await response.json(); if (result.detections && isDetecting) { updateUI(result.detections); } } catch (e) { console.log("Loop skip..."); } isProcessing = false; // Delay barha diya taake system par bojh na paray setTimeout(captureLoop, 800); } function updateUI(detections) { const canvas = document.getElementById('detectionCanvas'); const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); if (detections.length > 0) { let obj = detections[0]; // Visuals ctx.strokeStyle = "#00FF00"; ctx.lineWidth = 4; ctx.strokeRect(obj.x, obj.y, obj.w, obj.h); ctx.fillStyle = "#00FF00"; ctx.font = "bold 20px Arial"; ctx.fillText(obj.label.toUpperCase(), obj.x, obj.y - 10); // VI Logic let direction = obj.x + (obj.w/2) < 213 ? "on your left" : (obj.x + (obj.w/2) > 426 ? "on your right" : "in front"); let area = (obj.w * obj.h) / (640*480); let msg = area > 0.4 ? `STOP! ${obj.label} very close` : `${obj.label} ${direction}`; speak(msg, area > 0.4); // Force speak if very close } }