仮想と物理とエトセトラ

xRや物理とかごった煮の備忘録的技術ブログ

MRTK(2.7.2)のExampleを試す その3 (EyeTracking)

今回は前回の続きです。

xr-physics-work-etc.hatenablog.com

前提

今回の前提は以下です。
Unity 2019.4.17f1
MRTK 2.7.2

準備

前回と同じようにPackage Managerから対象のデモをImportします。
f:id:napo909:20211205135836p:plain

EyeTrackingDemo-00-RootScene

このSceneはEyeTrackingの各デモに遷移するためのSceneです。 f:id:napo909:20211205141810p:plain

EyeTrackingのデモでは、Gaze SettingsにEyeGazeCursorが設定されており、視線が何を指しているか確認できるようになっています。

f:id:napo909:20211205151114p:plain

EyeCalibrationChecker

デモ用のスクリプトですが、使いまわしがききそうなので、EyeCalibrationCheckerを取り扱います。
このスクリプトでは、HoloLensのEye Trackingのキャリブレーションが済んでいるかどうかで、アプリ起動時またはキャリブレーションを実施したタイミングで実行するUnityEventを切り替えることができます。
HoloLensでは、アプリ内からキャリブレーションを実施して戻ってくる、ということもあるので、Eye Trackingに関する設定を行う場合は、キャリブレーションが済んだタイミングで設定などを切り替える必要があります。

EyeCalibrationCheckerではInspector上から下記設定が行えます。

f:id:napo909:20211205142812p:plain

EyeTrackingDemo-01-BasicSetup

このデモでは、視線に追従する紫色のカーソルと、物体に視線を合わせ、タップすることで視線で物体を選択できることを試すことができます。

f:id:napo909:20211205150706p:plain

FollowEyeGazeGazeProvider

このスクリプトでは、アタッチしたオブジェクトの位置を視線でポイントしている場所に移動させることができます。
視線で何をポイントしているか、強調することができます。

Inspector上で設定できるパラメタは以下です。

  • defaultDistanceInMeters
    自分とFollowEyeGazeGazeProviderをアタッチしたオブジェクトとの距離。デフォルト値は2m

f:id:napo909:20211205155934p:plain

ColorTap

このスクリプトでは、アタッチしたオブジェクトのマテリアル色をHover, Selectしたときに変更することができます。
色を変えることで、選択できているか否か、明確にすることができます。

Inspector上で設定できるパラメタは以下です。

  • tapAction
    対象とするInputAction。選択であれば、Selectを設定する。デフォルト値はNone

  • color_IdleState
    通常時(未選択)の時に設定される色。デフォルト値はColor.cyan

  • color_OnHover
    Hover(Hand rayや視線などでポイントする)した際に変更する色。デフォルト値はColor.white

  • color_OnSelect
    tapActionに設定したものを物体に対して実行した場合に変更する色。(Selectの場合はタップ操作)デフォルト値はColor.blue

f:id:napo909:20211205160020p:plain

EyeTrackingDemo-02-TargetSelection

このデモでは、視線を合わせた際に物体に実行させることができる挙動を確認できます。
視線を合わせたり、視線を合わせた状態でタップ操作をすることで物体操作が遠距離で実施できます。

f:id:napo909:20211205153521p:plain

EyeTrackingTarget

このスクリプトでは、自オブジェクトに対して視線が当たっている際に行う動作を設定できます。
視線の操作だけでなく、ボイスコマンドにも紐づけることできます。
Inspector上で設定できるパラメタは以下です。

  • Select Action
    対象とするInputAction。選択であれば、Selectを設定する。デフォルト値はNone

  • Voice Select
    視線が合っているときに有効になるボイスコマンド。ボイスコマンドを実行することでOnSelectedが発火する。

  • Dwel Time In Sec
    OnEyeFocusDwellが発火するために視線を当て続ける必要のある時間。

  • On Look At Start
    視線を合わせ始めた際に実行されるイベント

  • While Lokking At Target
    視線を合わせ続けているときに毎フレーム実行されるイベント

  • On Look Away
    ターゲットから視線を外した際に実行されるイベント

  • On Dwell
    Dwel Time In Secで設定した時間の間視線を合わせ続けると発生するイベント。(1回のみ)

  • On Selected
    視線を合わせつつ、タップやボイスコマンドで発火させることができるイベント。

  • On Tap Down
    RaiseEventManually_TapDownが呼ばれた際に実行されるイベント

  • On Tap Up
    RaiseEventManually_TapUpが呼ばれた際に実行されるイベント

