Spaces:
Running
Running
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Mobius Rover ('S.A.N.J.A.Y')</title> | |
<style> | |
body { | |
margin: 0; | |
background-color: black; | |
overflow: hidden; | |
height: 100vh; | |
position: relative; | |
color: #0A74DA; | |
font-family: Arial, sans-serif; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
flex-direction: column; | |
} | |
video { | |
position: fixed; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
width: 100%; | |
height: auto; | |
z-index: -1; | |
} | |
.container { | |
max-width: 600px; | |
margin: auto; | |
position: relative; | |
z-index: 2; | |
} | |
button { | |
margin-top: 10px; | |
padding: 10px; | |
background-color: #0A74DA; | |
color: white; | |
border: none; | |
cursor: pointer; | |
border-radius: 5px; | |
} | |
button:hover { | |
background-color: #084a8d; | |
} | |
select { | |
margin-top: 10px; | |
} | |
.status { | |
margin-top: 20px; | |
color: #0A74DA; | |
font-weight: bold; | |
text-align: center; | |
} | |
.error-message { | |
color: red; | |
text-align: center; | |
} | |
</style> | |
</head> | |
<body> | |
<video id="background-video" autoplay muted loop> | |
<source src="videos/original-b507b736387559b36766da23936f214d.mp4" type="video/mp4"> | |
Your browser does not support the video tag. | |
</video> | |
<div class="container"> | |
<div class="app-container"> | |
<div class="headings-container"> | |
<h1>Mobius Rover ('S.A.N.J.A.Y')</h1> | |
</div> | |
<div class="interaction-container"> | |
<div class="status" id="status-display">Initializing voice assistant...</div> | |
<div class="error-message" id="error-display"></div> | |
<div> | |
<label for="language-select">Select Language:</label> | |
<select id="language-select"> | |
<option value="en-US">English</option> | |
<option value="hi-IN">Hindi</option> | |
<option value="te-IN">Telugu</option> | |
</select> | |
</div> | |
<div> | |
<h3>Recognition Result:</h3> | |
<p id="result"></p> | |
</div> | |
<div class="api-response" id="api-response"> | |
<h3>Bot Response:</h3> | |
<pre id="api-response-content"></pre> | |
</div> | |
<div> | |
<button onclick="requestMicrophonePermission()">Request Microphone</button> | |
<button onclick="resetAssistant()">Reset Assistant</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
let speechSynth = window.speechSynthesis; | |
let recognition = null; | |
const wakeWord = 'sanjay'; | |
let isListeningForCommand = false; | |
let retryCount = 0; | |
const MAX_RETRY_ATTEMPTS = 3; | |
function displayStatus(message, isError = false) { | |
const statusDisplay = document.getElementById('status-display'); | |
const errorDisplay = document.getElementById('error-display'); | |
statusDisplay.textContent = message; | |
if (isError) { | |
errorDisplay.textContent = message; | |
console.error(message); | |
} else { | |
errorDisplay.textContent = ''; | |
} | |
} | |
function convertTextToSpeech(text) { | |
return new Promise((resolve, reject) => { | |
if (!text || text.trim().length === 0) { | |
resolve(); | |
return; | |
} | |
const utterance = new SpeechSynthesisUtterance(text); | |
const languageCode = document.getElementById('language-select').value; | |
utterance.lang = languageCode; | |
utterance.onstart = () => { | |
displayStatus('Speaking...'); | |
}; | |
utterance.onend = () => { | |
displayStatus('Waiting for wake word...'); | |
resolve(); | |
}; | |
utterance.onerror = (error) => { | |
displayStatus('Speech synthesis error', true); | |
reject(error); | |
}; | |
speechSynth.speak(utterance); | |
}); | |
} | |
function initializeSpeechRecognition() { | |
// Check browser support | |
if (!('SpeechRecognition' in window || 'webkitSpeechRecognition' in window)) { | |
displayStatus('Speech recognition not supported', true); | |
return null; | |
} | |
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; | |
const newRecognition = new SpeechRecognition(); | |
newRecognition.continuous = true; | |
newRecognition.interimResults = false; | |
newRecognition.maxAlternatives = 1; | |
const languageCode = document.getElementById('language-select').value; | |
newRecognition.lang = languageCode; | |
return newRecognition; | |
} | |
function startWakeWordDetection() { | |
try { | |
// Stop existing recognition if any | |
if (recognition) { | |
try { | |
recognition.stop(); | |
} catch(e) { | |
// Ignore stopping errors | |
} | |
} | |
recognition = initializeSpeechRecognition(); | |
if (!recognition) return; | |
displayStatus('Listening for wake word...'); | |
recognition.onresult = function(event) { | |
const result = event.results[event.results.length - 1][0].transcript.toLowerCase(); | |
document.getElementById('result').innerText = result; | |
if (!isListeningForCommand && result.includes(wakeWord)) { | |
isListeningForCommand = true; | |
displayStatus('Wake word detected. How can I help?'); | |
convertTextToSpeech('Hello! How can I assist you?') | |
.then(() => startCommandRecognition()) | |
.catch(() => resetAssistant()); | |
} | |
}; | |
recognition.onerror = function(event) { | |
displayStatus(`Recognition Error: ${event.error}`, true); | |
if (retryCount < MAX_RETRY_ATTEMPTS) { | |
retryCount++; | |
setTimeout(startWakeWordDetection, 1000); | |
} else { | |
resetAssistant(); | |
} | |
}; | |
recognition.onend = function() { | |
if (!isListeningForCommand) { | |
try { | |
recognition.start(); | |
} catch(e) { | |
displayStatus('Failed to restart recognition', true); | |
resetAssistant(); | |
} | |
} | |
}; | |
recognition.start(); | |
} catch(error) { | |
displayStatus('Failed to start wake word detection', true); | |
resetAssistant(); | |
} | |
} | |
function startCommandRecognition() { | |
try { | |
if (recognition) { | |
recognition.stop(); | |
} | |
recognition = initializeSpeechRecognition(); | |
if (!recognition) return; | |
displayStatus('Listening for command...'); | |
recognition.onresult = function(event) { | |
const result = event.results[event.results.length - 1][0].transcript.toLowerCase(); | |
document.getElementById('result').innerText = result; | |
fetchApiResponse(result); | |
}; | |
recognition.onerror = function(event) { | |
displayStatus(`Recognition Error: ${event.error}`, true); | |
resetAssistant(); | |
}; | |
recognition.onend = function() { | |
isListeningForCommand = false; | |
startWakeWordDetection(); | |
}; | |
recognition.start(); | |
} catch(error) { | |
displayStatus('Failed to start command recognition', true); | |
resetAssistant(); | |
} | |
} | |
function fetchApiResponse(query) { | |
const apiUrl = `https://srivatsavdamaraju2-l-u-c-i.hf.space/ask/${encodeURIComponent(query)}`; | |
fetch(apiUrl) | |
.then(response => response.json()) | |
.then(data => { | |
const apiResponseText = data.response; | |
document.getElementById('api-response-content').textContent = JSON.stringify(data, null, 2); | |
convertTextToSpeech(apiResponseText) | |
.then(() => resetAssistant()) | |
.catch(() => resetAssistant()); | |
}) | |
.catch(error => { | |
displayStatus('Error fetching API response', true); | |
document.getElementById('api-response-content').textContent = "Error fetching API response."; | |
resetAssistant(); | |
}); | |
} | |
function requestMicrophonePermission() { | |
navigator.mediaDevices.getUserMedia({ audio: true }) | |
.then(() => { | |
displayStatus('Microphone access granted'); | |
resetAssistant(); | |
}) | |
.catch(error => { | |
displayStatus('Microphone access denied', true); | |
}); | |
} | |
function resetAssistant() { | |
if (recognition) { | |
try { | |
recognition.stop(); | |
} catch(e) { | |
// Ignore stopping errors | |
} | |
} | |
if (speechSynth.speaking) { | |
speechSynth.cancel(); | |
} | |
isListeningForCommand = false; | |
retryCount = 0; | |
startWakeWordDetection(); | |
} | |
// Initialize on page load | |
window.onload = function() { | |
// Check for browser support | |
if (!('SpeechRecognition' in window || 'webkitSpeechRecognition' in window)) { | |
displayStatus('Speech recognition not supported in this browser', true); | |
return; | |
} | |
// Request microphone permission on page load | |
requestMicrophonePermission(); | |
}; | |
// Handle voices loaded | |
window.speechSynthesis.onvoiceschanged = function() { | |
const voices = window.speechSynthesis.getVoices(); | |
}; | |
</script> | |
</body> | |
</html> |