酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Windows PhoneでMicrosoft Translator APIを使用して翻訳をおこなう/テキストを読ませる

マイクロソフト社が、Microsoft Translatorと呼ばれる翻訳サービスを提供しているのをご存知でしょうか?

f:id:ch3cooh393:20150415144657p:plain

このMicrosoft Translatorは、翻訳機能や、入力したテキストを異なる言語にて読ませる事が出来ます。異なる言語グループ同士の人々が言葉や音声を使ってコミュニケーションを取るのをサポートしてくれます。

例えば、Twitterクライアントに取り入れると面白そうです。Twitterは世界中で使われているウェブサービスですので、日本語よりも圧倒的に外国語の方が多いです。異なる言語の方のツイートを自分の母国語に翻訳した上でタイムラインに表示出来れば、言語を意識することなくコミュニケーションが図るクライアントが開発出来そうです。

なお、Microsoft Translator APIは現在バージョン2ですが、新しいバージョンがリリースされる時には新旧2つのバージョンが90日間ホスティングされます。ですのでアプリケーションやウェブサービスでTranslator APIを使用している場合、90日の間で移行を完了させる必要があります。

新しいバージョンの公開情報や、旧バージョンのAPIのサポート打ち切りのスケジュールなどは、以下のフォーラムにて発表されます。一度目を通しておくと有益な情報が得られるかもしれません。

さて、このTranslator APIは、AJAX ServiceHTTP ServiceSOAP Serviceの3種類のサービスで提供されています。Windows Phone 7アプリケーション開発でもっとも相性が良いと思われるのは、Visual Studio 2010のサービス参照機能が使用出来るSOAP Serviceでしょう。

サービス参照に以下のURLを追加すると、コード側からの呼び出しが可能になります。

SOAP ServiceをVisual Studio 2010にてサービス参照を行い、コード上から呼び出しを行えるようにするまでの準備については、SOAP Serviceをサービス参照してコード上で使用するにて詳しく記載しております。

翻訳をおこなう

デザイナにて翻訳前の文章を入力するTextBoxと翻訳後の文章を表示するTextBlockを用意します。翻訳処理を開始するトリガーとなるButtonも忘れずに配置しておきましょう。それぞれ名前は、textBefore、textAfter、btnTranslateとします。

f:id:ch3cooh393:20150415144815p:plain

ボタンのイベントハンドラに以下のコードを書いておきます。サービス参照の追加で作成したクライアントクラスのインスタンスを生成し、翻訳完了イベントのTranslateCompletedのハンドラにラムダ式で翻訳後の文章をTextBlockに設定しています。最後にTranslateメソッドを非同期にて実行するようにしています。

下記のサンプルコードにあるTranslateAsyncメソッドの第一引数の"{Bing AppID}"は、Bing Developer Centerにて登録したAppIDを入力しておく必要があります。

private void btnTranslate_Click(object sender, RoutedEventArgs e)
{
    Translator.LanguageServiceClient client = new Translator.LanguageServiceClient();
    // 翻訳が完了したらTextBlockに翻訳後の文章を設定する
    client.TranslateCompleted += (sx, ex) => { textAfter.Text = ex.Result; };
    // TextBoxに入力した文章を英語から日本語への翻訳を行う
    client.TranslateAsync("{Bing AppID}", textBefore.Text, "en", "ja", null, null); 
}

準備は整いました。「Hello world」を英語から日本語に翻訳してみましょう。TextBoxに「Hello world」と入力して、ボタンをタップします。

f:id:ch3cooh393:20150415144837p:plain

インターネットに接続されている環境なら、すぐに日本語訳された文章が返ってきます。TextBlockに「ハロー ワールド」と表示されているのが判るでしょうか。

f:id:ch3cooh393:20150415144854p:plain

テキストを読みあげさせる

前回は入力した文章を翻訳しTextBlockへ表示しました。今回は翻訳後の文章を音声で読みあげさせましょう。

テキストの読みあげには、Translator APIのSpeakメソッドを使用します。このSpeakメソッドは、テキストと言語情報をサーバーへリクエストします。サーバーサイドで音声ファイルを作成するので、アプリケーションでは音声ファイルをダウンロードし、MediaElementを使って再生を行います。