RaiseEventManually_TapUp, RaiseEventManually_TapDownについては情報があまり見つからず、実際にどのタイミングで発火するか不明瞭。

f:id:napo909:20211205154026p:plain

EyeTrackingDemo-03-Navigation

このデモでは、テクスチャの拡縮、移動を実施できるPanZoomTextureや、スクロールを実施できるScrollRectを視線を合わせることで発火させることができます。

f:id:napo909:20211205160119p:plain

OnLookAtRotateByEyeGaze

このスクリプトでは、アタッチしたオブジェクトに視線が当たっている間、物体を回転させることができます。
BaseEyeFocusHandlerを継承しており、OnEyeFocusStayをオーバライドすることで視線が当たった際の動作を設定しています。
Inspector上で設定できるパラメタは以下です。

  • Focus Enabled
    Focusが有効かどうか設定できる(BaseFocusHandlerからの継承)

  • Time To Trigger Dwell In Sec
    Dwellを発火させるために必要なFocus時間(BaseEyeFocusHandlerからの継承)

  • Speed X, Y
    それぞれの軸の回転速度。(0の場合は回転しない)

  • Inverse X, Y
    それぞれの軸の回転方向を反転させるか否か

  • Rotation Thresh In Degrees
    少しの回転を繰り返さないようにするための閾値

  • Min Rot X, Y
    最小回転角

  • Max Rot X, Y
    最大回転角

f:id:napo909:20211205162547p:plain

EyeTrackingDemo-04-TargetPositioning

このデモでは、視線を合わせることで物体を選択し、タップすることで移動させることができます。
キューブや、スライダを視線とタップ操作だけで操作することができます。

f:id:napo909:20211205164013p:plain

MoveObjByEyeGaze

このスクリプトでは、アタッチしたオブジェクトに視線が当たっている間、物体を移動させることができます。
移動させることのできる軸や、移動量を制限することができます。

  • Use Eye Supported Target Placement
    視線で物体配置を有効化するかどうかの設定

  • Min Look Away Dist To Enable Eye Warp
    ※確認中※

  • Hand Input Enabled
    移動を音声のみで行う場合は、falseにする

  • Handmapping
    手の移動量の何倍の動きを物体にさせるか

  • Delta Hand Movem Thresh
    手の動きを有効にする閾値

  • Transparency_in Transition
    ドラッグしている間のターゲットの透明度設定

  • Transparency_preview
    プレビューをドラッグしている間のターゲットの透明度設定

  • Preview Placem Dist Thresh
    ※確認中※

  • Freeze X, Y, Z
    動きを制約する軸方向

  • Local Min Max_X, Y, Z
    各軸の移動量の制約

  • Placement Surface
    配置する平面の方向(水平か、垂直か)

  • Audio_On Drag Start
    ドラッグ開始時の音

  • Audio_On Drag stop
    ドラッグ停止時の音

  • Voice Action_Put This
    ドラッグ開始に使用するInputAction(音声コマンド用)

  • Voice Action_Over Here
    ドラッグ終了時に使用するInputAction(音声コマンド用)

  • On Drag Start
    ドラッグ開始時に発生させるイベント

  • On Drop
    ドラッグ終了時に発生させるイベント

  • User as Slider
    スライダとして使用するか否か

  • Txt Output_slider Value
    スライダ位置を表示するためのTextMeshオブジェクト

  • Slider_snap To Neareset Decimal
    スライダの場合の刻み幅

f:id:napo909:20211205164415p:plain

EyeTrackingDemo-05-Visualizer

このデモでは視線の当たった箇所が熱源のように、ヒートマップを表示するデモです。
視線の軌跡を可視化することができます。

f:id:napo909:20211205170837p:plain

このデモでは、InteractableEyeTrackingTargetを組み合わせることで、Interactableのアタッチされたオブジェクトに視線を与えてタップ動作をするだけでOnClickを発火させることができます。

f:id:napo909:20211205171626p:plain

DrawOnTexture

