だれでも勝手に弊社社長の部屋を音声で遠隔操作できるハックについての技術解説



今回、エープリルフールで作った、弊社社長の部屋を誰でも勝手に音声で操作できるようにするハックについて解説します。
http://rti-giken.jp/


chromeのブラウザからアクセスすると、ブラウザから誰でも音声で弊社社長の部屋の照明や扇風機をコントロールすることができます。(2013/4/1いっぱいまで有効です。)



簡単に説明すると、ブラウザの x-webkit-speech で javascript音声認識をやって、それをPHPを経由して、rti技研のC++で作った鯖に情報を書き込みます。
フューチャーホームコントローラーで、その情報を取得することで、ホームコントロールを行なっています。


フューチャーホームコントローラーは、C++で作った鯖に対して ロングポーリングしています。
なので、情報は高速に受け継がれます。(wimax回線でつないでいるUSTの遅延が多少あります。)

フューチャーホームコントローラーって何よ?


フューチャーホームコントローラーは、声でしゃべるだけで様々な家電を操作できる未来的ガジェットです。(写真の手前にあるのは名刺のです。)

今回は、ブラウザ経由で家電を操作しましたが、実際には、ガジェットそのもので家電を操作します。
ボタンを押すとか必要なく、何もせずに話しかけるだけで、さまざまな家電を操作できるようになります。

また、V8エンジンを搭載しているので、javascriptとかで自由に拡張することができます。
家を自在にハックするデバイスです。

フューチャーホームコントローラーと毎回書くと疲れるので、FHCと略したりします。

ブラウザで使える音声認識

ブラウザで使える音声認識として、chromeだと2つの方法があります。
x-webkit-speechと HTML5 の Web Speech APIがあります。

ともに、メリットとデメリットがあります。

x-webkit-speech

x-webkit-speechのメリットは、手軽であることです。 inputタグに 1属性追加するだけで使うことができます。
UIの表示などはすべて自動的にやってもらえます。
逆にデメリットとしては、カスタムが出来ないところです。
必ず、マイクアイコンをクリックしてから話しかける動作しか出来ませんし、
マイクアイコンの差し替えができません。(超強引にやればできるのかも・・・?)
javascriptで細かく操作することができません。

<input type="text" x-webkit-speech />

HTML5 の Web Speech APIのメリットは、カスタマイズ性が高いというところです。
javascriptで細かく操作することができます。
また、認識したワードの正確さパラメータを取得したりなどと、いろいろ高度なことができます。
あと、連続して音声認識を行うことができます。
毎回、音声認識するたびにボタンを押すのではなく、一度音声認識モードに入ると、連続して音声認識を行うことができます。
逆にデメリットとしては、すべての面倒を自分で見なければいけない点と、
まだ実装されてから日が浅いので、情報が少ないところです。恐る恐る使う感じでしょうか。
また、プライバシーとセキュリテイ対策のためか、利用するたびに「マイクへのアクセス許可」を与える必要があります。

「マイクへのアクセス許可」がありますので、HTML5 の Web Speech APIも、x-webkit-speech同様、何かしらのボタンを押して開始するというところは同じですね。

var recognition = new webkitSpeechRecognition();

今回は、 x-webkit-speech

FHCの仕様としては、ハンズフリー音声認識です。
開始ボタンとかを押さなくて、好きなときにしゃべればそれを認識する形式です。

そのため、仕様としては、HTML5 の Web Speech APIが近いのですが、
Web Speech APIを連続して使っていると、挙動が不思議なことがあったので、
今回は、x-webkit-speechで実装しています。


x-webkit-speechの問題点としてカスタマイズ性の問題があります。
x-webkit-speechは常にinput textの右端にレンダリングされます。
いまのところ、これを変更することはできません。

そこで、今回は、超小さいinput textを作りました。
それをcss3 tranform scaleで数倍に拡大することで、
マイクのアイコンだけをボタンのように取り出しています。

.navigationbar_xspeech input {
	vertical-align:middle;
	-webkit-transform: scale(3.6,2.6); /* 超拡大する */
	-moz-transform: scale(3.6,2.6);
	-ms-transform: scale(3.6,2.6);
	transform: scale(3.6,2.6);
	width: 16px;	/* 幅が小さい入力フォーム  */
}





後は単純


これで、ボタンを押して喋ってもらえば、認識結果が文字列として取得出来ます。
その結果を indexOfとかで適当にスキャンして、マッチする命令に当て込みます。
あとは、マッチした命令を鯖になげます。
今回は、PHPでproxyを作っています。
鯖とのつなぎ込みは、今はハックの部分になるので、あまり公開したくないところです。

FHC鯖は、C++で書いています。
FHC端末は、FHC鯖に対してロングポーリングを行なっています。
C++httpdから書いているので、このあたりはやりたい放題です。

鯖のステータスが変更されると、直ちにFHC端末に反映されます。
これで、FHC端末本体が、赤外線信号を送ることで、うちの電気がついたり消えたりします。

javascript -> PHP -> C++ -> C++ -> マイコン(C言語)が強調して動くことで実現できているわけですね。
胸熱ですね。


トマトが降ったりするのは?

トマトが降ったりすることもありますが、ただの jquery box2d で落としているだけです。
落としながら、画面をスクロールさせたりとかの、画として面白いコンテンツにするために工夫はありましたが、技術的というよりも、エンターテイメントとしての微調整です。


また、音声の読み上げは、opnejtalkで読み上げさせた合成音声をmp3に変換したものを事前に用意しておいて、それを HTML5 の Audioで鳴らしています。
Audioでの音楽再生はファイルロードの遅延があるので、事前に全ての音声をキャッシュさせています。ココらへんは地味にめんどいところです。

var g_mp3cache = {};
function play(filename,isplay)
{
	if (! g_mp3cache[filename] )
	{
		g_mp3cache[filename] = new Audio(filename);
	}
	if (isplay)
	{
		g_mp3cache[filename].play();
	}
}