MRが楽しい

MRやVRについて学習したことを書き残す

VisualStudioのビルドで「コード1で終了しました」エラーが発生する

本日はチュートリアルの実施枠のおまけです。
Academyに従って作成したプロジェクトをVisualStudioでビルドしたところ、一度目は以下のエラーが発生しました。
「コマンド""~~~~~""はコード1で終了しました。」
f:id:bluebirdofoz:20180811180618j:plain

本エラーはプロジェクトのフォルダパスが長すぎることが原因です。
フォルダパスを短くすることで解消できます。私の環境ではパスが75文字以上の時、エラーが発生しました。
f:id:bluebirdofoz:20180811180637j:plain

フォルダパスを修正し、再度ビルドを行うと、エラーが解消されます。
f:id:bluebirdofoz:20180811180717j:plain

チュートリアルのページにも、フォルダパスを長くし過ぎないように、という注意書きがあります。
docs.microsoft.com

公式チュートリアル「MR and Azure 301 10~11章」を試してみる

本日はチュートリアルの実施枠です。
Academyの「MR and Azure 301: Language translation」の実施内容をまとめます。
docs.microsoft.com
前回記事の続きです。
bluebirdofoz.hatenablog.com
今回は「Chapter 10 ~ Chapter 11(完成)」です。

Chapter 10:Build the UWP solution and sideload on local machine

Unityセクションで必要なものは全て完成したので、ビルドを行います。
1.メニューから File -> Build Settings を選択します。
f:id:bluebirdofoz:20180810093115j:plain

2.「Unity C# Projects」をチェックし、「Build」を実行します。
f:id:bluebirdofoz:20180810093124j:plain

Chapter 11:Deploy your application

アプリケーションを HoloLens に展開します。
1-3.ビルドで出力された sln ファイルを開きます。
構成を「Release」「x86」「リモートコンピュータ(HoloLensのIPアドレス)」に変更します。
f:id:bluebirdofoz:20180810093134j:plain

4.メニューから デバッグ -> デバッグなしで実行 でアプリを HoloLens にインストールして実行します。
f:id:bluebirdofoz:20180810093145j:plain

5.HoloLens 上で動作確認を行います。
インストールに伴い、パネルサイズの変更と、日本語 -> 英語の変換に設定を変えてみました。
少々見えづらいですが、喋った日本語が英語に変換されていることが分かります。
f:id:bluebirdofoz:20180810093154j:plain

※ 日本語認識は、日本語版OSをインストールしている場合のみ可能です。
bluebirdofoz.hatenablog.com


以上で HOLOGRAMS 301 は終了です。

公式チュートリアル「MR and Azure 301 9章」を試してみる

本日はチュートリアルの実施枠です。
Academyの「MR and Azure 301: Language translation」の実施内容をまとめます。
docs.microsoft.com
前回記事の続きです。
bluebirdofoz.hatenablog.com
今回は「Chapter 9」です。

Chapter 9:Test in mixed reality

この時点で、シーンが適切に実装されていることをテストします。
テストするには、エディタの再生ボタンを押します。
f:id:bluebirdofoz:20180810092915j:plain

マイクに対して発話してみると、音声が認識されると共に翻訳結果が表示されます。
f:id:bluebirdofoz:20180810092926j:plain

エラーの対処

筆者の環境では最初にシーンを再生した際、以下のエラーが発生しました。
「Dictation support is not enabled on this device(see 'Get to know me' in Settings > Privacy > Speech, inking, & typing)[Operation has failed with error 0x80045509:(null)]」
f:id:bluebirdofoz:20180810092938j:plain

これは Windows音声認識の機能がオンになっていないことが原因です。
以下の通り、Windwos の設定を変更して対処します。
1.「Windowsの設定」を開き、「プライバシー」を開く。
f:id:bluebirdofoz:20180810092950j:plain

2.「音声認識、手書き入力、入力の設定」タブを開き、「音声認識サービスと入力候補をオンにします」をクリックします。
「有効にする」ボタンが表示されるので、続けてそれをクリックします。
f:id:bluebirdofoz:20180810092959j:plain