このスクリプトでは、視線の当たった位置に、Tableとして設定したTextureから取得した色を設定できるものです。
EyeTrackingTarget::LookedAtPointを使用して視線の当たった位置の座標を取得することで、視線が当たった位置の色を変更しています。
Inspector上で設定できるパラメタは以下です。

  • Heatmap Look Up Table
    ヒートマップ(描画する色)をTextureとして設定する

  • Draw Brush Size
    ヒートマップで色を変更する範囲のサイズ

  • Draw Intensity
    ヒートマップの最大強度

  • Min Thresh Delta Heat Map
    ヒートマップ表示のための閾値

  • Use Live Input Stream
    ヒートマップの結果をすぐに表示するか否か

  • Heatmap Overlay Material Templete
    ヒートマップ描画前のベースのmaterial

f:id:napo909:20211205172738p:plain

今回はここまでです。
次回はGltfのデモを確認します。

MRTK(2.7.2)のExampleを試す その2 (Boundary, Diagnostics)

今回は前回の続きです。

xr-physics-work-etc.hatenablog.com

前提

今回の前提は以下です。
Unity 2019.4.17f1
MRTK 2.7.2

準備

前回と同じようにPackage Managerから対象のデモをImportします。
f:id:napo909:20211128170127p:plain

Boundary Visualization Example

このサンプルでは、PlayAreaなどを視覚的に表示することができます。(VR向けのため、HoloLensでは動作していないと思われる)
f:id:napo909:20211128180644p:plain

CoreServices.csを介してIMixedRealityBoundarySystemを操作することで、表示/非表示を切り替えています。

f:id:napo909:20211128172812p:plain

有効/無効を切り替える対象であるBoundsry Visualizationについては下記に記載があります。

docs.microsoft.com

### 詳細は、VR機器で試すことができた際に追記 ###

DiagnosticsDemo

このサンプルでは、アプリの状態を示すDiagnosticの機能を表示/非表示にできるサンプルです。
DiagnosticDemoControls.csが使用されているかのような記載がScene上にありますが、該当するスクリプトは見つけられず。。。記載が古い?

f:id:napo909:20211128173716p:plain

Diagnostics自体はMixedRealityToolkitDiagnostics Profileから有効/無効の設定ができます。

f:id:napo909:20211128174454p:plain

Diagnosticsは、シーン実施中にMixedRealityPlayspace配下に現れます。
Diagnosticsには2つのコンポーネントがアタッチされています。

  • DiagnosticsSystemVoiceControls.cs
    下記2種のボイスコマンドで有効/無効を切り替えることができる。

    • toggle diagnostics
      診断システムの有効/無効を切り替える。(無効の場合、Profilerも非表示になる)
    • toggle profiler
      CPU使用率などのProfile情報の表示/非表示を切り替える。
  • MixedRealityToolkitVisualProfiler.cs
    CPU使用率などのProfile情報を表示するためのコンポーネント
    基本的にはカスタマイズすることはないと思われる。

f:id:napo909:20211128174823p:plain

今回はいつになく内容が薄いですが、キリが良いので今回はここまで。
次回はEyeTrackingのサンプルを取り扱います。

MRTK(2.7.2)のExampleを試す その1 Demos-Audio

今回は、MRTK ver.2.7.2のExampleを見て、これまであまり使用してこなかったMRTKの機能を確認します。
第一回はDemos-Audioを使用します。

前提

今回の前提は以下です。
Unity 2019.4.17f1
MRTK 2.7.2

準備

まずは、Package ManagerのMixed Realiy Toolkit Examplesでインポートしたいサンプルを選択します。
Demos - AudioImport into Projectを選択しインポートします。
※ 私の場合一度インポートしているので表示はInport againになっています。
f:id:napo909:20211123135238p:plain f:id:napo909:20211123135024p:plain

ProjectウィンドウからAsset/Samples/Mixed Reality Toolkit Examples/2.7.2/Demos - Audio/ Scenesを開くとサンプルシーンを確認できます。
一つずつ確認していきます。

f:id:napo909:20211123135353p:plain

Audio Lo-Fi Effect Examples

このサンプルは、AudioLoFiEffect.csでLo-Fi効果をAudio出力に反映させるサンプルです。

ja.wikipedia.org

赤い球体から音声が出力されており、球体をタップするたびにLo-Fi効果の種類が変化します。
AudioSourceから出力される音声に対して周波数制限を行って、聞こえる音を変更することができます。
このサンプルで使用される主なMRTKコンポーネントMixedRealitySeneContent -> SoundEmitterにアタッチされているAudioLoFiEffect.csです。

