Spaces:
Sleeping
Sleeping
Update static/script.js
Browse files- static/script.js +76 -127
static/script.js
CHANGED
|
@@ -137,186 +137,135 @@
|
|
| 137 |
|
| 138 |
|
| 139 |
/* ================================================================
|
| 140 |
-
1.
|
| 141 |
================================================================ */
|
| 142 |
-
window.onload = () => {
|
| 143 |
-
const nameElement = document.getElementById('user-name-data');
|
| 144 |
-
let actualName = (nameElement && nameElement.innerText.trim() !== "") ? nameElement.innerText.trim() : "User";
|
| 145 |
-
|
| 146 |
-
setTimeout(() => {
|
| 147 |
-
speak(`Welcome ${actualName} to the Voice Vision world.`);
|
| 148 |
-
}, 1500);
|
| 149 |
-
};
|
| 150 |
-
|
| 151 |
let cameraOn = false;
|
| 152 |
let isDetecting = false;
|
| 153 |
let isProcessing = false;
|
| 154 |
-
let
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
|
| 156 |
/* ================================================================
|
| 157 |
-
2. POWER &
|
| 158 |
================================================================ */
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
function stopEverything() {
|
| 162 |
-
isDetecting = false;
|
| 163 |
cameraOn = false;
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
// 1. Camera Hardware Release
|
| 167 |
const video = document.getElementById('video');
|
| 168 |
if (video && video.srcObject) {
|
| 169 |
-
|
| 170 |
-
tracks.forEach(track => track.stop()); // Camera light band ho jayegi
|
| 171 |
video.srcObject = null;
|
| 172 |
}
|
| 173 |
-
|
| 174 |
-
// 2. Speech Synthesis ko chup karwayein
|
| 175 |
window.speechSynthesis.cancel();
|
| 176 |
-
|
| 177 |
-
// 3. UI Reset
|
| 178 |
-
const canvas = document.getElementById('detectionCanvas');
|
| 179 |
-
if (canvas) {
|
| 180 |
-
const ctx = canvas.getContext('2d');
|
| 181 |
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
| 182 |
-
}
|
| 183 |
}
|
| 184 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
async function handlePowerOn() {
|
| 186 |
const video = document.getElementById('video');
|
| 187 |
-
const powerBtn = document.getElementById('powerBtn');
|
| 188 |
-
|
| 189 |
try {
|
| 190 |
-
const stream = await navigator.mediaDevices.getUserMedia({
|
| 191 |
-
video: { width: 640, height: 480 }
|
| 192 |
-
});
|
| 193 |
video.srcObject = stream;
|
| 194 |
cameraOn = true;
|
| 195 |
-
|
| 196 |
-
powerBtn.style.display = 'none';
|
| 197 |
document.getElementById('startDetectBtn').style.display = 'inline-block';
|
| 198 |
document.getElementById('powerOffBtn').style.display = 'inline-block';
|
| 199 |
-
|
| 200 |
-
speak("System online. Camera activated.");
|
| 201 |
} catch (err) {
|
| 202 |
-
alert("Camera
|
| 203 |
}
|
| 204 |
}
|
| 205 |
|
| 206 |
-
function handlePowerOff() {
|
| 207 |
-
speak("Shutting down system.");
|
| 208 |
-
stopEverything(); // Pehle sab rokein
|
| 209 |
-
|
| 210 |
-
setTimeout(() => {
|
| 211 |
-
sessionStorage.setItem('isShuttingDown', 'true');
|
| 212 |
-
window.location.reload();
|
| 213 |
-
}, 800);
|
| 214 |
-
}
|
| 215 |
-
|
| 216 |
-
function logout() {
|
| 217 |
-
speak("Logging out. Goodbye.");
|
| 218 |
-
stopEverything(); // Pehle sab rokein
|
| 219 |
-
|
| 220 |
-
setTimeout(() => {
|
| 221 |
-
window.location.href = "/logout";
|
| 222 |
-
}, 800);
|
| 223 |
-
}
|
| 224 |
-
|
| 225 |
-
/* ================================================================
|
| 226 |
-
3. DETECTION & REALITY-BASED VI LOGIC
|
| 227 |
-
================================================================ */
|
| 228 |
-
|
| 229 |
function handleStartDetection() {
|
| 230 |
isDetecting = true;
|
| 231 |
document.getElementById('modeButtonsGroup').style.display = 'flex';
|
| 232 |
document.getElementById('startDetectBtn').style.display = 'none';
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
captureAndSend();
|
| 236 |
}
|
| 237 |
|
| 238 |
-
async function
|
| 239 |
-
// Agar hardware off hai ya detection band hai, to loop ruk jaye
|
| 240 |
if (!cameraOn || !isDetecting) return;
|
| 241 |
if (isProcessing) {
|
| 242 |
-
setTimeout(
|
| 243 |
return;
|
| 244 |
}
|
| 245 |
|
| 246 |
const video = document.getElementById('video');
|
| 247 |
-
const canvas = document.createElement('canvas');
|
| 248 |
-
canvas.width = 640;
|
| 249 |
-
canvas.
|
| 250 |
-
const ctx = canvas.getContext('2d');
|
| 251 |
-
ctx.drawImage(video, 0, 0, 640, 480);
|
| 252 |
|
| 253 |
-
const dataUrl = canvas.toDataURL('image/jpeg', 0.4);
|
| 254 |
isProcessing = true;
|
| 255 |
-
|
| 256 |
try {
|
| 257 |
const response = await fetch('/process_frame', {
|
| 258 |
method: 'POST',
|
| 259 |
headers: { 'Content-Type': 'application/json' },
|
| 260 |
-
body: JSON.stringify({ image:
|
| 261 |
});
|
| 262 |
-
|
| 263 |
const result = await response.json();
|
| 264 |
if (result.detections && isDetecting) {
|
| 265 |
-
|
| 266 |
-
processVIAwareness(result.detections);
|
| 267 |
}
|
| 268 |
-
} catch (
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
}
|
| 274 |
}
|
| 275 |
|
| 276 |
-
function
|
| 277 |
const canvas = document.getElementById('detectionCanvas');
|
| 278 |
const ctx = canvas.getContext('2d');
|
| 279 |
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
| 280 |
|
| 281 |
-
detections.
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
ctx.
|
| 285 |
-
|
| 286 |
-
ctx.fillStyle =
|
| 287 |
-
ctx.
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
let obj = detections[0];
|
| 296 |
-
let centerX = obj.x + (obj.w / 2);
|
| 297 |
-
let area = (obj.w * obj.h) / (640 * 480);
|
| 298 |
-
|
| 299 |
-
// Direction Logic
|
| 300 |
-
let direction = "in front of you";
|
| 301 |
-
if (centerX < 213) direction = "on your left";
|
| 302 |
-
else if (centerX > 426) direction = "on your right";
|
| 303 |
-
|
| 304 |
-
// Proximity Alert
|
| 305 |
-
let warning = "";
|
| 306 |
-
if (area > 0.45) warning = "STOP! OBSTACLE VERY CLOSE. ";
|
| 307 |
-
else if (area > 0.2) warning = "Careful, ";
|
| 308 |
-
|
| 309 |
-
let finalMessage = `${warning}${obj.label} ${direction}`;
|
| 310 |
-
|
| 311 |
-
if (finalMessage !== lastSpoken) {
|
| 312 |
-
speak(finalMessage);
|
| 313 |
-
lastSpoken = finalMessage;
|
| 314 |
}
|
| 315 |
-
}
|
| 316 |
-
|
| 317 |
-
function speak(text) {
|
| 318 |
-
window.speechSynthesis.cancel();
|
| 319 |
-
let msg = new SpeechSynthesisUtterance(text);
|
| 320 |
-
msg.rate = 1.2;
|
| 321 |
-
window.speechSynthesis.speak(msg);
|
| 322 |
}
|
|
|
|
| 137 |
|
| 138 |
|
| 139 |
/* ================================================================
|
| 140 |
+
1. GLOBAL VARIABLES & VOICE SETTINGS
|
| 141 |
================================================================ */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
let cameraOn = false;
|
| 143 |
let isDetecting = false;
|
| 144 |
let isProcessing = false;
|
| 145 |
+
let lastSpokenTime = 0; // Smoothness ke liye
|
| 146 |
+
let lastMessage = "";
|
| 147 |
+
|
| 148 |
+
function speak(text, force = false) {
|
| 149 |
+
const now = Date.now();
|
| 150 |
+
// Smoothness: Har 2 second se pehle dobara mat bolein (agar STOP na ho)
|
| 151 |
+
if (!force && (now - lastSpokenTime < 2000)) return;
|
| 152 |
+
if (text === lastMessage && !force) return;
|
| 153 |
+
|
| 154 |
+
window.speechSynthesis.cancel();
|
| 155 |
+
let msg = new SpeechSynthesisUtterance(text);
|
| 156 |
+
msg.rate = 0.9; // Fast se slow kar diya (insani awaz)
|
| 157 |
+
msg.pitch = 1.0;
|
| 158 |
+
|
| 159 |
+
lastSpokenTime = now;
|
| 160 |
+
lastMessage = text;
|
| 161 |
+
window.speechSynthesis.speak(msg);
|
| 162 |
+
}
|
| 163 |
|
| 164 |
/* ================================================================
|
| 165 |
+
2. POWER OFF & LOGOUT (THE RESET FIX)
|
| 166 |
================================================================ */
|
| 167 |
+
async function stopSystemProperly() {
|
| 168 |
+
isDetecting = false;
|
|
|
|
|
|
|
| 169 |
cameraOn = false;
|
| 170 |
+
|
| 171 |
+
// Camera Hardware Release
|
|
|
|
| 172 |
const video = document.getElementById('video');
|
| 173 |
if (video && video.srcObject) {
|
| 174 |
+
video.srcObject.getTracks().forEach(track => track.stop());
|
|
|
|
| 175 |
video.srcObject = null;
|
| 176 |
}
|
|
|
|
|
|
|
| 177 |
window.speechSynthesis.cancel();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
}
|
| 179 |
|
| 180 |
+
async function handlePowerOff() {
|
| 181 |
+
speak("System shutting down. Please wait.", true);
|
| 182 |
+
await stopSystemProperly();
|
| 183 |
+
setTimeout(() => {
|
| 184 |
+
window.location.replace(window.location.href); // Hard reload
|
| 185 |
+
}, 1000);
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
async function logout() {
|
| 189 |
+
speak("Logging out. Goodbye.", true);
|
| 190 |
+
await stopSystemProperly();
|
| 191 |
+
setTimeout(() => {
|
| 192 |
+
window.location.replace("/logout"); // Server-side logout
|
| 193 |
+
}, 1000);
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
/* ================================================================
|
| 197 |
+
3. DETECTION LOGIC (WITH SMOOTHING)
|
| 198 |
+
================================================================ */
|
| 199 |
async function handlePowerOn() {
|
| 200 |
const video = document.getElementById('video');
|
|
|
|
|
|
|
| 201 |
try {
|
| 202 |
+
const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480 } });
|
|
|
|
|
|
|
| 203 |
video.srcObject = stream;
|
| 204 |
cameraOn = true;
|
| 205 |
+
document.getElementById('powerBtn').style.display = 'none';
|
|
|
|
| 206 |
document.getElementById('startDetectBtn').style.display = 'inline-block';
|
| 207 |
document.getElementById('powerOffBtn').style.display = 'inline-block';
|
| 208 |
+
speak("System Online.", true);
|
|
|
|
| 209 |
} catch (err) {
|
| 210 |
+
alert("Camera error. Please refresh.");
|
| 211 |
}
|
| 212 |
}
|
| 213 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
function handleStartDetection() {
|
| 215 |
isDetecting = true;
|
| 216 |
document.getElementById('modeButtonsGroup').style.display = 'flex';
|
| 217 |
document.getElementById('startDetectBtn').style.display = 'none';
|
| 218 |
+
speak("Detection Active.", true);
|
| 219 |
+
captureLoop();
|
|
|
|
| 220 |
}
|
| 221 |
|
| 222 |
+
async function captureLoop() {
|
|
|
|
| 223 |
if (!cameraOn || !isDetecting) return;
|
| 224 |
if (isProcessing) {
|
| 225 |
+
setTimeout(captureLoop, 200);
|
| 226 |
return;
|
| 227 |
}
|
| 228 |
|
| 229 |
const video = document.getElementById('video');
|
| 230 |
+
const canvas = document.createElement('canvas');
|
| 231 |
+
canvas.width = 640; canvas.height = 480;
|
| 232 |
+
canvas.getContext('2d').drawImage(video, 0, 0, 640, 480);
|
|
|
|
|
|
|
| 233 |
|
|
|
|
| 234 |
isProcessing = true;
|
|
|
|
| 235 |
try {
|
| 236 |
const response = await fetch('/process_frame', {
|
| 237 |
method: 'POST',
|
| 238 |
headers: { 'Content-Type': 'application/json' },
|
| 239 |
+
body: JSON.stringify({ image: canvas.toDataURL('image/jpeg', 0.4) })
|
| 240 |
});
|
|
|
|
| 241 |
const result = await response.json();
|
| 242 |
if (result.detections && isDetecting) {
|
| 243 |
+
updateUI(result.detections);
|
|
|
|
| 244 |
}
|
| 245 |
+
} catch (e) { console.log("Loop skip..."); }
|
| 246 |
+
|
| 247 |
+
isProcessing = false;
|
| 248 |
+
// Delay barha diya taake system par bojh na paray
|
| 249 |
+
setTimeout(captureLoop, 800);
|
|
|
|
| 250 |
}
|
| 251 |
|
| 252 |
+
function updateUI(detections) {
|
| 253 |
const canvas = document.getElementById('detectionCanvas');
|
| 254 |
const ctx = canvas.getContext('2d');
|
| 255 |
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
| 256 |
|
| 257 |
+
if (detections.length > 0) {
|
| 258 |
+
let obj = detections[0];
|
| 259 |
+
// Visuals
|
| 260 |
+
ctx.strokeStyle = "#00FF00"; ctx.lineWidth = 4;
|
| 261 |
+
ctx.strokeRect(obj.x, obj.y, obj.w, obj.h);
|
| 262 |
+
ctx.fillStyle = "#00FF00"; ctx.font = "bold 20px Arial";
|
| 263 |
+
ctx.fillText(obj.label.toUpperCase(), obj.x, obj.y - 10);
|
| 264 |
+
|
| 265 |
+
// VI Logic
|
| 266 |
+
let direction = obj.x + (obj.w/2) < 213 ? "on your left" : (obj.x + (obj.w/2) > 426 ? "on your right" : "in front");
|
| 267 |
+
let area = (obj.w * obj.h) / (640*480);
|
| 268 |
+
let msg = area > 0.4 ? `STOP! ${obj.label} very close` : `${obj.label} ${direction}`;
|
| 269 |
+
speak(msg, area > 0.4); // Force speak if very close
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 270 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
}
|