これで音声認識の機能がオンになり、エラーが解消されます。

Chapter 9 はここまでです。
次回は Chapter 10 ~ 11 を実施します。
bluebirdofoz.hatenablog.com

公式チュートリアル「MR and Azure 301 8章」を試してみる

本日はチュートリアルの実施枠です。
Academyの「MR and Azure 301: Language translation」の実施内容をまとめます。
docs.microsoft.com
前回記事の続きです。
bluebirdofoz.hatenablog.com
今回は「Chapter 8」です。

Chapter 8:Configure the Unity Scene

本記事ではシーンの構成に MRTK を用いたので、シーンの作成方法を一部変更しています。

1.Hierarchy パネルの空の領域を右クリックして、Create Empty で空の GameObject を追加します。
名前を Scripts に変更します。
f:id:bluebirdofoz:20180809093044j:plain

2.作成した Scripts オブジェクトに Assets フォルダから Results クラスをドラッグして適用します。
f:id:bluebirdofoz:20180809093054j:plain

3.Script オブジェクトの Inspector パネルを開き、適切なTextオブジェクトを階層パネルから4つのスロットにドラッグします
f:id:bluebirdofoz:20180809093103j:plain

4.次に、Translator クラスを Scripts オブジェクトにドラッグします。
f:id:bluebirdofoz:20180809093114j:plain

5.次に、MicrophoneManager クラスを Scripts オブジェクトにドラッグします。
f:id:bluebirdofoz:20180809093123j:plain

6.最後に、Translator クラスのドロップダウンを操作して変換前の言語と変換後の言語を指定します。
f:id:bluebirdofoz:20180809093132j:plain


Chapter 8 はここまでです。
次回は Chapter 9 を実施します。
bluebirdofoz.hatenablog.com

公式チュートリアル「MR and Azure 301 7章」を試してみる

本日はチュートリアルの実施枠です。
Academyの「MR and Azure 301: Language translation」の実施内容をまとめます。
docs.microsoft.com
前回記事の続きです。
bluebirdofoz.hatenablog.com
今回は「Chapter 7」です。

Chapter 7:Call to Azure and translator service

最後に作成するスクリプトは Translator クラスです。
このクラスは以下を担当します。
・認証トークンと引き換えに、Azure でアプリケーションを認証する。
・認証トークンを使用して、翻訳するテキスト(MicrophoneManager クラスから受信)を送信します。
・翻訳結果を受け取って Results クラスに渡し、UIで視覚化します。

1.Script フォルダを開きます。
2.フォルダ内で右クリックして、Creapte -> C# Script を選択します。
Script の名称は Translator に設定します。
f:id:bluebirdofoz:20180809092712j:plain

3.新しいスクリプトをダブルクリックしてVisual Studioで開きます。
4-9.以下の通り、スクリプトを編集します。
・Translator.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 名前空間の追加
using System;
using System.Collections;
using System.Xml.Linq;
using UnityEngine;
using UnityEngine.Networking;

public class Translator : MonoBehaviour {
    // メンバ変数の追加
    public static Translator instance;
    private string translationTokenEndpoint = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken";
    private string translationTextEndpoint = "https://api.microsofttranslator.com/v2/http.svc/Translate?";
    private const string ocpApimSubscriptionKeyHeader = "Ocp-Apim-Subscription-Key";

    //Substitute the value of authorizationKey with your own Key 
    //authorizationKeyの値を代入する
    private const string authorizationKey = "-InsertYourAuthKeyHere-";
    private string authorizationToken;

    // 言語を設定する
    // languages set below are: 
    // English 
    // French 
    // Italian 
    // Japanese 
    // Korean 
    // Translator Text API がサポートする60種類以上の言語の一覧は以下にあります
    // ・Supported languages in the Microsoft Translator Text API
    //   https://docs.microsoft.com/en-us/azure/cognitive-services/translator/languages
    public enum Languages { en, fr, it, ja, ko };
    public Languages from = Languages.en;
    public Languages to = Languages.it;
    
