🔰

SpeechRecognition/Synthesisでかんたんオウム返し

2021/09/12に公開

SpeechRecognition/Synthesisとは!?

SpeechRecognitioは、音声認識APIです。(ブラウザに向かって発した声を文字に変換します)
SpeechRecognition

SpeechSynthesisは、音声読み上げAPIです。(文字を音声として自動で読み上げます)
SpeechSynthesis

今回はこの2つのAPIを使い、オウム返しシステムを作ってみます。

プロジェクトを用意する

次の様にプロジェクトを作ります。

MyProject01/
 ├ index.html (プログラムを起動するファイルです)
 ├ main.js (メインのプログラムを記述するファイルです)

HTMLファイルを用意する

では、作っていきましょう。
HTMLファイルを用意して、下記コードを記述します。

index.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8"/>
	<script src="./main.js" defer></script>
</head>
<body>
	<button id="btnStart">開始</button>
	<button id="btnStop">停止</button>
	<ul id="txtResult"></ul>
</body>
</html>

HTMLには開始ボタンと停止ボタン、そして音声認識した内容を表示するエリアを用意しておきます。

JavaScriptファイルを用意する

次はメインのプログラムです。
ここからは、次の順番で解説をしていきますね。

  1. 音声読み上げAPIをインスタンス化する関数を用意する
  2. 音声認識APIをインスタンス化する関数を用意する
  3. 開始ボタン、停止ボタンで音声認識を開始する

1, 音声読み上げAPIをインスタンス化する関数を用意する

"SpeechSynthesisUtterrance"オブジェクトは、発話に関連するオブジェクトです。
各パラメータには、声質、音量、速度、音程を指定する事が出来ます。

このオブジェクトを返す関数として、"readySpeak関数"を用意します。
同時に、発話させる命令をまとめた関数"startSpeak関数"も用意しておきます。

main.js(抜粋)
function readySpeak(callback){

	const utter = new SpeechSynthesisUtterance();
	const voices = window.speechSynthesis.getVoices();
	utter.voice  = voices[7]; // 7:Google 日本人 ja-JP
	utter.volume = 1.0; // 音量 min 0 ~ max 1
	utter.rate   = 0.5; // 速度 min 0.1 ~ max 10
	utter.pitch  = 1.0; // 音程 min 0 ~ max 2
	utter.lang   = "ja-JP";
	utter.text   = "何か言いましたか!?";
	utter.onend = callback;// Callback
	return utter;
}

function startSpeak(utter, text){
	utter.text = text;
	speechSynthesis.speak(utter);
}

2, 音声認識APIをインスタンス化する関数を用意する

"webkitSpeechRecognition"オブジェクトを返す、"readyRecognition関数"を用意します。
このオブジェクトのイベント"onresult"では音声認識の結果を取得する事ができます。
"onerror"イベントでは、エラーハンドリングを行います。(エラー時に音声認識を再始動させます)

main.js(抜粋)
function readyRecognition(callback){

	const rec = new webkitSpeechRecognition();
	rec.continuous = true;
	rec.interimResults = false;
	rec.lang = "ja-JP";
	rec.onresult = (e)=>{
		for(let result of e.results){
			if(!result.isFinal) continue;
			rec.stop();
			callback(result[0].transcript);// Callback
		}
	}
	rec.onerror = (e)=>{
		if(e.error !== "no-speech") return;
		setTimeout(()=>{rec.start();}, 500);
	}
	return rec;
}

3, 開始ボタン、停止ボタンで音声認識を開始する

最後は簡単です。
HTMLに用意しておいた2つのボタンのクリックイベントを実装します。

main.js(抜粋)
document.getElementById("btnStart").onclick = ()=>{
	rec.start();// 音声認識開始
}

document.getElementById("btnStop").onclick = ()=>{
	rec.stop();// 音声認識停止
}

そして、認識結果である文字列を表示する"addText関数"を実装しています。

main.js(抜粋)
function addText(str){
	const elem = document.createElement("li");
	elem.innerHTML = str;
	document.getElementById("txtResult").appendChild(elem);
}

全体のコード

最後に、全体のコードを載せておきます。

main.js
window.onload = ()=>{

	const utter = readySpeak((e)=>{
		console.log("Time:" + e.elapsedTime);
		setTimeout(()=>{rec.start();}, 500);// 音声読み上げが終了したら音声認識を起動する
	});

	const rec = readyRecognition((text)=>{
		startSpeak(utter, text);// 音声認識が完了したら、音声読み上げを実行する
		addText(text);// 認識結果をHTMLに表示する
	});

	document.getElementById("btnStart").onclick = ()=>{
		rec.start();// 音声認識開始
	}

	document.getElementById("btnStop").onclick = ()=>{
		rec.stop();// 音声認識停止
	}
}

function readyRecognition(callback){

	const rec = new webkitSpeechRecognition();
	rec.continuous = true;
	rec.interimResults = false;
	rec.lang = "ja-JP";
	rec.onresult = (e)=>{
		for(let result of e.results){
			if(!result.isFinal) continue;
			rec.stop();
			callback(result[0].transcript);// Callback
		}
	}
	rec.onerror = (e)=>{
		if(e.error !== "no-speech") return;
		setTimeout(()=>{rec.start();}, 500);
	}
	return rec;
}

function readySpeak(callback){

	const utter = new SpeechSynthesisUtterance();
	const voices = window.speechSynthesis.getVoices();
	utter.voice  = voices[7]; // 7:Google 日本人 ja-JP
	utter.volume = 1.0; // 音量 min 0 ~ max 1
	utter.rate   = 0.5; // 速度 min 0.1 ~ max 10
	utter.pitch  = 1.0; // 音程 min 0 ~ max 2
	utter.lang   = "ja-JP";
	utter.text   = "何か言いましたか!?";
	utter.onend = callback;// Callback
	return utter;
}

function startSpeak(utter, text){
	utter.text = text;
	speechSynthesis.speak(utter);
}

function addText(str){
	const elem = document.createElement("li");
	elem.innerHTML = str;
	document.getElementById("txtResult").appendChild(elem);
}

なんと、これだけでオウム返しシステムが出来てしまいます。(やりました!!)

最後に

今回は、喋った内容をそのまま返すオウム返しシステムを作ってみました。
捉えた文字の特定の言葉にだけ反応させたりすると、面白い物が作れそうな気がしてきます。
ここまで読んでいただき有難うございました。

Discussion