f:id:napo909:20211123150230p:plain

f:id:napo909:20211123150329p:plain

AudioLoFiEffect.cs

github.com

AudioLoFiEffect.csではAudioSourceから出力される音声を、ラジオのように音声の周波数範囲を制限することができます。 Inspector上から、周波数範囲制限としてAudioLoFiSourceQualityで定義される下記の5種類を設定できます。

  • NarrowBandTelephony : 300 Hz - 3.4 kHz
  • WideBandTelephony : 50 Hz - 7 kHz
  • AmRadio : 40 Hz - 5 kHz
  • FmRadio : 30 Hz - 15 kHz
  • FullRange : 10 Hz - 22 kHz

依存コンポーネントとしてAudioSource, AudioLowPassFilter, AudioHighPassFilterがアタッチされますが、MRTKで提供されているAudioInfluencerController.csも同時にアタッチすることが推奨されています。

AudioInfluencerController.cs

github.com

AudioSourceの出力に対してMicrosoft.MixedReality.Toolkit.Audio.IAudioInfluencerのアタッチされたコンポーネントを用いて影響を与え、コントロールするためのコンポーネントです。
Inspector上から制御できる要素は下記のとおりです。

  • UpdateInterval : AudioSourceに対して操作をする間隔(デフォルト値 : 0.25 s)
  • MaxDistance : ユーザとIAudioInfluencerを検索するための最大距離 (デフォルト値 : 20 m)
  • maxObjects : 対象とするIAudioInfluencerの最大値 (デフォルト値 : 10個)
  • audioSource : 操作対象となるAudioSourceをアタッチする

AudioOcclusionExamples

このサンプルでは青色の球体から音声が出力されており、青いパネル(左)の前で聞くといつものように、後ろで聞くと若干くぐもった壁にさえぎられているように聞こえます。
このサンプルで使用される主なMRTKコンポーネントは青いパネルであるMixedRealitySeneContent -> SoundOccluderにアタッチされているAudioOccluder.csです。

f:id:napo909:20211123150104p:plain
f:id:napo909:20211123150414p:plain

AudioOccluder.cs

github.com

このスクリプトでは音声に対して、カットする周波数と通す音量の割合を設定して、遮られているかのような効果を音声に与えることができます。
IAudioInfluencerが継承されており、先ほどのAudioInfluencerControllerを用いて音声に効果を与えることができます。
Inspector上から制御できる要素は下記のとおりです。

  • CutoffFrequency : 10 Hz - 22 kHzの間でカットする周波数を設定する。設定値より高音をカットする。(デフォルト値 : 5kHz)
  • VolumePassThrough : 透過する音量を0 ~ 100%の間で設定する。(デフォルト値 : 100%)

TextToSpeechExamples

このサンプルは、先日翻訳機で使用したTextToSpeechを用いたサンプルです。
赤い球体をそれぞれクリックすることで、違う種類の音声ソースでの合成音声を試すことができます。
設定した文字列を合成音声で音声出力させることができます。

f:id:napo909:20211123152017p:plain

TextToSpeech.cs

github.com

このスクリプトでは、TextToSpeech::StartSpeaking(string)メソッドを使用することで、任意の文章(英文)を合成音声にしゃべらせることができます。
Inspector上から制御できる要素は下記のとおりです。

  • AudioSource : 音声出力に使用するAudioSourceを設定します。
  • Voice : TextToSpeechVoiceで定義された4つの合成音声(Default(system voice), David, Mark, Zira)から音源を指定できます。

WindowsMicrophoneStreamDemo

このサンプルでは、マイクの入力の大きさによって、Spatial Awarenessのメッシュの明るさが変化します。

f:id:napo909:20211123153903p:plain

このサンプルでは、特定のMRTKコンポーネントを使用しておらず、MicrophoneAmplitudeDemo.cs中でWindowsMicrophoneStreamからのマイク入力結果を使用して判定しています。

github.com

WindowsMicrophoneStream::Initialize()で初期化し、WindowsMicrophoneStream::StartStream()で録音を開始します。
WindowsMicrophoneStream::ReadAudioFrame()でそのフレームにおける音声情報を取得できます。

MRTKのコンポーネントにフォーカスしたDemos-Audioとしては以上です。
次回は、Demos - Boundaryを取り扱います。

簡易翻訳機を作ってみる その6 ボイスコマンドを使って録音を開始する

今回はその5の続きです。

