iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 20
0

以下動作建議在 localHost 操作,不然可能發生無法正常運作

成品連結:Speech Detection操作前程式碼完成後程式碼

今天要做的是即時語音辨識功能,你可以一邊說話畫面上會一邊印出你所說的話。感覺很難但其實不會(比起昨天的 web cam)!

Web Speech API

這是今天的主角,也因為有它才能實現今天的成品。這隻 API 是瀏覽器內建的,但不幸的是只有在 Chrome 上可以成功執行。假如你沒有使用 Chrome 可能要請你安裝一下才能成功使用囉!

首先要設定使用環境

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

這段在程式碼已經打好了,後面的 webkit- 前綴是為了支援 Chrome(這功能仍不是原生支援,需要加上前綴)

接著寫入:

const recognition = new SpeechRecognition();
recognition.lang = 'cmn-Hant-TW';
// recognition.lang = 'en-US';
recognition.interimResults = true;

recognition 就是接下來我們要操作的元素了

recognition.lang 指定使用的語言,上面我寫的是中文,如果要英文就填入 en-US參考連結有完整的支援語言列表

recognition.interimResults 指定是否要及時提供結果,如果要則 assign true,但如果要等到整句話說完才提供結果則設為 false

建立 p 並加入到 HTML

這裡顯示結果的方式是將結果放到 p tag 當中,每一句話都是一行

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

這裡為何使用 let 而不是 const 等一下會再說明~

處理結果

剛剛已經先宣告 recognition 了,我們可以透過它的方法來開始語音辨識

// global
recognition.start();

接著我們要處理辨識後的結果

recognition.addEventListener('result', function(e) {
    // code here
});

如果你試著印出 e,會發現 e.results 當中有辨識後的結果(包含說話是否已結束、辨識信心度以及辨識文字),而我們要放在 p tag 中的就是辨識文字(transcript)。

e.results 的結果

要取出辨識文字你可以這樣做,並放入 p tag

recognition.addEventListener('result', function(e) {
    const transcript = e.results[0][0].transcript;
    
    p.textContent = transcript;
});

上面的方法適用當你只需要 transcripy 一個東西時;但假如在某一層會需要特別的操作,則要一層一層的抽絲剝繭至 transcript。但由於 e.results 不是 array,為了要使用 array 的方法,要先將 e.results 轉型成 array

recognition.addEventListener('result', function(e) {
    const transcript = Array.from(e.results)
        .map(result => result[0])
        .map(result => result.transcript).join('');
    
    p.textContent = transcript;
});

上面的寫法之前有寫過了,為了避免宣告過多暫時的變數所以寫成一條長鍊。難起來很複雜,但其實就是一層一層深入至 transcript 並使用 join('') 將其合併成 string

至此功能大致具備了,但語音辨識預設為當 e.results[0].isFinal === true 時會執行 recognition.stop() 終止辨識,所以我們要在結束時再次執行語音辨識

// global
recognition.addEventListener('end', recognition.start);

記得 recognition.start 不要加小括號啊,不然會在 window 讀取時就執行。

接著你會發現畫面上的 p 的內容每次都會被刷新。為了解決這個情形,我們要在 e.results[0].isFinal === true(也就是一句話結束時)時創建新的 p tag,這也是為什麼剛剛宣告 p 要用 let,因為需要重複使用/賦值。我們要在 e.results[0].isFinal === true 時創新的 p tag 並放到 HTML 當中

recognition.addEventListener('result', function(e) {
    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);
    }
});

到這裡就完成啦!接下來你可以試著新增一些功能,像是在說出特定的話時顯示特定的字等等。不知不覺就會在這上面玩很久了呢...

Reference


上一篇
JS30 Day 19 - Webcam Fun
下一篇
JS30 Day 21 - Geolocation
系列文
一起挑戰 JavaScript 30 吧!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言