testcppp / index.html
Charan5775's picture
Create index.html
aa44aee verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Whisper.cpp Live STT</title>
<style>
body {
font-family: Arial, sans-serif;
background: #0f172a;
color: #e5e7eb;
display: flex;
flex-direction: column;
align-items: center;
padding: 30px;
}
h1 {
margin-bottom: 10px;
}
.controls {
margin: 20px 0;
}
button {
margin: 0 10px;
padding: 10px 20px;
border-radius: 8px;
border: none;
cursor: pointer;
font-size: 16px;
}
#startBtn {
background: #22c55e;
color: #022c22;
}
#stopBtn {
background: #ef4444;
color: #fee2e2;
}
#status {
margin-top: 10px;
font-size: 14px;
opacity: 0.8;
}
#output {
margin-top: 20px;
width: 100%;
max-width: 700px;
min-height: 200px;
border-radius: 10px;
padding: 15px;
background: #020617;
box-shadow: 0 0 0 1px #1f2937 inset;
white-space: pre-wrap;
overflow-y: auto;
}
</style>
</head>
<body>
<h1>Whisper.cpp Live Speech-to-Text</h1>
<p>Click start, allow mic access, and speak. Partial transcripts will appear below.</p>
<div class="controls">
<button id="startBtn">🎤 Start</button>
<button id="stopBtn" disabled>⛔ Stop</button>
</div>
<div id="status">Status: idle</div>
<pre id="output"></pre>
<script>
let socket = null;
let mediaRecorder = null;
let isRecording = false;
const statusEl = document.getElementById("status");
const outputEl = document.getElementById("output");
const startBtn = document.getElementById("startBtn");
const stopBtn = document.getElementById("stopBtn");
function logStatus(text) {
statusEl.textContent = "Status: " + text;
console.log("[STATUS]", text);
}
function appendText(text) {
outputEl.textContent += text + "\n";
outputEl.scrollTop = outputEl.scrollHeight;
}
function createWebSocket() {
// Build ws/wss URL from current location (works local + HF Space)
const wsUrl = (location.origin.replace(/^http/, "ws") + "/ws/transcribe_stream");
console.log("Connecting to", wsUrl);
socket = new WebSocket(wsUrl);
socket.onopen = () => {
logStatus("WebSocket connected, mic ready");
};
socket.onmessage = (event) => {
const msg = event.data;
appendText(msg);
};
socket.onerror = (err) => {
console.error("WebSocket error:", err);
logStatus("WebSocket error");
};
socket.onclose = () => {
logStatus("WebSocket closed");
};
}
async function startRecording() {
if (isRecording) return;
// Make sure WebSocket exists and open
if (!socket || socket.readyState !== WebSocket.OPEN) {
createWebSocket();
// Wait briefly for connect (simple version)
await new Promise((resolve) => setTimeout(resolve, 500));
}
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const options = { mimeType: "audio/webm;codecs=opus" };
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
alert("WebM/Opus not supported in this browser.");
return;
}
mediaRecorder = new MediaRecorder(stream, options);
mediaRecorder.onstart = () => {
isRecording = true;
startBtn.disabled = true;
stopBtn.disabled = false;
logStatus("Recording...");
};
mediaRecorder.ondataavailable = (event) => {
if (event.data && event.data.size > 0 && socket && socket.readyState === WebSocket.OPEN) {
event.data.arrayBuffer().then((buffer) => {
socket.send(buffer); // send binary audio chunk
});
}
};
mediaRecorder.onstop = () => {
isRecording = false;
startBtn.disabled = false;
stopBtn.disabled = true;
logStatus("Recording stopped");
};
// send chunks every 500ms
mediaRecorder.start(500);
} catch (err) {
console.error("Error starting microphone:", err);
logStatus("Mic permission denied or error");
}
}
function stopRecording() {
if (!isRecording || !mediaRecorder) return;
mediaRecorder.stop();
if (socket && socket.readyState === WebSocket.OPEN) {
// Tell server we are done
socket.send("__END__");
}
}
startBtn.addEventListener("click", startRecording);
stopBtn.addEventListener("click", stopRecording);
</script>
</body>
</html>