xr-physics-work-etc.hatenablog.com

せっかく音声入力で翻訳対象となる文字列を入力しているので、録音の開始も音声入力で行えるように設定します。

準備

音声入力でコマンドを実行するために、Speech Commands ProfileInteractableを使用します。

docs.microsoft.com

Speech Commands Profileを設定する

まずはMixedRealityToolkitオブジェクトのMixedRealityToolkitコンポーネントからSpeech Commands Profileを編集します。
InputSpeechからSpeech Commands Profileにアクセスできます。
まずは、現在の設定を修正するためにCloneボタンを押下します。

f:id:napo909:20211114161343p:plain

Cloneボタンを押すと、今のProfileをコピーして新たなプロファイルを作成できます。
Profile Nameから作成するプロファイル名を設定して、Cloneボタンを押します。

f:id:napo909:20211114161517p:plain

新しいプロファイルを作成すると、Speech Commands Profileの中身を修正できるようになります。
Add a New Speech Commandボタンを押すと、新しい設定項目を増やすことができます。

設定項目の内容と機能は以下の通りです。

  • Keyword
    音声入力で使用する語句(実際に発声するワード)

  • LocalizationKey
    入力された文字列をWindows.ApplicationModel.Resources.ResourceLoader中で検索して該当するものを置き換える。
    説明翻訳:ローカライズされたバージョンでキーワードを上書きするために使用するオプションのキー。
    ※ 用途がよくわからない。

  • KeyCode
    Keywordを入力したときと同様の効果を持つキーの設定。
    例) F1を設定しておくと、F1キーを押したときに設定したKeywordが音声入力されたのと同じ動作をする。

  • Action
    発火するActionの設定。MixedRealityInputActionで設定されており、InteractableInput Actionと同じです。

f:id:napo909:20211114162318p:plain

今回は音声入力のため、次のように設定しました。
Lキーを押すことで、UnityEditor上でも動作確認できるはずです。
f:id:napo909:20211114165239p:plain

Interactableを設定する

次に、音声入力で発火対象になるボタンのInteractableに設定を行います。
Speech Commandに先ほど設定したRecordを設定します。 今回は、どの状態でも録音を開始できるように、Requires Focusのチェックを外します。
視線などが当たっている場合のみ音声コマンドを受け付けたい場合は、Requires Focusにチェックを付けます。

f:id:napo909:20211114170625p:plain

動作確認

Project SettingsPlayerPublishing SettingsCapabilitiesMicrophoneが有効になっていることを確認しビルドします。

f:id:napo909:20211114170850p:plain

「レコード」の発声で録音を開始することができました。
現状の問題点としては、入力終了時に結局ボタンを押す必要があることです。
試しに「レコード」を発声しても、翻訳対象の文言として認識されるだけで、select扱いにはなりませんでした。
原因は、Interactableの音声コマンド待ちより、文字入力用のDictationが優先されて音声入力を受けているためと思われます。
対策としては、無音時間○秒で完了とみなす、とかでしょうか。
DictationHandlerでは、無音が一定時間経過するとエラー発生の挙動となっていたので、無音時間で判断するにはDictationHandlerをラップするスクリプトが必要そうです。

MRTK Figma Bridgeを試してみる

今回は以前取り上げたMRTK Figma Toolkitを、Unityに取り込むためのUnity用Figma Bridgeを試してみます。

xr-physics-work-etc.hatenablog.com

MRTK Figma Bridge for Unityは、MRTK FIgma Toolkitで作成したデザインを直接MRTKに取り込むことができるツールです。

docs.microsoft.com

環境

Unity 2019.4.17f1 → 2020.3.16f1
MRTK 2.7.2

準備

Figma Toolkitのインストール

まず、MRTK Figmaの結果をインポートしたいUnityProjectを、Mixed Reality Feature Toolで開きます。

docs.microsoft.com

Discover FeatureMixed Reality ToolkitからMRTK Figma Bridgeを探し、チェックボックスにチェックを入れます。
念のため、インポート済みのMRTK2.7.2にもチェックを付けます。

f:id:napo909:20211107164719p:plain

右下のGet Featuresボタンを押すと、インポートされる内容が表示されます。
必要なものがすべて選択されていれば、Importボタンを押します。
f:id:napo909:20211107164808p:plain

