WEBで音声操作
昔、「しゃべる!DSお料理ナビ」というゲームがあって調理中でも音声でレシピの手順を進める事が出来た。
今やDSは使わないけどiPadとかで音声操作できるブラウザがあったら便利かもと検索したら「Speech Recognition API」というJavaScriptのAPIが見つかったので試して見ることにした。
「Speech Recognition API」は昔は限られた環境でしか利用できなかったようですが最近はiOSでも使えるみたいなので試して見ました。
https://uda2.com/speechme/
右上のマイクボタン(音声操作START)を押すと音声操作が開始します。(非対応なブラウザではボタンが現れません。)
「次へ」で次のステップに進んで「戻る」で前のステップに戻って「終了」で音声認識を終了します。
recognition.interimResultsをtrueにする事で聞きながら音声解読するので反応が早くなります。
resultイベント(音声が確認できたら)の最後に毎度停止再開をしてるのはコマンドが短いのに「まだ何か言うかも」と待機するのを抑止する為です。
上の方法で永続化はされてるのですがスタートしてから5分間と任意でストップするまで永続化したかったのでタイマーを仕掛けて状態を維持するようにしています。
他に誤認識を考慮してワードをセレクトしています。
「戻る」は何度か「本」「婆」「保存」と謎な誤認識をされたので入れてます。
var speechme = () => {
const recbtnObj = document.getElementById('recbtn');
const recognition = new webkitSpeechRecognition() || new SpeechRecognition();
if (typeof recognition === 'undefined') return;
recbtnObj.style.display = "block";
var recognizing = false;
var rectime = 0;
recognition.interimResults = true;
recognition.maxAlternatives = 10;
recognition.addEventListener('result', function(event) {
const results = event.results;
let strs = [];
let command = "";
paragraph: for (let i = event.resultIndex; i < results.length; i++) {//文節(今回は0だけ)
for (let j = 0; j < results[i].length; j++){//候補
const result = results[i][j].transcript;
if (results[i].isFinal) {
recognition.stop();
recognizing = false;
}
strs.push({c: results[i][j].confidence, s: result});
if (result == "ストップ" || result == "止めて" || result == "停止" || result == "終了") command = "stop";
if (result == "次へ" || result == "次" || result == "月" || result == "進む" || result == "進んで" || result == "そんで" || result == "そして" || result == "それから" || result == "オッケー") command = "next";
if (result == "戻る" || result == "本" || result == "婆" || result == "保存" || result == "戻って" || result == "バック") command = "back";
if (command != "") break paragraph;
}
}
if (command == "stop") return recStop();
if (command == "next") stepxstep(1);
if (command == "back") stepxstep(-1);
//console.log(JSON.stringify(strs));
document.getElementById('debug').innerText = JSON.stringify(strs);
recognition.stop();
recognition.start();
});
recbtnObj.addEventListener('click', () => {
if (recbtn.textContent == 'START') {
rectime = Date.now();
recStart();
} else {
recStop();
}
});
recognition.addEventListener('start', () => {
recbtnObj.className = "online";
});
recognition.addEventListener('end', () => {
recbtnObj.className = "offline";
recognizing = false;
});
function recStop() {
recognition.stop();
recognizing = false;
recbtn.textContent = 'START';
}
function recStart() {
recognition.start();
recognizing = true;
recbtn.textContent = 'STOP';
}
setInterval(() => {
if (recbtn.textContent == 'STOP' && recognizing === false) {//録音状態なのにAPI停止
const mysec = Math.floor((Date.now() - rectime) / 1000);
if (mysec < 60*5) {
recognition.start();
recognizing = true;
} else {
recStop();
}
}
}, 1000);
};
speechme();
Tags: JavaScript, Speech Recognition API