    // 初期化処理の追加
    private void Awake()
    {
        // Set this class to behave similar to singleton  
        // このクラスをシングルトンと同じように動作させます 
        instance = this;
    }

    // 初期化処理の追加(StartはAwakeの後に実行)  
    void Start()
    {
        // When the application starts, request an auth token 
        // アプリケーションが起動すると、認証トークンを要求する
        // ※ トークンは10分後に期限切れになります。
        //    アプリのシナリオに応じて、同じコルーチン呼び出しを複数回行う必要があります。
        StartCoroutine("GetTokenCoroutine", authorizationKey);
    }

    /// <summary> 
    /// Request a Token from Azure Translation Service by providing the access key. 
    /// Debugging result is delivered to the Results class. 
    /// Azure翻訳サービスからトークンを要求するには、アクセスキーを入力します。
    /// デバッグ結果はResultsクラスに渡されます。
    /// </summary> 
    private IEnumerator GetTokenCoroutine(string key)
    {
        if (string.IsNullOrEmpty(key))
        {
            throw new InvalidOperationException("Authorization key not set.");
        }

        using (UnityWebRequest unityWebRequest = UnityWebRequest.Post(translationTokenEndpoint, string.Empty))
        {
            unityWebRequest.SetRequestHeader("Ocp-Apim-Subscription-Key", key);
            yield return unityWebRequest.SendWebRequest();

            long responseCode = unityWebRequest.responseCode;

            // Update the UI with the response code 
            // 応答コードでUIを更新します
            Results.instance.SetAzureResponse(responseCode.ToString());

            if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError)
            {
                Results.instance.azureResponseText.text = unityWebRequest.error;
                yield return null;
            }
            else
            {
                authorizationToken = unityWebRequest.downloadHandler.text;
            }
        }

        // After receiving the token, begin capturing Audio with the MicrophoneManager Class
        // トークンを受け取った後、MicrophoneManagerクラスでAudioのキャプチャを開始します。 
        MicrophoneManager.instance.StartCapturingAudio();
    }

    /// <summary> 
    /// Request a translation from Azure Translation Service by providing a string.  
    /// Debugging result is delivered to the Results class. 
    /// 文字列を入力して、Azure翻訳サービスから翻訳を依頼してください。
    /// デバッグ結果はResultsクラスに渡されます。
    /// </summary> 
    public IEnumerator TranslateWithUnityNetworking(string text)
    {
        // This query string will contain the parameters for the translation 
        // このクエリ文字列には、翻訳のパラメータが含まれます。
        string queryString = string.Concat("text=", Uri.EscapeDataString(text), "&from=", from, "&to=", to);

        using (UnityWebRequest unityWebRequest = UnityWebRequest.Get(translationTextEndpoint + queryString))
        {
            unityWebRequest.SetRequestHeader("Authorization", "Bearer " + authorizationToken);
            unityWebRequest.SetRequestHeader("Accept", "application/xml");
            yield return unityWebRequest.SendWebRequest();

            if (unityWebRequest.isNetworkError || unityWebRequest.isHttpError)
            {
                Debug.Log(unityWebRequest.error);
                yield return null;
            }

            // Parse out the response text from the returned Xml
            // 返されたXmlからの応答テキストを解析します。
            string result = XElement.Parse(unityWebRequest.downloadHandler.text).Value;
            Results.instance.SetTranslatedResult(result);
        }
    }
}

f:id:bluebirdofoz:20180809092727j:plain
※ 個人の環境に合わせて "-InsertYourAuthKeyHere-"の値を Chapter 1 で取得した Key 値に修正します。
bluebirdofoz.hatenablog.com

10.Visual Studio で変更を保存して Unity に戻ります。
f:id:bluebirdofoz:20180809092756j:plain


Chapter 7 はここまでです。
次回は Chapter 8 を実施します。
bluebirdofoz.hatenablog.com

公式チュートリアル「MR and Azure 301 6章」を試してみる

本日はチュートリアルの実施枠です。
Academyの「MR and Azure 301: Language translation」の実施内容をまとめます。
docs.microsoft.com
前回記事の続きです。
bluebirdofoz.hatenablog.com
今回は「Chapter 6」です。

