Anthony Chao

JS30 day20 Speech Recognition

#Javascript

JS30 day20 - Speech Recognition

作業內容

今天的作業內容我也覺得很有趣,是語音辨識!把講出來的話直接印在網頁上!

學到什麼

  • JS

    1. 語音辨識目前似乎只有桌機版的 Chrome 有實作,原作者這樣寫的目的好像是為了抓到 FireFox 實作的語音辨識,但我們其實用下面的寫法就好了
    window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
    
    const recognition = new SpeechRecognition()
    // 上面可以直接改成這樣 (只適用在 Chrome)
    const recognition = new webkitSpeechRecognition()
    1. 這個物件比較常用的兩個屬性分別是決定語言還有是否即時辨識
    const recognition = new SpeechRecognition()
    recognition.interimResults = true //即時辨識 false 代表講完話才開始辨識
    recognition.lang = 'en-US';
    1. 語音物件的格式滿複雜的,我們要的東西(文字)藏在 event 的 results 第一個項目的 transcript 中,所以我們先把它轉陣列用 map 方法取出,最後轉成字串 result 這個 event 只存在 SpeechRecognition 物件中,只要有文字被辨識出並回傳到 app 就會觸發這個事件
    recognition.addEventListener('result', e =>{
      const transcript = Array.from(e.results)
        .map(result => result[0])
        .map(result => result.transcript)
        .join('')
    })

    下面這張圖表示 e.results 的格式 參考資料: SpeechRecognition: result event

    1. isFinal 這個屬性看這個結果是不是最後回傳值,如果是 false 表示這個結果只是暫時的,還會繼續被更新
    p.textContent = transcript
    if(e.results[0].isFinal){
      p = document.createElement('p')
      words.appendChild(p)
    }
    console.log(transcript)

    參考資料:SpeechRecognitionResult.isFinal

    1. 如果單單只有一行 recognition.start() ,在聽完一句話就結束了,必須去監聽 end 事件 end 事件是當語音識別物件與語音識別伺服器結束連結時觸發,因此才可以讓監聽的效果一直不間斷
    recognition.addEventListener('end', recognition.start)
    recognition.start();

    參考資料: https://ithelp.ithome.com.tw/articles/10196487

參考資料: https://github.com/wesbos/JavaScript30

code 內容: HTML:

<div class="words" contenteditable></div>

CSS:

html {
  font-size: 10px;
}

body {
  background: #ffc600;
  font-family: 'helvetica neue';
  font-weight: 200;
  font-size: 20px;
}

.words {
  max-width: 500px;
  margin: 50px auto;
  background: white;
  border-radius: 5px;
  box-shadow: 10px 10px 0 rgba(0,0,0,0.1);
  padding: 1rem 2rem 1rem 5rem;
  background: -webkit-gradient(linear, 0 0, 0 100%, from(#d9eaf3), color-stop(4%, #fff)) 0 4px;
  background-size: 100% 3rem;
  position: relative;
  line-height: 3rem;
}

p {
  margin: 0 0 3rem;
}

.words:before {
  content: '';
  position: absolute;
  width: 4px;
  top: 0;
  left: 30px;
  bottom: 0;
  border: 1px solid;
  border-color: transparent #efe4e4;
}

JS:

window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;

const recognition = new SpeechRecognition()
recognition.interimResults = true //即時辨識 false 代表講完話才開始辨識
recognition.lang = 'en-US';

let p = document.createElement('p')
const words = document.querySelector('.words')
words.appendChild(p)

recognition.addEventListener('result', e =>{
  // console.log(e.results);
  const transcript = Array.from(e.results)
    .map(result => result[0])
    .map(result => result.transcript)
    .join('')

  p.textContent = transcript
  if(e.results[0].isFinal){
    p = document.createElement('p')
    words.appendChild(p)
  }
  console.log(transcript)
})
recognition.addEventListener('end', recognition.start)
recognition.start();