バックエンドでAPIの実装をしていると、これインタラクティブに動かせたら楽しそうじゃないですかって思うことがよくあると思います。少なくとも最近あったわけですね。
それでAjaxなんて調べてみて、フロントエンドさんに聞いてみたりして、掲題の内容を書くに至りました。
とりあえず非同期通信おうむ返しする
まず入力した文字を瞬時に打ち返してくる仕組みをAjaxとPHPで実装したいと思います。
htmlファイルはこれだけでおk。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<head> <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script> <script> function clicker() { var text = document.forms.UpecmJ.DKfiCM.value; $(".HjUNYy").append("user: " + text + "<br>"); $.ajax({ url: './sample.php', dataType: 'json', data: {message: text}, success: function(data){ $(".HjUNYy").append("system: " + data.message + "<br>"); } }); } </script> </head> <body> <form name="" id="UpecmJ" action=""> <p>入力</p> <input name="" id="DKfiCM" type="text" value="" /> <input type="button" value="入力" onclick="clicker();" /> </form> <div class="HjUNYy"> <p>会話ログ</p> </div> </body> |
clicker関数は入力された文字をmessage変数に入れてsample.phpに飛ばしてmessage変数に入って戻って来た文字をdivタグ配下に追加していきます。
sample.phpはおうむ返しです。
1 2 3 4 5 6 7 8 9 10 11 12 |
$response = array( 'message' => $_GET['message'], ); header("Content-Type: application/json; charset=UTF-8"); header("X-Content-Type-Options: nosniff"); echo json_encode( $response, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ); exit; |
もうこの2つがあるだけでひたすら言い合いができます。
ここまで出来たら欲が出てくる
せっかくなら声で入力したいし声で返してくれたらいいなって思いました。ですので、Web Speech APIとVoiceText Web APIを使いたいと思います。
・Web Speech API: 音声の入力を文字に起こしてくれる便利なやつです。実行できる環境は限られますのでご注意ください。
・VoiceText Web API: 逆に文字を音声にしてくれる便利なやつです。使う前に規約とか読むといいですね。
htmlファイルは少し変わります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<head> <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script> <script> window.SpeechRecognition = window.SpeechRecognition || webkitSpeechRecognition; var recognition = new webkitSpeechRecognition(); recognition.lang = 'ja'; recognition.addEventListener('result', function(event) { var text = event.results.item(0).item(0).transcript; $(".HjUNYy").append("user: " + text + "<br>"); $.ajax({ url: './sample2.php', dataType: 'json', data: {message: text}, success: function(data){ var sleep = setInterval(function() { $(".HjUNYy").append("system: " + data.message + "<br>"); $(".GnEyLt").attr("src","data:audio/wav;base64," + data.voice); clearInterval(sleep); }, 1000); } }); }, false); function record() { recognition.start(); } </script> </head> <body> <p>音声入力</p> <input type="button" onClick="record()" value="音声入力" /> <audio class="GnEyLt" src="" autoplay></audio> <div class="HjUNYy"> <p>会話ログ</p> </div> </body> |
5行目からWeb Speech APIの記述でございます。addExentListener関数でresultを指定してますが、どうやら音声入力が終了してからの処理をここで書けるようです。
17行目は勝手なこだわりですが、返答がすぐに返ってくるのが何か気持ち悪かったので何秒か処理を遅らせています。
sample2.phpは音声バイナリ付きおうむ返しです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
$voice = base64_encode(voice_text($_GET['message'],'show')); $response = array( 'message' => $_GET['message'], 'voice' => $voice ); header("Content-Type: application/json; charset=UTF-8"); header("X-Content-Type-Options: nosniff"); echo json_encode( $response, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP ); exit; function voice_text($text, $voice){ $voice_url = 'https://api.voicetext.jp/v1/tts'; $voice_key = '*****'; $result = ""; if($text){ $arr = array( 'text' => htmlspecialchars($text), //喋らせたいテキスト 'speaker' => $voice, //話す人 //'emotion' => 'happiness', //感情 //'emotion_level' => 1, //感情レベル 'pitch' => 100, //声の高低 'speed' => 100, //話す速度 'valume' => 100 //音量 ); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $voice_url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_USERPWD, $voice_key . ":"); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($arr)); $result = curl_exec($ch); curl_close($ch); } return $result; } |
15行目からVoiceText Web APIを実行する関数です。17行目のAPIキーは自分で取得する必要がありますのでご注意ください。
ちなみに1行目でbase64_encodeにかけていますが、HTMLソース側の19行目で受け取って型の認識しています。
こちらを参考にさせていただきました〜
準備は整ったので
あとは好きにPHP部分を変えるだけですね!雑談対話系のサービスにつないでみるもいいし、天気を聞いたら天気を返してくれるようにしてもいいかもしれませんね。ブラウザベースなのでやることは限られそうですけれども。
何かつなぎ込めたらまた書きますので(゜-゜)