|
808 | 808 | // ── Speech Recognition (browser-native, no API key needed) ── |
809 | 809 | let speechRecognition = null; |
810 | 810 | let recognitionFinalTranscript = ''; |
| 811 | + let srFailCount = 0; |
811 | 812 |
|
812 | 813 | function startSpeechRecognition() { |
813 | 814 | try { |
814 | 815 | const SR = window.SpeechRecognition || window.webkitSpeechRecognition; |
815 | | - if (!SR) { fallbackStartRecording(); return; } |
| 816 | + if (!SR) { srFailCount++; setLiveState('idle'); return; } |
| 817 | + if (srFailCount > 3) { setLiveState('idle'); return; } |
816 | 818 | speechRecognition = new SR(); |
817 | 819 | speechRecognition.lang = 'en-US'; |
818 | 820 | speechRecognition.interimResults = false; |
|
829 | 831 | speechRecognition = null; |
830 | 832 | recognitionFinalTranscript = ''; |
831 | 833 | if (transcript && liveActive) { |
| 834 | + srFailCount = 0; |
832 | 835 | processTranscript(transcript); |
833 | 836 | } else if (liveActive) { |
| 837 | + srFailCount++; |
834 | 838 | startLiveLoop(); |
835 | 839 | } |
836 | 840 | }; |
837 | 841 |
|
838 | 842 | speechRecognition.onerror = (event) => { |
839 | 843 | speechRecognition = null; |
840 | | - if (event.error === 'no-speech' || event.error === 'aborted') { |
841 | | - if (liveActive) startLiveLoop(); |
842 | | - return; |
843 | | - } |
| 844 | + srFailCount++; |
844 | 845 | console.error('Speech recognition error:', event.error); |
845 | | - fallbackStartRecording(); |
| 846 | + if (liveActive) startLiveLoop(); |
846 | 847 | }; |
847 | 848 |
|
848 | 849 | speechRecognition.start(); |
849 | 850 | } catch (e) { |
850 | | - fallbackStartRecording(); |
| 851 | + srFailCount++; |
| 852 | + if (liveActive) startLiveLoop(); |
851 | 853 | } |
852 | 854 | } |
853 | 855 |
|
854 | 856 | function stopSpeechRecognition() { |
855 | 857 | try { if (speechRecognition) { speechRecognition.abort(); speechRecognition = null; } } catch (e) {} |
856 | 858 | } |
857 | 859 |
|
858 | | - function fallbackStartRecording() { |
859 | | - if (liveActive) startRecording(); |
860 | | - } |
861 | | - |
862 | 860 | async function startRecording() { |
863 | 861 | const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); |
864 | 862 | recordingStream = stream; |
|
0 commit comments