Deepak Roshan commited on
Commit
549f96b
Β·
1 Parent(s): 38af066

fix: upgrade browser capture to 640x480, server encode to 85, and implement client-side TTS

Browse files
Files changed (2) hide show
  1. isl_detection.py +1 -1
  2. templates/dashboard.html +17 -8
isl_detection.py CHANGED
@@ -842,7 +842,7 @@ def core_processing_engine(shared_state, shm_name=None, frame_lock_val=None, fra
842
  # Send full 640Γ—480 frame β€” browser displays at native resolution.
843
  # Skeleton/overlay removed so JPEG compresses cleanly at quality 75.
844
  _, buffer_img = cv2.imencode(
845
- ".jpg", frame, [cv2.IMWRITE_JPEG_QUALITY, 75])
846
  frame_base64 = base64.b64encode(buffer_img.tobytes()).decode("utf-8")
847
 
848
  # ── State packet ───────────────────────────────────────────────
 
842
  # Send full 640Γ—480 frame β€” browser displays at native resolution.
843
  # Skeleton/overlay removed so JPEG compresses cleanly at quality 75.
844
  _, buffer_img = cv2.imencode(
845
+ ".jpg", frame, [cv2.IMWRITE_JPEG_QUALITY, 85])
846
  frame_base64 = base64.b64encode(buffer_img.tobytes()).decode("utf-8")
847
 
848
  # ── State packet ───────────────────────────────────────────────
templates/dashboard.html CHANGED
@@ -959,7 +959,7 @@
959
  }
960
  try {
961
  cameraStream = await navigator.mediaDevices.getUserMedia({
962
- video: { width: { ideal: 320 }, height: { ideal: 240 }, facingMode: 'user' },
963
  audio: false
964
  });
965
  videoElement = document.createElement('video');
@@ -970,21 +970,21 @@
970
  videoElement.style.position = 'absolute';
971
  videoElement.style.top = '-10000px';
972
  videoElement.style.left = '-10000px';
973
- videoElement.style.width = '320px';
974
- videoElement.style.height = '240px';
975
  videoElement.style.pointerEvents = 'none';
976
  document.body.appendChild(videoElement);
977
 
978
  videoElement.addEventListener('loadeddata', () => {
979
- captureCanvas.width = 320;
980
- captureCanvas.height = 240;
981
  if (!window.cameraInterval) {
982
  window.cameraInterval = setInterval(() => {
983
  // Skip if a frame is still being processed by server
984
  if (_frameInFlight) return;
985
  if (document.visibilityState === 'visible' && socket && socket.connected) {
986
- captureCtx.drawImage(videoElement, 0, 0, 320, 240);
987
- const frame = captureCanvas.toDataURL('image/jpeg', 0.5);
988
  _frameInFlight = true;
989
  socket.emit('browser_frame', { frame: frame.split(',')[1] });
990
  // Auto-release lock after 600ms even if no ack received
@@ -1160,7 +1160,16 @@
1160
  const sentence = document.getElementById('cur-sentence').textContent.trim();
1161
  const word = document.getElementById('cur-word').textContent.trim();
1162
  const text = sentence || (word !== 'β€”' ? word : '');
1163
- if (text && socket) socket.emit('command', { action: 'speak', text });
 
 
 
 
 
 
 
 
 
1164
  } else {
1165
  if (socket) socket.emit('command', { action });
1166
  }
 
959
  }
960
  try {
961
  cameraStream = await navigator.mediaDevices.getUserMedia({
962
+ video: { width: { ideal: 640 }, height: { ideal: 480 }, facingMode: 'user' },
963
  audio: false
964
  });
965
  videoElement = document.createElement('video');
 
970
  videoElement.style.position = 'absolute';
971
  videoElement.style.top = '-10000px';
972
  videoElement.style.left = '-10000px';
973
+ videoElement.style.width = '640px';
974
+ videoElement.style.height = '480px';
975
  videoElement.style.pointerEvents = 'none';
976
  document.body.appendChild(videoElement);
977
 
978
  videoElement.addEventListener('loadeddata', () => {
979
+ captureCanvas.width = 640;
980
+ captureCanvas.height = 480;
981
  if (!window.cameraInterval) {
982
  window.cameraInterval = setInterval(() => {
983
  // Skip if a frame is still being processed by server
984
  if (_frameInFlight) return;
985
  if (document.visibilityState === 'visible' && socket && socket.connected) {
986
+ captureCtx.drawImage(videoElement, 0, 0, 640, 480);
987
+ const frame = captureCanvas.toDataURL('image/jpeg', 0.7);
988
  _frameInFlight = true;
989
  socket.emit('browser_frame', { frame: frame.split(',')[1] });
990
  // Auto-release lock after 600ms even if no ack received
 
1160
  const sentence = document.getElementById('cur-sentence').textContent.trim();
1161
  const word = document.getElementById('cur-word').textContent.trim();
1162
  const text = sentence || (word !== 'β€”' ? word : '');
1163
+ if (text) {
1164
+ // Client-side Web Speech API Synthesis
1165
+ if ('speechSynthesis' in window) {
1166
+ window.speechSynthesis.cancel(); // Stop any currently speaking voice
1167
+ const utterance = new SpeechSynthesisUtterance(text);
1168
+ utterance.lang = 'en-US';
1169
+ window.speechSynthesis.speak(utterance);
1170
+ }
1171
+ if (socket) socket.emit('command', { action: 'speak', text });
1172
+ }
1173
  } else {
1174
  if (socket) socket.emit('command', { action });
1175
  }