import { useState, useRef } from 'react' export default function Home() { const [recording, setRecording] = useState(false) const [playing, setPlaying] = useState(false) const mediaRecorderRef = useRef(null) const audioChunksRef = useRef([]) const audioRef = useRef(null) async function startRecording() { if (!navigator.mediaDevices) return alert('No microphone available') const stream = await navigator.mediaDevices.getUserMedia({ audio: true }) const mr = new MediaRecorder(stream) mr.ondataavailable = (e) => audioChunksRef.current.push(e.data) mr.onstop = async () => { const blob = new Blob(audioChunksRef.current, { type: 'audio/webm' }) audioChunksRef.current = [] await sendAudio(blob) } mediaRecorderRef.current = mr audioChunksRef.current = [] mr.start() setRecording(true) } function stopRecording() { if (mediaRecorderRef.current && mediaRecorderRef.current.state !== 'inactive') { mediaRecorderRef.current.stop() setRecording(false) } } async function sendAudio(blob) { const form = new FormData() // Convert webm to wav on the client is complex; many servers accept webm/ogg. form.append('file', blob, 'recording.webm') const res = await fetch('http://localhost:8000/chat', { method: 'POST', body: form }) if (!res.ok) { const text = await res.text() alert('Error: ' + res.status + ' ' + text) return } const audioBlob = await res.blob() const url = URL.createObjectURL(audioBlob) if (audioRef.current) { audioRef.current.src = url audioRef.current.play() setPlaying(true) audioRef.current.onended = () => setPlaying(false) } } return (

Local Voice Assistant — Frontend

Press and hold the big button to record, or click to toggle.

Playback:

) }