|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8" /> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> |
|
<title>Speech Grammar Checker</title> |
|
<style> |
|
body { |
|
font-family: Arial, sans-serif; |
|
background: #f1f3f8; |
|
margin: 0; |
|
padding: 0; |
|
} |
|
header { |
|
background: #4a90e2; |
|
color: white; |
|
padding: 1em 2em; |
|
text-align: center; |
|
font-size: 1.5em; |
|
} |
|
.container { |
|
max-width: 700px; |
|
margin: 2em auto; |
|
background: white; |
|
padding: 2em; |
|
border-radius: 10px; |
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1); |
|
} |
|
textarea { |
|
width: 100%; |
|
height: 120px; |
|
padding: 1em; |
|
font-size: 1em; |
|
border: 1px solid #ccc; |
|
border-radius: 8px; |
|
resize: vertical; |
|
} |
|
button { |
|
background: #4a90e2; |
|
color: white; |
|
padding: 0.75em 1.5em; |
|
border: none; |
|
font-size: 1em; |
|
margin-top: 1em; |
|
border-radius: 6px; |
|
cursor: pointer; |
|
} |
|
button:hover { |
|
background: #3c7dcf; |
|
} |
|
.result { |
|
margin-top: 1.5em; |
|
background: #f9f9f9; |
|
border-left: 4px solid #4a90e2; |
|
padding: 1em; |
|
border-radius: 5px; |
|
font-size: 1em; |
|
white-space: pre-wrap; |
|
} |
|
footer { |
|
margin-top: 3em; |
|
text-align: center; |
|
color: #888; |
|
font-size: 0.9em; |
|
} |
|
input[type="file"] { |
|
margin-top: 1em; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
|
|
<header>🗣️ Speech Grammar Checker</header> |
|
|
|
<div class="container"> |
|
<label><strong>Type your sentence or upload speech audio:</strong></label> |
|
<textarea id="speechInput" placeholder="Enter your sentence..."></textarea> |
|
|
|
<input type="file" id="audioInput" accept="audio/*" /> |
|
<button onclick="checkGrammar()">Check Grammar</button> |
|
|
|
<div class="result" id="resultBox" style="display: none;"> |
|
<strong>✅ Results:</strong><br/><br/> |
|
<strong>Baseline:</strong> <div id="baselineText"></div><br/> |
|
<strong>Score:</strong> <div id="scoreText"></div><br/> |
|
<strong>Improved:</strong> <div id="improvedText"></div> |
|
</div> |
|
</div> |
|
|
|
<footer> |
|
Made with ❤️ using Hugging Face | Rookus.ai |
|
</footer> |
|
|
|
<script> |
|
|
|
function transcribeSpeech() { |
|
return new Promise((resolve, reject) => { |
|
if (!('webkitSpeechRecognition' in window)) { |
|
reject('Speech recognition not supported in this browser.'); |
|
return; |
|
} |
|
const recognition = new webkitSpeechRecognition(); |
|
recognition.lang = 'en-US'; |
|
recognition.interimResults = false; |
|
recognition.maxAlternatives = 1; |
|
|
|
recognition.onresult = (event) => { |
|
resolve(event.results[0][0].transcript); |
|
}; |
|
recognition.onerror = (event) => reject(event.error); |
|
|
|
recognition.start(); |
|
}); |
|
} |
|
|
|
|
|
async function checkGrammarWithLanguageTool(text) { |
|
const url = 'https://api.languagetool.org/v2/check'; |
|
const params = new URLSearchParams(); |
|
params.append('text', text); |
|
params.append('language', 'en-US'); |
|
|
|
const response = await fetch(url, { |
|
method: 'POST', |
|
body: params, |
|
headers: { |
|
'Content-Type': 'application/x-www-form-urlencoded', |
|
}, |
|
}); |
|
return await response.json(); |
|
} |
|
|
|
|
|
function parseLanguageToolResult(text, result) { |
|
let correctedText = text; |
|
let offsetShift = 0; |
|
const matches = result.matches || []; |
|
|
|
matches.forEach((match) => { |
|
if (match.replacements && match.replacements.length > 0) { |
|
const replacement = match.replacements[0].value; |
|
const start = match.offset + offsetShift; |
|
const end = start + match.length; |
|
|
|
correctedText = |
|
correctedText.slice(0, start) + replacement + correctedText.slice(end); |
|
|
|
offsetShift += replacement.length - match.length; |
|
} |
|
}); |
|
|
|
const score = 100 - Math.min(100, matches.length * 10); |
|
return { correctedText, score }; |
|
} |
|
|
|
async function checkGrammar() { |
|
const textInput = document.getElementById("speechInput").value.trim(); |
|
const audioInput = document.getElementById("audioInput").files[0]; |
|
const resultBox = document.getElementById("resultBox"); |
|
const baselineText = document.getElementById("baselineText"); |
|
const scoreText = document.getElementById("scoreText"); |
|
const improvedText = document.getElementById("improvedText"); |
|
|
|
resultBox.style.display = "block"; |
|
baselineText.innerText = "⏳ Loading..."; |
|
scoreText.innerText = ""; |
|
improvedText.innerText = ""; |
|
|
|
try { |
|
let text; |
|
|
|
if (audioInput) { |
|
|
|
|
|
text = await transcribeSpeech(); |
|
document.getElementById("speechInput").value = text; |
|
} else if (textInput) { |
|
text = textInput; |
|
} else { |
|
baselineText.innerText = "Please enter text or upload audio."; |
|
return; |
|
} |
|
|
|
baselineText.innerText = text; |
|
|
|
const result = await checkGrammarWithLanguageTool(text); |
|
const { correctedText, score } = parseLanguageToolResult(text, result); |
|
|
|
scoreText.innerText = `${score}%`; |
|
improvedText.innerText = correctedText; |
|
|
|
} catch (error) { |
|
baselineText.innerText = "❌ Error processing input."; |
|
console.error(error); |
|
} |
|
} |
|
</script> |
|
|
|
|
|
</body> |
|
</html> |