右のFiles to be copied into the projectにMRTK Figma bridgeとMRTK2.7.2が設定されていることを確認し、Approveを選択します。
f:id:napo909:20211107164903p:plain

UnityProjectが更新されるので、Exitボタンを押た後、UnityProjectを開きます。

f:id:napo909:20211107164407p:plain

いくつかエラーが出ているので、エラー内容を確認したところ、Unity2019に存在しないIStyle.textOverflowを使用しているようです。
Figma Bridgeの公式チュートリアルにはUnity2019以降って書いてあったんだけどなぁ
f:id:napo909:20211107165144p:plain

docs.unity3d.com

そのため、Unity2020.3.16f1でMRTK、Figma Bridgeの導入を再度実施しました。
Unity2020.3.16f1で試したところ、今度はエラーが出ずにFigma Bridgeのメニューが選択できるようになりました。
f:id:napo909:20211107171719p:plain

Figmaの内容のインポート

先ほど確認したFugna BridgeのメニューからFigma Bridge Windowを選択するとFigma Tokenを入力するウィンドウが表示されます。
f:id:napo909:20211107171825p:plain

Figma Tokenを取得するために、ブラウザからFigmaのプロジェクト画面を開き、左上メニューからHelp and AccountAccount Settingを選択します。
※アカウント作成が必要です。
f:id:napo909:20211107172114p:plain

表示されたAccount SettingPersonal access tokensのテキストボックスに任意の文字列を入れ、エンターキーを押すとaccess tokenが生成されます。
生成されたaccess tokenをUnityのFigma Bridge WindowFigma Tokenテキストボックスに入力し、Open Fileボタンを押します。
f:id:napo909:20211107172324p:plain

次に、FigmaプロジェクトのURLからIDを取得し入力します。
URLのフォーマットは下記で、[ID]の部分を探し、コピー&ペーストします。
https://www.figma.com/file/[ID]/[Title]
参考: docs.microsoft.com

f:id:napo909:20211107172638p:plain

GetFileボタンを押してしばらくすると、対象のFigmaプロジェクトの名前が表示されます。
目的のプロジェクト同じであれば、Load Fileボタンを押下します。
f:id:napo909:20211107173036p:plain

すると、Figmaプロジェクト中のページが表示され、インポートするページを選択できます。
今回は、作成したExportExampleを選択します。
f:id:napo909:20211107173248p:plain

動作確認

Build Pagesボタンを押すと現在表示中のScene中にFigmaからインポートした内容が追加されます。
ボタンやテキストなども適用されていますが、Menuの背面のプレートは表示されず、MeshRenderer自体もアタッチされていませんでした。
また、ボタンのアイコンも適用されていません。
Figmaプロジェクトのインポート元:
f:id:napo909:20211107174256p:plain
UnityProjectでのインポート結果:
f:id:napo909:20211107173802p:plain

別途元から用意されているComponentsページもインポートしましたが、同様に正しくインポートできるもの/できないものがありました。
インポート元:
f:id:napo909:20211107174840p:plain インポート結果:
f:id:napo909:20211107175048p:plain

原因は不明ですが、MRTK Figma Bridgeはまだベータ版なので正しく動いていないのでしょう。
正しくインポートされるようになれば、デザイン試作から実装までのプロセスがより簡単になりそうです。

簡易翻訳機を作ってみる その5 翻訳結果を音声出力する

今回は前回の翻訳機の続きです。

xr-physics-work-etc.hatenablog.com

今回は、音声読み上げと、別言語を翻訳先とする翻訳を行います。
音声の読み上げでは、TextToSpeechを使用します。
TextToSpeechは、任意の文字列を音声出力するためのコンポーネントです。

docs.microsoft.com

翻訳先の変更は、DeepL APIで翻訳リクエストを行うためのtarget_langを切り替えることで実現します。

準備

音声出力する

まずは、前回のUnityProjectにTextToSpeechコンポーネントをアタッチします。
今回はTranslateResultゲームオブジェクトにアタッチしました。
f:id:napo909:20211031154826p:plain

TextToSpeechコンポーネントをアタッチすると、AudioSourceコンポーネントも一緒にアタッチされます。
TextToSpeechには2つのオプションがInspector上から設定できます。

  • Audio Source
    使用するAudioSourceコンポーネントを設定する。
  • Voice
    音声ソース(しゃべるための音源)を変更する

TextToSpeechコンポーネントのStartSpeaking(string)メソッドを使用することで、任意の文字列を音声出力することができます。

