MainWindow.xamlのソースについては以下のようになっています(※画面部分のソースコードの解説は本連載の趣旨から外れるので割愛します)。
<Window x:Class="SpeechRecognitionAPI.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SpeechRecognitionAPI" mc:Ignorable="d" Title="Speech Recognition API" Height="350" Width="525"> <Grid> <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"> <Button Name="btnRec" Width="200" Height="50" Click="btnRec_Click"> <StackPanel Orientation="Horizontal"> <Label Name="lblBtnRec" Width="35" Height="30" Content="REC" Background="Red" Foreground="White" Visibility="Collapsed"/> <TextBlock Name="tblkBtnRec" Margin="20,0,0,0" VerticalAlignment="Center"/> </StackPanel> </Button> <ComboBox Name="cmbLocale" Width="200" Margin="0,20,0,0"> <ComboBoxItem Content="ja-JP" IsSelected="True" /> <ComboBoxItem Content="en-US" /> </ComboBox> <TextBox Name="tboxResult" Width="450" Height="150" TextWrapping="Wrap" Margin="0,20,0,0" /> </StackPanel> </Grid> </Window>
MainWindow.xaml.csで実際にプログラムから呼び出すところを作成します。プログラムの流れとしては非常にシンプルで、以下のようになります。
Text To Speech APIと同様、サービスが対応している言語の一覧を取得するAPIがないようなので、今回はプログラム内にリストを持つことにします(プログラムを簡便にするために、今回は英語と日本語のみとします)。
まず、今回はSpeech Recognition APIから返ってくるデータがJSON形式なので、このJSON形式で返ってくるデータを受け取るためのクラスを作成します。
メニューバーの「プロジェクト」から「クラスの追加」をクリックします。
追加するのは通常のクラスです。名前を「SpeechRecognitionResult.cs」として「追加」ボタンをクリックします。
クラスが追加されたら、以下の内容をコピーしてそのクラスにペーストしてください。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // 追加 using System.Runtime.Serialization; namespace SpeechRecognitionAPI { [DataContract] class SpeechRecognitionResult { [DataMember] public string version { get; set; } [DataMember] public Header header { get; set; } [DataMember] public Result[] results { get; set; } [DataContract] public class Header { [DataMember] public string status { get; set; } [DataMember] public string scenario { get; set; } [DataMember] public string name { get; set; } [DataMember] public string lexical { get; set; } [DataMember] public Properties properties { get; set; } } [DataContract] public class Properties { [DataMember] public string requestid { get; set; } [DataMember] public string HIGHCONF { get; set; } } [DataContract] public class Result { [DataMember] public string scenario { get; set; } [DataMember] public string name { get; set; } [DataMember] public string lexical { get; set; } [DataMember] public string confidence { get; set; } [DataMember] public Properties2 properties { get; set; } } [DataContract] public class Properties2 { [DataMember] public string HIGHCONF { get; set; } } } }
続いてアクセスキーを使用してTokenを取得する処理ですが、Tokenの取得については、Translator API、Text To Speech APIのときとまったく同じです。Tokenは10分間有効なので、前回取得時から10以上経過していたら再取得するよう、取得した時間を変数に取っておきます。
// ---------------------------------------------- // Tokenを取得する処理 // ---------------------------------------------- string GetAccessToken() { try { //取得したBing Speech API の Key string subscriptionKey = "xxxxxxxxxxxxxxxxxxxxxxxx"; WebRequest request = WebRequest.Create("https://api.cognitive.microsoft.com/sts/v1.0/issueToken"); //リクエスト設定 request.Method = "POST"; // メソッドはPOST request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey); request.ContentLength = 0; // リクエストを投げる WebResponse response = request.GetResponse(); Stream responseStream = response.GetResponseStream(); // レスポンスを受け取る StreamReader streamReader = new StreamReader(responseStream); // Tokenを取得した時間を取得 tokenRefreshedTime = DateTime.Now; // レスポンス(Token)を返す return streamReader.ReadToEnd(); } catch (WebException webException) { Stream responseStream = webException.Response.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream); tblkMessage.Text = streamReader.ReadToEnd(); return null; } catch (Exception exception) { tblkMessage.Text = exception.Message; return null; } }
続いて、音声ファイルを渡してテキストを取得する処理です。APIのリクエストメソッドはPOSTになります。Speech Recognition APIでは、リクエストの必須パラメーターとして以下の値を含めるように記載されています。
Name | Format | 特記事項、例、使い方 |
---|---|---|
Version | Digits and "." | 推奨が3.0なので、「version=3.0」と記載すればOK |
requestid | GUID | リクエストごとにグローバルでユニークなIDを振れ、とのことなので、プログラム内でリクエストのたびにIDを取得する。例としては「requestid=b2c95ede-97eb-4c88-81e4-80f32d6aee54」という形式になっている |
appID | GUID | 固定値とのこと。「appID = D4D52672-91D7-4C74-8AD8-42B1D98141A5」と記載すればOK |
format | UTF-8 | 推奨形式はJSON(それ以外にどのような形式をサポートしているのかの記述がない)。「format=json」と記載すればOK |
locale | UTF-8(IETF Language Tag) | 「Bing Speech Recognition API」のページの「Supported Locales」にある値(ja-JP、en-USなど)を指定すればOK |
device.os | UTF-8 | このリクエストを投げるアプリケーションが載っているOSを指定するパラメーター。こうでなければならないというのはないが、「Windows OS」「Windows Phone OS」「XBOX」「Android」「iPhone OS」といった形で指定すればOK |
scenarios | UTF-8 | 音声認識を実行するための文脈、背景、場面のパラメーター。サポートする値は「ulm」か「websearch」。いろいろ調べてはみたが、このパラメーターをそれぞれ変えることによる影響は不明 |
instanceid | GUID | デバイスごとにグローバルでユニークなIDを振れ、とのことなので、何か適当な値を固定値で持ってもいいし、都度新しいIDを取得しても問題ないようだ。例としては「instanceid=b2c95ede-97eb-4c88-81e4-80f32d6aee54」という形式になっている |
// ---------------------------------------------- // 音声データのテキスト変換結果を取得する処理 // ---------------------------------------------- string GetSpeechRecognitionResult(string pAccessToken, string pLocale, string pWavFile) { try { string url = " https://speech.platform.bing.com/recognize"; url += "?version=3.0"; url += "&requestid=" + Guid.NewGuid().ToString(); url += "&appid=D4D52672-91D7-4C74-8AD8-42B1D98141A5"; url += "&format=json"; url += "&locale=" + pLocale; url += "&device.os=Windows OS"; url += "&scenarios=ulm"; url += "&instanceid=" + Guid.NewGuid().ToString(); // リクエスト作成 HttpWebRequest request = WebRequest.CreateHttp(url); request.Method = "POST"; request.ContentType = "audio/wav; samplerate=16000"; request.Headers.Add("Authorization", "Bearer " + pAccessToken); // 音声ファイルの読み込み FileStream fs = new FileStream(pWavFile, FileMode.Open, FileAccess.Read); byte[] bs = new byte[fs.Length]; fs.Read(bs, 0, bs.Length); fs.Close(); Stream writer = request.GetRequestStream(); writer.Write(bs, 0, bs.Length); WebResponse webResponse = request.GetResponse(); Stream responseStream = webResponse.GetResponseStream(); DataContractJsonSerializer dcjs = new DataContractJsonSerializer(typeof(SpeechRecognitionResult)); SpeechRecognitionResult result = (SpeechRecognitionResult)dcjs.ReadObject(responseStream); if(result.header.status == "error") { return result.header.status; } return result.results[0].lexical; } catch (WebException webException) { Stream responseStream = webException.Response.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream); return streamReader.ReadToEnd(); } catch (Exception exception) { return exception.Message; } }
コンストラクタやボタンクリック時のイベントを含めると、最終的には「MainWindow.xaml.cs」は、こちらのようになります(※クリックしてダウンロードできます)。
ポイントとしては、録音にはmciSendStringを使用しています。また、以前は音声ファイルのサンプリングレートが16khzという制限があった記憶がありますが、2017年4月現在のドキュメントには特にサンプリングレートに関する制限は書かれていません。しかし、念のため今回のプログラムでは録音時にサンプリングレート16khzの音声ファイルを作成しています。
また、返ってくるJSONのデータのうち、音声データのテキスト化の結果が入っている値は「name」「lexical」です。基本的にnameを使えばいいと思います。
Copyright © ITmedia, Inc. All Rights Reserved.