LocalConnectionを使ったWindowsアプリケーションとFlashの連携
今回は、カヤックBM11ブログの babooo voiceのテクニカルノート からの転載です。
babooo voiceは音声認識とYahoo画像検索APIを組み合わせた眺める系画像検索サイトです。
その中で、
Windowsアプリケーションで動いている音声認識エンジンと、
ブラウザ上のFlashとの連携を、
FlashのLocalConnectionを利用して行っています。
ポイントを解説した記事をこちらでもご紹介させていただきます。
技術的なポイントは、Windows環境で、クロスブラウザで音声認識とWebアプリが連携する部分。
今までは、音声認識をWebで使おうと思ったら、IE限定で Microsoft SAPI(SpeechAPI) をjavascriptでActiveXObjectを使用して操作する、という方法がありました。
babooo voiceでは、その「IE限定」を無くす工夫をしています。 その詳細についてここでご紹介しましょう。
babooo voiceでは、音声認識エンジンとして、大語彙連続音声認識エンジン Juliusを使用しています。
Windowsのコマンドラインで動作して、マイク入力で動かしています。<.p>
さて、Juliusの認識した結果の文字列をWebアプリに渡すところです。
Windowsアプリと、Webアプリを連携させる方法はいくつかあり、最近になってまたいくつか増えましたね。
- WindowsアプリがサーバにPOSTして、Webアプリはサーバの変化をポーリング(またはComet)して反映させる
- ローカルにサーバを立ちあげてWebアプリがローカルのサーバをポーリングする
- Apolloとブラウザ内のFlashとのLocalConnection
- Widget
- まだまだありそうです…
それぞれ特徴ありますが、今回はインストールが簡単か、というところを重視して、Windowsアプリが直接ブラウザ内のFlashとLocalConnectionで通信する、ということをやっています。
LocalConnectionは、Win32ではミューテックスを使って排他しながらファイルマッピングを使ってプロセス間通信しています。
参考:OSFlash The LocalConnection explained
babooo voiceでは、Juliusの認識結果をWindowsアプリが受け取り、ファイルマッピングに書いてブラウザ内のFlashが読み取る、という流れです。
今回、音声認識結果をブラウザに渡すところを汎用化したので、あなたのWebアプリでも簡単に音声認識を使えます!
用意するのは、
- LCReceiver.swf
- ブラウザで音声認識結果を受け取るFlash
- 変更の必要無し、ページ内に置いておけばok
- javascriptコード
- LCReceiver.swfからexternalInterface.callで音声認識結果を受け取り、フォームを埋める等ページに反映させる
- voicerecon.ini
- Windowsアプリから送るLocalConnectionの設定ファイル
- http://babooo.kayac.com/html/run_voicerecon.zipの中にあるファイルをサービスのドメインに合わせて変更しますvoicerecon.exe と同じパスに置いてください
あとは、LCReceiver.swfとjavascriptコードのあるページをブラウザで開いて、run_voicerecon.exe を叩けばOK。
それぞれソースはこんな感じです。
//【LCReceiver.as】 package { import flash.display.*; import flash.net.*; import flash.events.*; import flash.external.ExternalInterface; public class LCReceiver extends Sprite{ private var lc:LocalConnection; public function LCReceiver(){ log("[swf][LCReceiver]"); lc = new LocalConnection(); lc.allowDomain("*"); lc.client = this; try{ lc.connect("LLC"); }catch(err:ArgumentError){ log("[swf][LCReceiver]Cant connect"); } } public function JSBridge(msg1:String):void{ log("[swf][LCReceiver][test]msg1: "+msg1); if (ExternalInterface.available) { ExternalInterface.call("LCReceived", msg1); } } } }
//【javascript】 var llc = new SWFObject("http://yourdomain.com/LCReceiver.swf", "externalInterfaceLCReceiver", "1", "1", "9", "#000000" ); llc.write("some_div_id"); function LCReceived(str){ console.log("[LCReceived] str: "+str); }
//【voicerecon.ini】 [target] domain=yourdomain.com connection=LLC method=JSBridge