|
10 | 10 | <div class="words" contenteditable> |
11 | 11 | </div> |
12 | 12 |
|
| 13 | + <button class="start-button">Start</button> |
| 14 | + |
13 | 15 | <script> |
| 16 | + // We grab the SpeechRecognition object from the window |
| 17 | + // We use the webkit prefix for any browsers that don't support the unprefixed version |
14 | 18 | window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; |
15 | 19 |
|
| 20 | + if ( !window.SpeechRecognition ) { |
| 21 | + document.querySelector('.words').textContent = 'Speech recognition is not supported in this browser.'; |
| 22 | + document.querySelector('.start-button').disabled = true; |
| 23 | + throw new Error('SpeechRecognition not supported'); |
| 24 | + } |
| 25 | + |
| 26 | + // We create a new instance of SpeechRecognition |
| 27 | + const recognition = new SpeechRecognition(); |
| 28 | + |
| 29 | + // If we want to get interim results while we are speaking, we set the interimResults property to true |
| 30 | + // Otherwise, we will only get final results after speech recognition has finished processing |
| 31 | + recognition.interimResults = true; |
| 32 | + |
| 33 | + let stopped = false; |
| 34 | + |
| 35 | + // Create a new paragraph element and add it to the '.words' div |
| 36 | + let p = document.createElement('p'); |
| 37 | + const words = document.querySelector('.words'); |
| 38 | + words.appendChild(p); |
| 39 | + |
| 40 | + // We listen for the 'result' event on the recognition object |
| 41 | + // Which is fired when we get a result from the speech recognition |
| 42 | + // The event object contains a results property |
| 43 | + // Which is an array of all the results we have received so far |
| 44 | + recognition.addEventListener( 'result', event => { |
| 45 | + const transcript = Array.from( event.results ) |
| 46 | + .map( result => result[0] ) |
| 47 | + .map( result => result.transcript ) |
| 48 | + .join(''); |
| 49 | + |
| 50 | + // We set the text content of the paragraph to the transcript |
| 51 | + p.textContent = transcript; |
| 52 | + |
| 53 | + // If the result is final, we create a new paragraph element and add it to the '.words' div |
| 54 | + // Final means that the speech recognition has finished processing the audio and has a final result for us |
| 55 | + if ( event.results[event.resultIndex].isFinal ) { |
| 56 | + p = document.createElement('p'); |
| 57 | + words.appendChild(p); |
| 58 | + } |
| 59 | + |
| 60 | + // If the transcript includes the word 'stop', we set the stopped variable to true and stop the recognition |
| 61 | + if ( /\bstop\b/i.test(transcript) ) { |
| 62 | + stopped = true; |
| 63 | + recognition.stop(); |
| 64 | + } |
| 65 | + |
| 66 | + } ); |
| 67 | + |
| 68 | + // When we stop speaking, we want to start the recognition again so we can keep getting results |
| 69 | + // Otherwise, it will only work once and then stop |
| 70 | + recognition.addEventListener( 'end', () => { |
| 71 | + if ( false === stopped ) { |
| 72 | + recognition.start(); |
| 73 | + } |
| 74 | + } ); |
| 75 | + |
| 76 | + // We grab the start button and listen for a click event on it |
| 77 | + const startButton = document.querySelector('.start-button'); |
| 78 | + |
| 79 | + // On click, we set the stopped variable to false and start the recognition again |
| 80 | + // We also disable the start button so we can't click it again while the recognition is running |
| 81 | + startButton.addEventListener( 'click', () => { |
| 82 | + stopped = false; |
| 83 | + recognition.start(); |
| 84 | + startButton.disabled = true; |
| 85 | + } ); |
| 86 | + |
| 87 | + // We disable the start button when the recognition starts |
| 88 | + recognition.addEventListener( 'start', () => startButton.disabled = true ); |
| 89 | + |
| 90 | + // When the recognition ends, we check if the stopped variable is true |
| 91 | + // If it is, we enable the start button again so we can start the recognition again |
| 92 | + // So if the user has said 'stop', the recognition will stop and the start button will be enabled again |
| 93 | + recognition.addEventListener( 'end', () => { |
| 94 | + if ( true === stopped ) { |
| 95 | + startButton.disabled = false; |
| 96 | + } |
| 97 | + } ); |
| 98 | + |
| 99 | + // We listen for the 'error' event on the recognition object |
| 100 | + // Which is fired when there is an error with the speech recognition |
| 101 | + // If the error is 'not-allowed', it means that the user has denied access to the microphone |
| 102 | + // In that case, we set the text content of the '.words' div to a message telling the user to allow microphone access and refresh the page |
| 103 | + recognition.addEventListener( 'error', e => { |
| 104 | + if ( e.error === 'not-allowed' ) { |
| 105 | + words.textContent = 'Microphone access was denied. Please allow microphone access and refresh the page.'; |
| 106 | + startButton.disabled = true; |
| 107 | + } |
| 108 | + } ); |
| 109 | + |
| 110 | + // We start the recognition for the first time when the page loads |
| 111 | + recognition.start(); |
16 | 112 |
|
17 | 113 | </script> |
18 | 114 |
|
|
0 commit comments