次に、音声出力有効/無効を切り替えるために、トグルボタンを配置します。
新しいトグルボタンをMRTK ToolBoxから選択し、シーン上に配置します。
f:id:napo909:20211031161946p:plain

今回は、アプリ起動時に音声出力を有効にしたいので、InteractableコンポーネントのIsToggledを有効にします。
f:id:napo909:20211031161906p:plain

次に、翻訳結果をTextToSpeechコンポーネントに渡すためのスクリプトSwitchAudioPlaying.csを作成し、Toggleボタンにアタッチします。

  • SwitchAudioPlaying.cs
クリックで展開
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.Audio;
using Microsoft.MixedReality.Toolkit.UI;

namespace SimplifiedTranslator
{
    public class SwitchAudioPlaying : MonoBehaviour
    {
        /// <summary>
        /// 翻訳機本体
        /// </summary>
        [SerializeField]
        Translator translator;
        
        /// <summary>
        /// 音声出力用コンポーネント
        /// </summary>
        [SerializeField]
        TextToSpeech textToSpeech;

        /// <summary>
        /// トグル状態取得用Interactableコンポーネント
        /// </summary>
        [SerializeField]
        Interactable interactable;

        // Start is called before the first frame update
        void Start()
        {
            if (interactable == null)
            {
                this.enabled = false;
            }
            translator.Finish_translate_event.AddListener(PlayTranslatedAudio);
        }

        /// <summary>
        /// 翻訳結果出力処理
        /// </summary>
        /// <param name="translateResult"></param>
        void PlayTranslatedAudio(string translateResult)
        {
            if (interactable.IsToggled)
            {
                textToSpeech.StartSpeaking(translateResult);
            }
        }

    }
}

f:id:napo909:20211031162600p:plain

Inspectorから対応するコンポーネントをアタッチすることで、翻訳結果取得時に、トグルボタンが有効な時には音声が出力されるようになりました。

翻訳先言語を変更する

これまでは英語にしか翻訳できなかったため、別言語にも翻訳できるようにします。
DeepL APIでは20種類以上の言語に翻訳することができます。

www.deepl.com

RadioButtonsオブジェクトをシーン上に配置し、InteractableToggleCollectionGridObjectCollectionをアタッチします。
そのオブジェクトの子として任意の数(今回は4つ)のラジオボタンを配置し、InteractableToggleCollectionコンポーネントに登録します。
GridObjectCollectionでは、ボタンを目的の並びになるようにパラメータを設定し、UnityEditor上からUpdate Collectionボタンを用いて整列します。
参考:

f:id:napo909:20211031162934p:plain f:id:napo909:20211031164347p:plain f:id:napo909:20211031163052p:plain f:id:napo909:20211031163113p:plain

次に、それぞれのボタンに言語情報を持たせるためにLangSettingコンポーネントを作成します。
このコンポーネントをそれぞれのラジオボタンにアタッチし、インスペクター上のプルダウンメニューから翻訳先の言語を設定します。

  • LangSetting.cs
クリックで展開
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SimplifiedTranslator
{
    public enum TargetLang
    {
        JA,
        EN,
        ZH,
        DE,
    }

    public class LangSetting : MonoBehaviour
    {
        [SerializeField]
        TargetLang target_lang;

        public string GetTargetLang()
        {
            return target_lang.ToString();
        }
    }
}

f:id:napo909:20211031163421p:plain

次に、現在ラジオボタンで有効になっている言語を翻訳時に取得するために、GetLangSettingコンポーネントを作成し、その3で作成したTranslateTestを一部修正します。

  • GetLangSetting.cs
クリックで展開
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.UI;

namespace SimplifiedTranslator
{
    public class GetLangSetting : MonoBehaviour
    {
        [SerializeField]
        InteractableToggleCollection interactableToggleCollection;

        public string GetLangInfo() 
        {
            Interactable interactable = interactableToggleCollection.ToggleList[interactableToggleCollection.CurrentIndex];

            return interactable.GetComponent<LangSetting>().GetTargetLang();
        }
    }
}
  • TranslateTest.cs
クリックで展開
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SimplifiedTranslator;
using TMPro;

namespace SimplifiedTranslator
{
    public class TranslateTest : MonoBehaviour
    {
        [SerializeField]
        TMP_InputField inputField;

        [SerializeField]
        TextMeshPro result;