Chapter 6:Create the MicrophoneManager class

2つ目に作成するスクリプトは MicrophoneManager クラスです。
このクラスは以下を担当します。
・ヘッドセットまたはマシンに接続されている録音デバイスを検出します(デフォルトのいずれか)
・オーディオ(音声)をキャプチャし、ディクテーションを使用して文字列として保存します
・音声が一時停止したら、口述を Translator クラスに提出します
・必要に応じて音声キャプチャを停止できる方法をホストします

1.Script フォルダを開きます。
2.フォルダ内で右クリックして、Creapte -> C# Script を選択します。
Script の名称は MicrophoneManager に設定します。
f:id:bluebirdofoz:20180808091054j:plain

3.新しいスクリプトをダブルクリックしてVisual Studioで開きます。
4-9.以下の通り、スクリプトを編集します。
・MicrophoneManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 名前空間の追加
using UnityEngine;
using UnityEngine.Windows.Speech;

public class MicrophoneManager : MonoBehaviour {
    // Help to access instance of this object 
    // このオブジェクトのインスタンスにアクセスするための変数
    public static MicrophoneManager instance;

    // AudioSource component, provides access to mic 
    // マイクへのアクセスを提供するAudioSourceコンポーネント
    private AudioSource audioSource;

    // Flag indicating mic detection
    // マイク検出を示すフラグ
    private bool microphoneDetected;

    // Component converting speech to text 
    // 音声をテキストに変換するコンポーネント
    private DictationRecognizer dictationRecognizer;

    // 初期化処理の追加
    private void Awake()
    {
        // Set this class to behave similar to singleton 
        // このクラスをシングルトンと同じように動作させます 
        instance = this;
    }

    // 初期化処理の追加(StartはAwakeの後に実行)
    void Start()
    {
        //Use Unity Microphone class to detect devices and setup AudioSource 
        // Unity Microphoneクラスを使用してデバイスを検出し、AudioSourceを設定する
        if (Microphone.devices.Length > 0)
        {
            Results.instance.SetMicrophoneStatus("Initialising...");
            audioSource = GetComponent<AudioSource>();
            microphoneDetected = true;
        }
        else
        {
            Results.instance.SetMicrophoneStatus("No Microphone detected");
        }
    }

    // アプリケーションが音声キャプチャの開始と停止に使用するメソッドの追加
    /// <summary> 
    /// Start microphone capture. Debugging message is delivered to the Results class. 
    /// マイクキャプチャを開始します。デバッグメッセージはResultsクラスに配信されます。
    /// </summary> 
    public void StartCapturingAudio()
    {
        if (microphoneDetected)
        {
            // Start dictation 
            // ディクテーションの開始
            dictationRecognizer = new DictationRecognizer();
            dictationRecognizer.DictationResult += DictationRecognizer_DictationResult;
            dictationRecognizer.Start();

            // Update UI with mic status 
            // UIのマイクステータスを更新する
            Results.instance.SetMicrophoneStatus("Capturing...");
        }
    }

    /// <summary> 
    /// Stop microphone capture. Debugging message is delivered to the Results class. 
    /// マイクのキャプチャを停止します。デバッグメッセージはResultsクラスに配信されます。
    /// </summary> 
    public void StopCapturingAudio()
    {
        Results.instance.SetMicrophoneStatus("Mic sleeping");
        Microphone.End(null);
        dictationRecognizer.DictationResult -= DictationRecognizer_DictationResult;
        dictationRecognizer.Dispose();
    }

    //音声が停止したときに呼び出されるDictation Handlerの追加
    /// <summary>
    /// This handler is called every time the Dictation detects a pause in the speech. 
    /// Debugging message is delivered to the Results class.
    /// ディクテーションが音声のポーズを検出するたびにこのハンドラが呼び出されます。
    /// デバッグメッセージはResultsクラスに配信されます。
    /// </summary>
    private void DictationRecognizer_DictationResult(string text, ConfidenceLevel confidence)
    {
        // Update UI with dictation captured
        // ディクテーションをキャプチャしてUIを更新
        Results.instance.SetDictationResult(text);

        // Start the coroutine that process the dictation through Azure 
        // Azureを通してディクテーションを処理するコルーチンを開始する
        StartCoroutine(Translator.instance.TranslateWithUnityNetworking(text));
    }
}

