73 lines
2.7 KiB
Plaintext
73 lines
2.7 KiB
Plaintext
---
|
|
import Layout from "../../layouts/Layout.astro";
|
|
---
|
|
<Layout title="DeepSpeech Streaming STT">
|
|
<h1>DeepSpeech Real-Time Transcription</h1>
|
|
<button id="startBtn">Start Listening</button>
|
|
<button id="stopBtn" disabled>Stop</button>
|
|
<div id="transcript"></div>
|
|
</Layout>
|
|
<script is:inline>
|
|
const startBtn = document.getElementById('startBtn');
|
|
const stopBtn = document.getElementById('stopBtn');
|
|
const transcriptDiv = document.getElementById('transcript');
|
|
|
|
let mediaStream;
|
|
let audioContext;
|
|
let processor;
|
|
let websocket;
|
|
|
|
startBtn.addEventListener('click', async () => {
|
|
try {
|
|
// Initialize WebSocket
|
|
websocket = new WebSocket('ws://localhost:3000');
|
|
|
|
websocket.onmessage = (event) => {
|
|
const data = JSON.parse(event.data);
|
|
transcriptDiv.innerHTML += data.transcript + (data.isFinal ? '<br>' : ' ');
|
|
};
|
|
|
|
// Get microphone
|
|
mediaStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
|
|
// Set up audio processing (16kHz, mono for DeepSpeech)
|
|
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
const source = audioContext.createMediaStreamSource(mediaStream);
|
|
|
|
// Resample to 16kHz (DeepSpeech requirement)
|
|
const downsampler = audioContext.createScriptProcessor(4096, 1, 1);
|
|
downsampler.onaudioprocess = (e) => {
|
|
const inputData = e.inputBuffer.getChannelData(0);
|
|
const pcm16 = new Int16Array(inputData.length);
|
|
|
|
for (let i = 0; i < inputData.length; i++) {
|
|
pcm16[i] = Math.max(-32768, Math.min(32767, inputData[i] * 32768));
|
|
}
|
|
|
|
if (websocket.readyState === WebSocket.OPEN) {
|
|
websocket.send(pcm16.buffer);
|
|
}
|
|
};
|
|
|
|
source.connect(downsampler);
|
|
downsampler.connect(audioContext.destination);
|
|
|
|
// Notify server to start processing
|
|
websocket.onopen = () => {
|
|
websocket.send('start');
|
|
startBtn.disabled = true;
|
|
stopBtn.disabled = false;
|
|
};
|
|
} catch (err) {
|
|
console.error('Error:', err);
|
|
}
|
|
});
|
|
|
|
stopBtn.addEventListener('click', () => {
|
|
if (mediaStream) mediaStream.getTracks().forEach(track => track.stop());
|
|
if (websocket) websocket.send('end');
|
|
|
|
startBtn.disabled = false;
|
|
stopBtn.disabled = true;
|
|
});
|
|
</script> |