連載
» 2017年05月10日 05時00分 公開

音声→テキスト変換のSpeech Recognition APIの使い方と、2017年4月におけるWatson、Google Cloud Speech APIとの違い認識系API活用入門(4)(2/3 ページ)

[岩本禎史,株式会社クロスキャット]

画面の作成

 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で実際にプログラムから呼び出すところを作成します。プログラムの流れとしては非常にシンプルで、以下のようになります。

  1. アクセスキーを使用してTokenを取得する
  2. 音声を録音し、音声ファイルを作成する
  3. Tokenを使用して、Speech Recognition APIに音声ファイルを渡し、テキスト(JSON形式)を取得する

 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.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。