Emeritus-21 commited on
Commit
0d1663b
·
verified ·
1 Parent(s): decf79a

Update static/script.js

Browse files
Files changed (1) hide show
  1. static/script.js +121 -94
static/script.js CHANGED
@@ -1,4 +1,4 @@
1
- document.addEventListener('DOMContentLoaded', () => {
2
  const topCard = document.getElementById('top-card');
3
  const enableWebcamBtn = document.getElementById('enable-webcam-btn');
4
  const predictionDiv = document.getElementById('prediction');
@@ -13,8 +13,18 @@ document.addEventListener('DOMContentLoaded', () => {
13
  return;
14
  }
15
 
16
- enableWebcamBtn.addEventListener('click', () => {
17
- console.log('Enable Webcam button clicked');
 
 
 
 
 
 
 
 
 
 
18
  topCard.innerHTML = `
19
  <div id="container">
20
  <video id="input_video" autoplay muted playsinline></video>
@@ -22,110 +32,127 @@ document.addEventListener('DOMContentLoaded', () => {
22
  </div>
23
  `;
24
  console.log('Video and canvas elements added to DOM');
25
- setTimeout(() => initMediaPipe(), 100);
26
- });
27
 
28
- clearBtn.addEventListener('click', () => {
29
- console.log('Clear button clicked');
30
- predictionText.textContent = 'None';
31
- loadingSpan.style.display = 'none';
32
- });
 
 
33
 
34
- listenBtn.addEventListener('click', () => {
35
- console.log('Listen button clicked');
36
- alert('Listen functionality not implemented yet');
37
- });
 
 
 
38
 
39
- function initMediaPipe() {
40
- const videoElement = document.getElementById('input_video');
41
- const canvasElement = document.getElementById('output_canvas');
42
- const canvasCtx = canvasElement.getContext('2d');
 
 
43
 
44
- if (!videoElement || !canvasElement || !canvasCtx) {
45
- console.error('Required elements not found:', { videoElement, canvasElement, canvasCtx });
46
- predictionText.textContent = 'Error: Video or canvas not found';
47
- return;
48
- }
49
 
50
- console.log('Initializing MediaPipe Hands');
51
- const isMobile = window.innerWidth <= 700;
52
- canvasElement.width = isMobile ? 480 : 640;
53
- canvasElement.height = isMobile ? 360 : 480;
54
 
55
- const hands = new Hands({
56
- locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/hands@0.4/${file}`
57
- });
58
 
59
- hands.setOptions({
60
- maxNumHands: 2,
61
- minDetectionConfidence: 0.7,
62
- minTrackingConfidence: 0.7,
63
- });
64
 
65
- let lastPredictionTime = 0;
66
 
67
- hands.onResults((results) => {
68
- if (!results.image) {
69
- console.warn('No video frame received from MediaPipe');
70
- predictionText.textContent = 'Error: No video frame received';
71
- loadingSpan.style.display = 'none';
72
- return;
73
- }
 
 
 
 
74
 
75
- canvasCtx.save();
76
- canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
77
- canvasCtx.drawImage(results.image, 0, 0, canvasElement.width, canvasElement.height);
78
-
79
- if (results.multiHandLandmarks && results.multiHandedness) {
80
- for (let i = 0; i < results.multiHandLandmarks.length; i++) {
81
- if (results.multiHandedness[i].label === "Right") {
82
- const landmarks = results.multiHandLandmarks[i];
83
- drawConnectors(canvasCtx, landmarks, Hands.HAND_CONNECTIONS, { color: '#00FF00', lineWidth: 4 });
84
- drawLandmarks(canvasCtx, landmarks, { color: '#FF0000', lineWidth: 2 });
85
- }
86
  }
87
  }
88
- canvasCtx.restore();
89
-
90
- const now = Date.now();
91
- if (now - lastPredictionTime > 500) {
92
- lastPredictionTime = now;
93
- loadingSpan.style.display = 'inline';
94
- const imageBase64 = canvasElement.toDataURL('image/png');
95
- fetch('/predict', {
96
- method: 'POST',
97
- headers: { 'Content-Type': 'application/json' },
98
- body: JSON.stringify({ image: imageBase64 }),
 
 
 
 
 
99
  })
100
- .then(res => {
101
- if (!res.ok) throw new Error(`HTTP error: ${res.status}`);
102
- return res.json();
103
- })
104
- .then(data => {
105
- predictionText.textContent = data.prediction;
106
- })
107
- .catch(err => {
108
- console.error('Prediction error:', err);
109
- predictionText.textContent = 'Error: Prediction failed';
110
- })
111
- .finally(() => {
112
- loadingSpan.style.display = 'none';
113
- });
114
- }
115
- });
116
 
117
- console.log('Starting camera');
118
- const camera = new Camera(videoElement, {
119
- onFrame: async () => {
120
- await hands.send({ image: videoElement });
121
- },
122
- width: isMobile ? 480 : 640,
123
- height: isMobile ? 360 : 480,
124
- });
125
 
126
- camera.start().catch(err => {
127
- console.error('Camera failed to start:', err);
128
- predictionText.textContent = 'Error: Failed to start webcam. Check permissions.';
129
- });
 
 
 
 
 
 
 
 
 
130
  }
131
- });
 
 
1
+ function setupEventListeners() {
2
  const topCard = document.getElementById('top-card');
3
  const enableWebcamBtn = document.getElementById('enable-webcam-btn');
4
  const predictionDiv = document.getElementById('prediction');
 
13
  return;
14
  }
15
 
16
+ // Remove existing listeners to prevent duplicates
17
+ enableWebcamBtn.removeEventListener('click', handleWebcamClick);
18
+ enableWebcamBtn.removeEventListener('touchstart', handleWebcamClick);
19
+
20
+ // Add click and touchstart listeners for desktop and mobile
21
+ enableWebcamBtn.addEventListener('click', handleWebcamClick);
22
+ enableWebcamBtn.addEventListener('touchstart', handleWebcamClick);
23
+
24
+ function handleWebcamClick(event) {
25
+ event.preventDefault(); // Prevent default touch/click behavior
26
+ console.log('Enable Webcam button activated (click or touch)');
27
+ alert('Webcam button clicked!'); // Test responsiveness
28
  topCard.innerHTML = `
29
  <div id="container">
30
  <video id="input_video" autoplay muted playsinline></video>
 
32
  </div>
33
  `;
34
  console.log('Video and canvas elements added to DOM');
35
+ setTimeout(() => initMediaPipe(), 200); // Increased delay for DOM update
36
+ }
37
 
38
+ if (clearBtn) {
39
+ clearBtn.addEventListener('click', () => {
40
+ console.log('Clear button clicked');
41
+ predictionText.textContent = 'None';
42
+ loadingSpan.style.display = 'none';
43
+ });
44
+ }
45
 
46
+ if (listenBtn) {
47
+ listenBtn.addEventListener('click', () => {
48
+ console.log('Listen button clicked');
49
+ alert('Listen functionality not implemented yet');
50
+ });
51
+ }
52
+ }
53
 
54
+ function initMediaPipe() {
55
+ const videoElement = document.getElementById('input_video');
56
+ const canvasElement = document.getElementById('output_canvas');
57
+ const canvasCtx = canvasElement.getContext('2d');
58
+ const predictionText = document.getElementById('prediction-text');
59
+ const loadingSpan = document.getElementById('loading');
60
 
61
+ if (!videoElement || !canvasElement || !canvasCtx) {
62
+ console.error('Required elements not found:', { videoElement, canvasElement, canvasCtx });
63
+ predictionText.textContent = 'Error: Video or canvas not found';
64
+ return;
65
+ }
66
 
67
+ console.log('Initializing MediaPipe Hands');
68
+ const isMobile = window.innerWidth <= 700;
69
+ canvasElement.width = isMobile ? 480 : 640;
70
+ canvasElement.height = isMobile ? 360 : 480;
71
 
72
+ const hands = new Hands({
73
+ locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/hands@0.4/${file}`
74
+ });
75
 
76
+ hands.setOptions({
77
+ maxNumHands: 2,
78
+ minDetectionConfidence: 0.7,
79
+ minTrackingConfidence: 0.7,
80
+ });
81
 
82
+ let lastPredictionTime = 0;
83
 
84
+ hands.onResults((results) => {
85
+ if (!results.image) {
86
+ console.warn('No video frame received from MediaPipe');
87
+ predictionText.textContent = 'Error: No video frame received';
88
+ loadingSpan.style.display = 'none';
89
+ return;
90
+ }
91
+
92
+ canvasCtx.save();
93
+ canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
94
+ canvasCtx.drawImage(results.image, 0, 0, canvasElement.width, canvasElement.height);
95
 
96
+ if (results.multiHandLandmarks && results.multiHandedness) {
97
+ for (let i = 0; i < results.multiHandLandmarks.length; i++) {
98
+ if (results.multiHandedness[i].label === "Right") {
99
+ const landmarks = results.multiHandLandmarks[i];
100
+ drawConnectors(canvasCtx, landmarks, Hands.HAND_CONNECTIONS, { color: '#00FF00', lineWidth: 4 });
101
+ drawLandmarks(canvasCtx, landmarks, { color: '#FF0000', lineWidth: 2 });
 
 
 
 
 
102
  }
103
  }
104
+ }
105
+ canvasCtx.restore();
106
+
107
+ const now = Date.now();
108
+ if (now - lastPredictionTime > 500) {
109
+ lastPredictionTime = now;
110
+ loadingSpan.style.display = 'inline';
111
+ const imageBase64 = canvasElement.toDataURL('image/png');
112
+ fetch('/predict', {
113
+ method: 'POST',
114
+ headers: { 'Content-Type': 'application/json' },
115
+ body: JSON.stringify({ image: imageBase64 }),
116
+ })
117
+ .then(res => {
118
+ if (!res.ok) throw new Error(`HTTP error: ${res.status}`);
119
+ return res.json();
120
  })
121
+ .then(data => {
122
+ predictionText.textContent = data.prediction;
123
+ })
124
+ .catch(err => {
125
+ console.error('Prediction error:', err);
126
+ predictionText.textContent = 'Error: Prediction failed';
127
+ })
128
+ .finally(() => {
129
+ loadingSpan.style.display = 'none';
130
+ });
131
+ }
132
+ });
 
 
 
 
133
 
134
+ console.log('Starting camera');
135
+ const camera = new Camera(videoElement, {
136
+ onFrame: async () => {
137
+ await hands.send({ image: videoElement });
138
+ },
139
+ width: isMobile ? 480 : 640,
140
+ height: isMobile ? 360 : 480,
141
+ });
142
 
143
+ camera.start().catch(err => {
144
+ console.error('Camera failed to start:', err);
145
+ predictionText.textContent = 'Error: Failed to start webcam. Check permissions.';
146
+ });
147
+ }
148
+
149
+ // Initial setup
150
+ setupEventListeners();
151
+
152
+ // Retry setup if DOM changes (e.g., dynamic reload)
153
+ const observer = new MutationObserver(() => {
154
+ if (document.getElementById('enable-webcam-btn')) {
155
+ setupEventListeners();
156
  }
157
+ });
158
+ observer.observe(document.body, { childList: true, subtree: true });