Abdalkaderdev commited on
Commit
15307bb
·
1 Parent(s): fc3eead

Fix voice interface - restore browser speech recognition

Browse files
Files changed (1) hide show
  1. frontend/app/voice/page.tsx +22 -60
frontend/app/voice/page.tsx CHANGED
@@ -15,66 +15,31 @@ export default function OraVoice() {
15
  const audioChunksRef = useRef<Blob[]>([]);
16
 
17
  useEffect(() => {
18
- // Whisper-based recording will replace browser STT
19
- // No need for webkitSpeechRecognition anymore
20
- }, []);
21
-
22
- const startWhisperRecording = async () => {
23
- try {
24
- setState("LISTENING");
25
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
26
- const recorder = new MediaRecorder(stream);
27
-
28
- audioChunksRef.current = [];
29
-
30
- recorder.ondataavailable = (e) => {
31
- audioChunksRef.current.push(e.data);
32
- };
33
-
34
- recorder.onstop = async () => {
35
- const audioBlob = new Blob(audioChunksRef.current, { type: 'audio/wav' });
36
- const reader = new FileReader();
37
-
38
- reader.onloadend = async () => {
39
- const base64Audio = (reader.result as string).split(',')[1];
40
-
41
- // Send to Whisper for transcription
42
- const res = await fetch("/api/transcribe", {
43
- method: "POST",
44
- headers: { "Content-Type": "application/json" },
45
- body: JSON.stringify({ audio_data: base64Audio }),
46
- });
47
-
48
- const data = await res.json();
49
- setTranscript(data.text);
50
- handleSend(data.text);
51
  };
52
 
53
- reader.readAsDataURL(audioBlob);
54
- stream.getTracks().forEach(track => track.stop());
55
- };
56
-
57
- recorder.start();
58
- mediaRecorderRef.current = recorder;
59
-
60
- // Auto-stop after 10 seconds
61
- setTimeout(() => {
62
- if (mediaRecorderRef.current?.state === "recording") {
63
- mediaRecorderRef.current.stop();
64
- }
65
- }, 10000);
66
-
67
- } catch (error) {
68
- console.error("Recording error:", error);
69
- setState("IDLE");
70
- }
71
- };
72
 
73
- const stopWhisperRecording = () => {
74
- if (mediaRecorderRef.current?.state === "recording") {
75
- mediaRecorderRef.current.stop();
76
  }
77
- };
78
 
79
  const handleSend = async (text: string) => {
80
  setState("THINKING");
@@ -149,11 +114,8 @@ export default function OraVoice() {
149
 
150
  const toggleListen = () => {
151
  if (state === "IDLE") {
152
- startWhisperRecording();
153
- } else if (state === "LISTENING") {
154
- stopWhisperRecording();
155
  } else if (state === "SPEAKING") {
156
- // Audio will stop naturally
157
  setState("IDLE");
158
  }
159
  };
 
15
  const audioChunksRef = useRef<Blob[]>([]);
16
 
17
  useEffect(() => {
18
+ // Initialize browser Speech Recognition as fallback
19
+ if (typeof window !== "undefined") {
20
+ const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition;
21
+ if (SpeechRecognition) {
22
+ const recognition = new SpeechRecognition();
23
+ recognition.continuous = false;
24
+ recognition.lang = "en-US";
25
+ recognition.interimResults = false;
26
+
27
+ recognition.onstart = () => setState("LISTENING");
28
+
29
+ recognition.onresult = (event: any) => {
30
+ const text = event.results[0][0].transcript;
31
+ setTranscript(text);
32
+ handleSend(text);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  };
34
 
35
+ recognition.onend = () => {
36
+ if (state === "LISTENING") setState("IDLE");
37
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
+ recognitionRef.current = recognition;
40
+ }
 
41
  }
42
+ }, []);
43
 
44
  const handleSend = async (text: string) => {
45
  setState("THINKING");
 
114
 
115
  const toggleListen = () => {
116
  if (state === "IDLE") {
117
+ recognitionRef.current?.start();
 
 
118
  } else if (state === "SPEAKING") {
 
119
  setState("IDLE");
120
  }
121
  };