以下動作建議在 localHost 操作,不然可能發生無法正常運作
成品連結:Speech Detection、操作前程式碼、完成後程式碼
今天要做的是即時語音辨識功能,你可以一邊說話畫面上會一邊印出你所說的話。感覺很難但其實不會(比起昨天的 web cam)!
這是今天的主角,也因為有它才能實現今天的成品。這隻 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);
}
});
到這裡就完成啦!接下來你可以試著新增一些功能,像是在說出特定的話時顯示特定的字等等。不知不覺就會在這上面玩很久了呢...