読み上げ開始のトリガーとなるButtonをデザイナを使って配置します。以前使ったTranslateボタンの隣に配置しましょう。名前はbtnSpeakとします。

f:id:ch3cooh393:20150415144914p:plain

ボタンのイベントハンドラに以下のコードを書きます。サービス参照の追加で作成したクライアントクラスのインスタンスを生成し、音声ファイル作成完了イベントのSpeakCompletedのハンドラにラムダ式でダウンロード処理を設定しています。最後にSpeakメソッドを非同期にて実行します。

少し複雑ですのでSpeakCompletedのラムダ式の中についても説明します。Translator APIのSpeakメソッドのレスポンスには、音声ファイルのURLが含まれています。得られたURLのデータをダウンロードする為にWebClientクラスのOpenReadAsyncメソッドを使っています。

private void btnSpeak_Click(object sender, RoutedEventArgs e)
{
    // 翻訳後のテキストがTextBlockにあるか判定
    if (string.IsNullOrEmpty(textAfter.Text))
    {
        MessageBox.Show("翻訳を行ってください.");
        return;
    }

    // MediaElementの初期化
    mediaElement.Source = null;

    Translator.LanguageServiceClient client = new Translator.LanguageServiceClient();
    // waveファイルの作成完了後、サーバーからwaveファイルをダウンロードする
    client.SpeakCompleted += (sx, ex) => {
        if (ex.Error != null) return;

        WebClient wc = new WebClient();
        wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
        wc.OpenReadAsync(new Uri(ex.Result, UriKind.Absolute));
    };
    // TextBlockに入力した文章の読ませたwaveファイルの作成を行う
    client.SpeakAsync("{Bing AppID}", textBefore.Text, "ja", null, null); 
}

上記のサンプルコードにあるSpeakAsyncメソッドの第一引数の"{Bing AppID}"は、Bing Developer Centerにて登録したAppIDを入力しておく必要があります。このままでは実行出来ませんので気をつけてください。

デザイナに戻り、音声の再生に利用するMediaElementを配置します。動画と違い見えないコントロールですのでどこに配置しても問題ありません。ここではTranslateボタンの右下に配置しました。名前をmediaElementとしています。

f:id:ch3cooh393:20150415144949p:plain

再生を行うMediaElementの準備は整いました。ただ、この時点では再生するデータは設定されていません。

WebClientのOpenReadCompletedイベントのハンドラ内で読み込んだストリームを分離ストレージのファイルに書き出し、ダウンロードを完了させた後、分離ストレージ側のストリームをMediaElementに設定します。

分離ストレージの使い方については、分離ストレージ(Isolated Storage)を使ってデータの保存と取得を行うをご覧ください。

void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    if (e.Error != null) return;

    string fileName = "translate_test.wav";
    var store = IsolatedStorageFile.GetUserStoreForApplication();

    // 以前に作成したファイルが残っている場合は削除する
    if (store.FileExists(fileName))
    {
        store.DeleteFile(fileName);
    }

    // 読み込んだストリームを分離ストレージのファイルに書き出す
    using (var strm = store.CreateFile(fileName))
    {
        var bytes = new byte[256*1024];
        while (true)
        {
            int read = e.Result.Read(bytes, 0, bytes.Length);
            if (read <= 0) break;
            strm.Write(bytes, 0, read);
        }

        // 指定されたストリームを使ってSourceプロパティに設定します
        mediaElement.SetSource(strm);
        // 設定されたSourceの再生の開始
        mediaElement.Play();
    }
}

インターネットに接続されている環境なら、翻訳後のテキストに入力した「ハロー ワールド」が読みあげられたのが確認出来ましたでしょうか。無事、音声が再生されていれば英和翻訳アンドテキスト読みあげアプリは完成です。

f:id:ch3cooh393:20150415145012p:plain

音声ですのでスクリーンショットだけでは限界があるため、Youtubeに動画をアップロードしています。英語を入力した場合と日本語を入力した場合の音声の違いを確かめてください。

関連記事

blog.ch3cooh.jp