リクルートの進学ネットAPI と 字幕in株式会社様の文字音声変換API "TEXT2VOICE"を使って、以下のようなサンプルを制作してみました。
架空のニュースチャンネル「進学ネットニュース」。興味のある職業やジャンル、関連語句を画面下部の検索フォームに入力し、検索ボタンをクリックして下さい。著作権フリー素材な女性キャスターが、かなりバーチャルな声で、あなたの進路に有益な情報をアナウンスしてくれます。(ローディング画面がないので、ちょっと待ってやって下さい。たまに文字音声変換APIが落ちていることもあるようです。)
尚、上のサンプルでは、ニュースのイメージ映像の部分には Yahoo! の「画像検索Webサービス」を利用しています。
ここからは、上記サンプルで使用した「進学ネットAPI」と「文字音声変換API "TEXT2VOICE"」それぞれの利用法を、それぞれ別個に解説させていただきます。この2つのAPIは、「Mash up Award」の対象APIにもなっておりますので、興味をお持ち頂けましたらふるってご応募ください。
制作環境はFlash8、ActionScript2.0を使用しています。
1. リクルート進学ネットAPIを使う
このAPIは、リクルート進学ネットに掲載されている学校および各種学問・仕事・資格を様々な軸で検索できるAPIです。今回はその中の「仕事検索API」を使って、入力されたキーワードをもとに、それに関連する職種と、その職業に就くために役に立つ資格・学問を取得しています。
まずはリクルートWEBサービスのサイトから、事前にご自分の API キーを取得しておいてください。
仕事検索APIには、 ActionScript2.0 用のユーティリティーライブラリ「CASA framework」を使いました。こちらのページから、ZIPファイルをダウンロードします。Flashで、外部ライブラリを使う方法はいくつかありますが、今回は、解凍してできたファイルの中にある「org」フォルダを、作業対象の fla ファイルと同じフォルダに置いておくのが、一番手軽でしょう。
それでは fla ファイルの編集をしていきます。
ドキュメントのルートに、インスタンス名「input」というテキスト入力フォームと、インスタンス名「btn」という、ムービークリップを置きます。
次に、ルートのフレームスクリプトに次のようなコードを記述します。
01| /* 進学ネットAPI(http://webservice.recruit.co.jp/shingaku/)を利用するサンプル */
02| System.security.loadPolicyFile("http://webservice.recruit.co.jp/shingaku/crossdomain.xml");
03|
04| import org.casaframework.load.data.xml.XmlLoad;
05| import org.casaframework.util.XmlUtil;
06|
07| var RWSApiKey:String = "ご自分のAPIキー(入力必須)"; //ご自分のAPIキー
08| var keyword:String;
09| var myXmlLoad:XmlLoad;
10| var workInfo:Array;
11|
12| //ボタンが押されたら、テキストボックスの内容でキーワード検索する
13| btn.onPress = function(){
14| keyword = input.text;
15| loadXml(keyword);
16| }
17|
18| //XMLのロード作業
19| function loadXml(kw:String):Void{
20| //検索キーワードをUTF-8でURLエンコードする
21| kw = escape(kw);
22| myXmlLoad = new XmlLoad("http://webservice.recruit.co.jp/shingaku/work/v1/?key="+RWSApiKey+"&keyword="+kw);
23| this.myXmlLoad.addEventObserver(this, XmlLoad.EVENT_LOAD_COMPLETE, "onDataLoad");
24| this.myXmlLoad.start();
25| }
26|
27| //XMLのパース作業
28| function onDataLoad(sender:XmlLoad):Void {
29| //trace(this.myXmlLoad.getXml());
30| workInfo = XmlUtil.xmlToObject(this.myXmlLoad.getXml())['results'][0]['work'];
31| init();
32| }
33|
34| //XMLのパースが終わったら以下の関数を実行
35| function init():Void{
36| //試しに work ノードの最初の仕事名を出力してみる
37| trace(workInfo[0].name[0].nodeValue);
38| }
それでは上から解説していきます。
line 2: FlashからリクルートWEBサービスを使う際は、loadPolicyFile メソッドで、crossdomain.xml ファイルの場所を指定しておく必要があります。この1行を書いておかないと、ローカルでの開発では問題ないのですが、完成ファイルをサーバー上にアップした際に API にアクセスできなくなります。場所指定は各 API ごとに異なりますので、詳しくは各 API ドキュメントの最下部の記述(リンク先は 進学ネットAPI 用の記述例)を参照ください。
line 4-5: このサンプルではXMLをロード、パース(解析)するのに、CASA framework(ドキュメント) の XmlLoad クラスと XmlUtil クラスを利用します。import 文で両クラスを読み込んでおきましょう。
line 7-10: 7行目に、ご自分で取得されたAPIキーを記述しておいて下さい(「"〜"」と、ダブルクオーテーョンで囲んでおきましょう。)
line 13-16: ステージ上の btn をクリックしたタイミングで、テキスト入力フォームの内容をキーワードとして取得し、そのキーワードを引数として、loadXML 関数を実行します。
line 19-25: kwとして受け取ったキーワードをもとに、進学APIサービスに問い合わせをします。問い合わせは URL 形式で行います(こんな感じですね)。22行目で、7行目で指定しておいたご自分の API キーを設定しています。同様に、「&keyword=キーワード」の形で、検索キーワードを指定すれば良いのですが、日本語のまま値を渡すのではなく、サーバーに理解できるように文字列を変換させてやる必要があります。それが21行目の kw = escape(kw); の部分です。リクルートの多くの API と同様、この進学ネットAPIでも、日本語文字列を渡すときは「UTF-8、URLエンコーディング」で、文字列変換しておく必要があります。幸い Flash8 は標準で UTF-8 ベースですので、escape 関数を使うことで、簡単に UTF-8 の URL エンコードをかけてやることができるのです。あとはその変換後の文字列を keyword として渡しているわけです。
23行目では、XML のロードが終わったタイミングで、onDataLoad 関数を実行しますよという指定。
24行目で、実際にXMLのロードを開始しています。ここまでが、CASA の XMLLoad クラスの役割です。
line 28: XML のロードが終わった時に実行される onDataLoad 関数の設定をしていきます。
line 29: このコメントアウトを外すと、ロードした XML を確認できます。APIリファレンスのレスポンスフィールドと対応しているのが確認できますね。
line 30: ここで、XML をパース(解析)して、Flash で扱いやすいように変換する作業をしています。今回必要なのは、各仕事の情報なので、APIリファレンスのレスポンスフィールドとにらめっこしながら、work ノードが必要だということが分かりました。CASA framework の XmlUtil クラスの XmlToObject メソッドを使って、ダウンロードした XML ファイルの、各 work ノード以下の内容を、配列(オブジェクト)として、workInfo という配列に格納しています。
line 31: パースが終わったら、init 関数を実行します。
line 35-38: この部分に、コンテンツにあわせて実現させたい命令をコーディングしていきましょう。ここでは試しに、work ノードの要素番号 0 (1個目)の name ノード([0]が必要なので注意)の中身(nodeValue)を出力しています。
試しにパブリッシュしてみて、入力欄に「建築」と入力して検索ボタンを押すと「CGデザイナー」と出力されるかと思います。
この状態までのサンプルを、ソースコード利用規約に同意の上、ダウンロード。(zip圧縮:FlashMX2004形式)
注)別途 CASA framework を入手して下さい。
8/1にオープンしました「リクルートWEBサービス」の各種APIを Flash/ActionScript2.0 から利用する際は、ほぼ同様のアプローチが有効ですので、ご参考にしてみてください。
2. 文字音声変換API "TEXT2VOICE" を使う
続きまして、別に新規 FLA ファイルを作って、字幕in株式会社様ご提供の、文字列を音声に変換してくれる「文字音声変換API」の使い方を紹介していきます。
試しにブラウザ上で実験してみましょう。このAPIは、リクエストURL(APIを呼び出すためのURL)を
http://api.satoru.net/text2voice/?text=ここに音声に変換させたい文字列
のように、「text=」以降に変換したい文字列を付けてやると、ブラウザウィンドウに
http://api.satoru.net/text2voice/mp3/Q/r/j/d/QrjdGH7oLaR.mp3
という文字列が表示されるかと思います。その際、アドレスバーの日本語部分が、「%E3%81%93%E3〜」のように、自動的に変換されていることに注意しておきましょう。これがURLエンコードってやつですね。
さて、このmp3アドレスにアクセスすると、上で指定した文字列を読み上げてくれるmp3ファイルを確認&視聴できるかと思います。この一連のフローを Flash で再現すればいいわけですね。
先ほど使った素材と同じものでも良いですが、ステージ上にインスタンス名「input」というテキスト入力フォームと、インスタンス名「btn」という、ムービークリップを置きます。長文にも対応できるように、テキスト入力フォームは複数行にしてみました。そして、ドキュメントルートのフレームスクリプトとして、以下のコードを記述します。
01| /* 文字音声変換API(http://api.satoru.net/#voice)を利用するサンプル */
02|
03| import org.casaframework.load.data.xml.XmlLoad;
04|
05| var keyword:String
06| var myXmlLoad:XmlLoad;
07|
08| //ボタンが押されたら、テキストボックスの内容を sendRequest 関数に渡す
09| btn.onPress = function(){
10| keyword = input.text;
11| sendRequest(keyword);
12| }
13|
14| //受け取ったキーワードを、音声変換APIのクエリとして渡し、そのURLにアクセスする関数
15| function sendRequest(kw:String):Void{
16| kw = escape(kw);
17| myXmlLoad = new XmlLoad("http://api.satoru.net/text2voice/?text="+kw);
18| this.myXmlLoad.addEventObserver(this, XmlLoad.EVENT_LOAD_COMPLETE, "onAnnounceReady");
19| this.myXmlLoad.start();
20| }
21|
22| //APIからmp3の場所URLが返ってくるので、そのURLからmp3をロードして再生する。
23| function onAnnounceReady(sender:XmlLoad):Void {
24| var mp3Url:String = this.myXmlLoad.getXml();
25| //trace(typeof(mp3Url));
26| trace(mp3Url);
27| mySound = new Sound(this);
28| mySound.onLoad = function(bool:Boolean){
29| if(bool){
30| mySound.start();
31| }else{
32| trace("mp3音声のロード失敗")
33| }
34| }
35| mySound.loadSound(mp3Url,false);
36| }
パブリッシュして、入力フォームに文字を入力し、ボタンを押すと、きちんと音声読み上げしてくれるかと思います。それでは各行ごとに、コードの役割を見ていきましょう。
line 3: ここでも CASA framework の XmlLoad を使います。あれ、xml をロードするんだっけ?と思った方、そうですよね。僕も思ったのですが、使ってみたらきちんと動作しましたので、今回は気にせず使ってみましょう。
line 5-6: どの変数をローカル変数とするかの判断は、その後の実装に応じて変わっていきます。今回はこの2変数を外に置いておきます。
line 9-12: 入力フォームに文字を入力し、ボタンを押したら sendRequest 関数を実行する。その際、引数として、入力された文字列を渡しています。
line 15-20: 例1の LoadXml 関数と同様、CASA の XmlLoad クラスを利用して、APIリクエスト用のURLを生成し、アクセスしています。
line 16: 日本語のような2バイト文字をUTF-8形式でURLエンコード。
line 17: 変換した値をクエリ文字列として、APIリクエスト。この音声変換APIでは、リクルートWEBサービスで必要だった、使用する個人ごとのAPIキーは不要なので、その分の手間は省けます。
line 18: ロードができたら(mp3のURLが取得できたら)、onAnnounceReady 関数を実行しますよ、と定義しておいて、19行目でロード開始。
line 24: サーバーから返ってきた値が、myXmlLoad に格納されています。これを getXmlして、その中身(mp3のURL)を、mp3Url に格納。myXmlLoadに格納されているのは、xmlでもなくhtmlでもなく、mp3ファイルのアドレスというただの文字列のみなのだけど、getXml することでどうやら上手く動作するんです。
line 25: ここで疑問。24行目で mp3Url はString(文字列)だとしていしているのに、型を調べてみると Object になっています。そういうものなの?
line 26: trace すると、きちんとmp3ファイルの場所を取得できているので、まぁいいか。
line 27-35: あとはおなじみの音声再生のコード。新規サウンドインスタンスを生成し、ステージに関連付けておき、ロードが成功 or 失敗した時の処理、35行目で、mp3Url(mp3のファイルのアドレス)から mp3 ファイルをロード、2番目の引数は、true でストリーミングサウンド、今回は false にしてイベントサウンドにしています。
以上です。テキストを渡したらそれを読んでくれる。これはかなり楽しいAPIですね。RSSリーダーどころかRSSスピーカーもできちゃいますし。AS3で作って女声変換(できるかな?)したら、ミニドラマも作れそう。個人的には、TVCMや天気予報も含めた番組を、まるごと一本仕立ててみたいです。
サンプルで作った「進学ネットニュース」はこの2つを組み合わせて作りました。進学ネットAPIを使って、入力されたキーワードから、該当した仕事に関する情報を取得し、その順番を並べ替えたり、間をそれっぽく補って文章の形に整形して、それをまとめて文字音声変換APIに渡しているわけです。アイデアの起点は「APIってある程度フォーマット化されたデータなんだから、間をいい感じにつないだら、汎用的な文脈がつくれるんじゃね?」という感じです。最終の形さえ見えれば、半日もあれば作れると思います。
SNN 自体のソースも公開しようと思いますが、例外処理(該当するお仕事データがなかった場合にどう喋らせようか)とか、条件分岐(アクセス時間が朝なら「おはようございます」、夜なら「こんばんは」)などといった、API処理とは無関係な冗長なコードが散乱しているので、もうちょっと手を加えて、有益そうなコードになったらご紹介させていただこうと思います。