        [SerializeField]
        Translator translator;

        /// <summary>
        /// 今回の追加点
        /// </summary>
        [SerializeField]
        GetLangSetting getLangSetting;


        // Start is called before the first frame update
        void Start()
        {
            translator.Finish_translate_event.AddListener(ShowTranslateResult);
        }

        // Update is called once per frame
        void Update()
        {

        }

        public void StartTranslate()
        {
            Debug.Log("Start Translate");
            // 今回の変更点。getLangSettingを使用することで、ラジオボタンで選択された言語をターゲットに翻訳する
            // translator.GetTranslatorResult(inputField.text, "EN");
            translator.GetTranslatorResult(inputField.text, getLangSetting.GetLangInfo());
        }

        public void ShowTranslateResult(string translated_text)
        {
            result.SetText(translated_text);
        }
    }
}

作成した、GetLangSettingコンポーネントRadioButtonsオブジェクトにアタッチし、TranslateTestコンポーネントに参照させます。

f:id:napo909:20211031164158p:plain f:id:napo909:20211031164300p:plain

これで、ラジオボタンを用いて、目的の言語に翻訳させる準備ができました。

動作確認

音声出力はアルファベットの出力の際しか取得できず、ドイツ語も発音が正しいかわかりませんが、英語では正しそうな音声出力結果を取得することができました。
中国語への翻訳の場合は、対応する文字をTextMeshProのフォントに登録していなかったため正しく表示されていません。今後対応する必要があります。

これで、少なくとも日本語→英語への翻訳結果を音声出力することができました。

簡易翻訳機を作ってみる その4 翻訳対象を声で入力する

今回は下記の続きで、前回キーボードから入力していた翻訳元の文字を、音声で入力するようにします。

xr-physics-work-etc.hatenablog.com

前回の記事で、DictationHandlerをつかっては?とのアドバイスをいただいたので、さっそく使ってみます。

bluebirdofoz.hatenablog.com

準備

MRTKのプロファイル設定を行います。
この設定は、MRTK2.7時点でも同じように実施できるため、参考記事の「プロファイルの設定」を参照し実施しました。

設定を完了すると、MixedRealityToolkitコンポーネントは以下のような状態になります。

f:id:napo909:20211024101550p:plain

Dictationのオン/オフはトグルボタンで切り替えます。
そのため、MRTK Toolboxからトグルボタンを選択し、シーン上に追加、任意の場所に移動します。
f:id:napo909:20211024103908p:plain

f:id:napo909:20211024111411p:plain

わかりやすいように、トグルボタンが有効な時はBackPlateが赤色になるようにします。
HolographicBackPlateRecordingStateマテリアルをトグルが有効になった場合に表示されるBackPlateToggleStateオブジェクトの子オブジェクトであるQuadに適用します。

f:id:napo909:20211024103612p:plain

f:id:napo909:20211024103650p:plain

次に実際にDictationを使用するために、DictationHandlerをアタッチします。
今回は、前回翻訳結果表示に使用したTranslateResultオブジェクトにアタッチしました。

音声入力されている場合、途中経過と結果をInputFiledに出力し、音声認識終了後に自動で翻訳されるようにするため、OnDictationHypothesisOnDictationCompleteにInputFIledのTMP_Inputfiled.SetTextWithoutNotifyを設定し、OnDictationCompleteにはTranslateTest.StartTranslateを追加で設定します。
現在の設定だと、誤入力された場合にも翻訳されてしまうので、音声入力の精度によっては翻訳は手動で行ったほうが良いかもしれません。
また、録音時間は規定値の10秒だと短いので、100秒に設定しています。
f:id:napo909:20211024112222p:plain

次に、先ほど追加したトグルボタンのInteractableにDictation開始、終了のためのイベントを設定します。
必要に応じてAdd Eventボタンを使い表示を増やし、Evetn Receiever TypeInteractableOnToggleReceiverを設定します。
そのあと、OnSelectにDictationHandler.StartRecording、OnDelectにdictationHandler.StopRecordingを設定します。
f:id:napo909:20211024115055p:plain

これで、音声認識で入力された文字列を元に翻訳する準備ができました。

動作確認

音声入力での翻訳元文字列入力ができました。
たまに誤認識もありますが、手動で文章も修正できるのでキーボード入力よりは早いです。

今回は短いですがここまで。
次回は翻訳後文章の自動読み上げを試します。