※ この時点でエラーが表示されます(「The name ‘Translator’ does not exist...」)。
これは、コードが Translator クラスを参照するためです。Translator クラスは、次の章で作成します
f:id:bluebirdofoz:20180808091107j:plain

10.Visual Studio で変更を保存して Unity に戻ります。
f:id:bluebirdofoz:20180808091118j:plain


Chapter 6 はここまでです。
次回は Chapter 7 を実施します。
bluebirdofoz.hatenablog.com

公式チュートリアル「MR and Azure 301 5章」を試してみる

本日はチュートリアルの実施枠です。
Academyの「MR and Azure 301: Language translation」の実施内容をまとめます。
docs.microsoft.com
前回記事の続きです。
bluebirdofoz.hatenablog.com
今回は「Chapter 5」です。

Chapter 5:Create the Results class

最初に作成するスクリプトは、翻訳の結果を表示する方法を提供する責任を負うResultsクラスです。
クラスは以下を格納して表示します。
・Azureからの応答結果
・マイクの状態
・ディクテーションの結果(音声からテキスト)
・翻訳の結果

1.Script フォルダを作成します。
Asset フォルダで右クリックし、Create > Folder を選択します。
f:id:bluebirdofoz:20180808090903j:plain

2.作成した Script フォルダを開き、フォルダ内で右クリックして、Creapte -> C# Script を選択します。
Script の名称は Results に設定します。
f:id:bluebirdofoz:20180808090912j:plain

3.新しい結果スクリプトをダブルクリックしてVisual Studioで開きます。
4-7.以下の通り、スクリプトを編集します。
・Results.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 名前空間の追加
using UnityEngine;
using UnityEngine.UI;

public class Results : MonoBehaviour {
    // メンバ変数の追加
    public static Results instance;

    [HideInInspector]
    public string azureResponseCode;

    [HideInInspector]
    public string translationResult;

    [HideInInspector]
    public string dictationResult;

    [HideInInspector]
    public string micStatus;

    public Text microphoneStatusText;

    public Text azureResponseText;

    public Text dictationText;

    public Text translationResultText;

    // 初期化処理の追加
    private void Awake()
    {
        // Set this class to behave similar to singleton
        // このクラスをシングルトンと同じように動作させます 
        instance = this;
    }
    /// <summary>
    /// Stores the Azure response value in the static instance of Result class.
    /// Azureのレスポンス値をResultクラスの静的インスタンスに格納します。
    /// </summary>
    public void SetAzureResponse(string result)
    {
        azureResponseCode = result;
        azureResponseText.text = azureResponseCode;
    }

    /// <summary>
    /// Stores the translated result from dictation in the static instance of Result class.
    /// ディクテーションの翻訳結果をResultクラスの静的インスタンスに格納します。
    /// </summary>
    public void SetDictationResult(string result)
    {
        dictationResult = result;
        dictationText.text = dictationResult;
    }

    /// <summary>
    /// Stores the translated result from Azure Service in the static instance of Result class. 
    /// Azure Serviceの翻訳結果をResultクラスの静的インスタンスに格納します。
    /// </summary>
    public void SetTranslatedResult(string result)
    {
        translationResult = result;
        translationResultText.text = translationResult;
    }

    /// <summary>
    /// Stores the status of the Microphone in the static instance of Result class. 
    /// Resultクラスの静的インスタンスにマイクのステータスを格納します。
    /// </summary>
    public void SetMicrophoneStatus(string result)
    {
        micStatus = result;
        microphoneStatusText.text = micStatus;
    }
}

f:id:bluebirdofoz:20180808090923j:plain

8.Visual Studio で変更を保存して Unity に戻ります。
f:id:bluebirdofoz:20180808090935j:plain

Chapter 5 はここまでです。
次回は Chapter 6 を実施します。
bluebirdofoz.hatenablog.com