JS30 day20 Speech Recognition

Posted by Anthony Chao on 2019-11-21

JS30 day20 - Speech Recognition

作業內容

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

學到什麼

  • JS

    1. 語音辨識目前似乎只有桌機版的 Chrome 有實作,原作者這樣寫的目的好像是為了抓到 FireFox 實作的語音辨識,但我們其實用下面的寫法就好了
    1
    2
    3
    4
    5
    window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;

    const recognition = new SpeechRecognition()
    // 上面可以直接改成這樣 (只適用在 Chrome)
    const recognition = new webkitSpeechRecognition()
    1. 這個物件比較常用的兩個屬性分別是決定語言還有是否即時辨識
    1
    2
    3
    const recognition = new SpeechRecognition()
    recognition.interimResults = true //即時辨識 false 代表講完話才開始辨識
    recognition.lang = 'en-US';
    1. 語音物件的格式滿複雜的,我們要的東西(文字)藏在 event 的 results 第一個項目的 transcript 中,所以我們先把它轉陣列用 map 方法取出,最後轉成字串
      result 這個 event 只存在 SpeechRecognition 物件中,只要有文字被辨識出並回傳到 app 就會觸發這個事件
    1
    2
    3
    4
    5
    6
    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 表示這個結果只是暫時的,還會繼續被更新
    1
    2
    3
    4
    5
    6
    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 事件是當語音識別物件與語音識別伺服器結束連結時觸發,因此才可以讓監聽的效果一直不間斷
    1
    2
    recognition.addEventListener('end', recognition.start)
    recognition.start();

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

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

code 內容:
HTML:

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

CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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();




prevent_hack