音声を使用して UI 要素を呼び出す

音声対応シェル (VES) は、ファーストクラスの音声エクスペリエンスをアプリ内で実現する Windows Speech Platform の拡張機能です。ユーザーは音声を使用してスクリーン コントロールを呼び出したりディクテーションによってテキストを挿入したりすることができます。 VES が目指しているのは、"見て発音する" 一般的なエンドツーエンドのエクスペリエンスを、アプリ開発者の手間を最小限にすべての Windows シェルおよびデバイスで実現することです。 それを実現するために、Microsoft Speech Platform と UI オートメーション (UIA) フレームワークが活用されています。

ユーザー エクスペリエンスのチュートリアル

以下、Xbox で VES を使用するユーザーが体験することを簡単にまとめます。VES のしくみについて深く追求する前に、その背景が把握しやすくなるはずです。

  • ユーザーが Xbox コンソールの電源を投入し、アプリを見回しながら関心のあるものを探します。

    ユーザー: "コルタナさん、マイ コレクションを開いて"

  • ユーザーはアクティブ リスニング モード (ALM) で待機します。つまり、画面に表示されたコントロールがユーザーによって呼び出されるのをコンソールが待機する状態になります。その都度 "コルタナさん" と言う必要はありません。 ユーザーはアプリの表示に切り替え、アプリ一覧をスクロールすることができます。

    ユーザー: "アプリケーション"

  • ビューをスクロールしたければ、単に次のように言います。

    ユーザー: "下へスクロール"

  • ユーザーには、関心のあるアプリのボックス アートが表示されますが、ユーザーは名前を忘れてしまいました。 ユーザーは、音声ヒント ラベルを表示するように依頼します。

    ユーザー: "ラベルを表示して"

  • 言うべきことがわかったら、アプリを起動することができます。

    ユーザー: "映画とテレビ"

  • アクティブ リスニング モードを終了するために、ユーザーは Xbox に聞き取りを停止するよう命令します。

    ユーザー: "聞き取りを停止"

  • その後、新しいアクティブ リスニング セッションを開始するには、次のように言います。

    ユーザー: "コルタナさん、選択して" または "コルタナさん、選んで"

UI オートメーションの依存関係

VES は UI オートメーション クライアントであり、アプリがその UI オートメーション プロバイダーを通じて公開する情報に依存します。 そのインフラストラクチャは、既に Windows プラットフォームのナレーター機能で使用されているものと同じです。 UI オートメーションを使用すると、コントロールの名前やその種類、実装されているコントロール パターンなど、ユーザー インターフェイス要素にプログラムからアクセスすることができます。 アプリの UI が変化すると、VES が UIA の更新イベントに反応し、更新された UI オートメーション ツリーを再解析して、操作可能な項目をすべて検出し、その情報を使用して音声認識文法を構築します。

すべての UWP アプリは UI オートメーション フレームワークにアクセスでき、ビルドされているグラフィックス フレームワーク (XAML、DirectX/Direct3D など) に関係なく、UI に関する情報を公開できます。 XAML など一部のケースでは、最も煩雑で手間のかかる部分がフレームワークによって行われるため、ナレーターや VES のサポートに必要な作業は非常に少なくなっています。

UI オートメーションについての詳細は、「UIオートメーションの基礎」をご覧ください。

コントロールの呼び出し名

VES では、音声認識エンジンにコントロール名として登録する語句 (つまりコントロールを呼び出す際にユーザーが読み上げるべき言葉) の決定に、以下のヒューリスティックが採用されています。 これは音声ヒント ラベルに表示される語句でもあります。

名前のソース (優先度順):

  1. 要素に LabeledBy という添付プロパティがある場合、そのテキスト ラベルの AutomationProperties.Name が使用されます。
  2. 要素の AutomationProperties.Name。 XAML では、コントロールのテキストの内容が AutomationProperties.Name の既定値として使用されます。
  3. コントロールが ListItem または Button である場合、有効な AutomationProperties.Name を含んだ最初の子要素が検索されます。

操作可能なコントロール

VES では、次のいずれかのオートメーション コントロール パターンを実装しているコントロールが操作可能と見なされます。

  • InvokePattern (例: Button) - 単一の明確な処理を開始または実行し、アクティブになったときに状態を保持しないコントロールを表します。

  • TogglePattern (例: Check Box) - 一連の状態を循環し、一度設定された状態を維持できるコントロールを表します。

  • SelectionItemPattern (例: Combo Box) - 選択可能な子項目のコレクションのコンテナーとして機能するコントロールを表します。

  • ExpandCollapsePattern (例: Combo Box) - 視覚的に展開してより多くのコンテンツを表示したり、折りたたんでコンテンツを非表示にしたりするコントロールを表します。

  • ScrollPattern (例: List) - 子要素のコレクションのスクロール可能なコンテナーとして機能するコントロール表します。

スクロール可能なコンテナー

ScrollPattern をサポートするスクロール可能なコンテナーの場合、VES は、"左にスクロール"、"右にスクロール" などの音声コマンドを聞き取り、そのいずれかのコマンドがユーザーによってトリガーされると、適切なパラメーターでスクロールを呼び出します。 スクロール コマンドは、HorizontalScrollPercent プロパティと VerticalScrollPercent プロパティの値に基づいて挿入されます。 たとえば、HorizontalScrollPercent が 0 より大きい場合は "左にスクロール" が追加され、100 より小さい場合は "右にスクロール" が追加されます。

ナレーターのオーバーラップ

ナレーター アプリケーションも UI オートメーション クライアントです。現在選択されている UI 要素について、読み上げるテキストのソースの 1 つとして AutomationProperties.Name プロパティを使用します。 アクセシビリティ エクスペリエンスを向上させるために、多くのアプリ開発者は、ナレーターによる読み上げ時に利用できる情報とコンテキストを増やすという目的の下で、Name プロパティに長い説明文を多重定義してきました。 しかし、このことが 2 つの機能間で葛藤を引き起こします。VES は、コントロールの表示テキストと一致 (または、ほぼ一致) する短い語句を必要とします。一方、ナレーターにとっては、コンテキストの質を高めるうえで説明語句は情報量が多くて長い方が有利です。

これを解決するために、Windows 10 Creators Update 以降では、ナレーターが、AutomationProperties.HelpText プロパティにも着目するように更新されています。 このプロパティが空でなければ、ナレーターは、AutomationProperties.Name に加えて、その内容を読み上げます。 HelpText が空の場合、ナレーターによって読み上げられるのは Name の内容のみです。 こうすることで、音声認識に適した語句の短さを Name プロパティには維持しつつ、必要に応じて説明文字列を長くすることができます。

Voice Enabled Shell が Name Configure をリッスンしていることを示す、AutomationProperties.Name と AutomationProperties.HelpText を含むボタンの背後にあるコードを示す図。

詳細については、「UI でのアクセシビリティ サポートのオートメーション プロパティ」を参照してください。

アクティブ リスニング モード (ALM)

ALM を有効にする

Xbox 上の VES は、音声入力を常時待機しているわけではありません。 ユーザーが次のように発話することで、アクティブ リスニング モードを明示的に有効にする必要があります。

  • "コルタナさん、選択して" または
  • "コルタナさん、選んで"

完了後もアクティブ リスニング モードのままになる Cortana コマンドは他にもいくつかあります。たとえば、"コルタナさん、サインインして" や "コルタナさん、ホームに移動して" が該当します。

ALM が有効になると、次の変化が現れます。

  • Cortana オーバーレイが右上隅に表示され、ユーザーは、見える内容を発話するよう促されます。 ユーザーが読み上げる間、音声認識エンジンによって認識された語句フラグメントも、この位置に表示されます。

  • VES は UIA ツリーを解析し、操作可能なコントロールをすべて見つけて、そのテキストを音声認識文法に登録し、継続リスニング セッションを開始します。

    [ラベルの表示] オプションが強調表示されているスクリーンショット。

ALM を終了する

ユーザーが音声を使って UI を操作している間、システムは ALM のままになります。 ALM を終了するには、次の 2 とおりの方法があります。

  • ユーザーが明示的に "聞き取りを停止" と言います。または
  • ALM が有効になってから、または直近のポジティブな認識から 17 秒以内にポジティブな認識結果が得られなかった場合はタイムアウトが発生します。

コントロールを呼び出す

ALM が有効になっていれば、ユーザーは音声を使用して UI を操作できます。 (表示テキストと一致する Name プロパティで) UI が正しく構成されていれば、音声を使用した操作のエクスペリエンスは、シームレスで、かつ自然なものとなるでしょう。 ユーザーは、画面に見える内容をそのまま発話することができます。

Xbox に UI をオーバーレイする

コントロールに対して VES が付ける名前が、実際に UI に表示されるテキストと異なる場合があります。 その原因として、コントロールの Name プロパティまたは添付された LabeledBy 要素が明示的に別の文字列に設定されていることが考えられます。 または、コントロールに備わっているのがアイコンまたは画像要素のみで、GUI テキストが存在しません。

このような場合、ユーザーには、そのコントロールを呼び出すために発話すべき内容を確認する手段が必要です。 そこで、アクティブ リスニングが有効になった後、"ラベルを表示して" と言うことで音声ヒントを表示できるようになっています。 操作可能なすべてのコントロール上に音声ヒント ラベルが表示されます。

ラベル数は 100 個に制限されているため、アプリの UI にある操作可能なコントロールが 100 個を超えている場合、一部のコントロールには、音声ヒント ラベルが表示されません。 この場合にどのラベルが選択されるかは決定論的ではありません。この点は、現在の、つまり UIA ツリーで最初に列挙されたときの UI の構造と構成に依存するためです。

いったん表示された音声ヒント ラベルを非表示にするコマンドはありません。次のいずれかのイベントが発生するまで表示され続けます。

  • ユーザーがコントロールを呼び出す
  • ユーザーが現在のシーンから移動する
  • ユーザーが "聞き取りを停止" と言う
  • アクティブ リスニング モードがタイムアウトする

音声ヒント ラベルの位置

音声ヒント ラベルは、コントロールの BoundingRectangle 内に、水平方向と垂直方向に中央揃えで配置されます。 コントロールが小さかったり密集したりしているために、ラベルが重なってしまったり他のコントロールの背後に隠れてしまったりする場合、VES はそれらの内容が見えるよう、ラベルの間隔を広げようと試みます。 しかし、これが常にうまくいく保証はありません。 UI があまりに密集している場合、いくつかのラベルが他のラベルで隠れてしまう可能性があります。 "ラベルを表示して" と言って UI を表示し、音声ヒントを表示するスペースが十分にあることを確認してください。

コントロールの外接する四角形内にある水平方向と垂直方向に中央に配置された音声ヒント ラベルのスクリーンショット。

コンボ ボックス

コンボ ボックスを展開すると、コンボ ボックス内の個々の項目にそれぞれ音声ヒント ラベルが表示され、ドロップダウン リストの背後にある既存のコントロールの上にそれらが重なってしまうことがよくあります。 コンボ ボックスを展開したときは、ラベルがごちゃ混ぜに (コンボ ボックスの項目のラベルとコンボ ボックスの背後にあるコントロールのラベルとが一緒に) 表示されるのを防ぐために、その子項目のラベルだけが表示され、その他の音声ヒント ラベルはすべて非表示になります。 その後、ユーザーはいずれかのドロップダウン項目を選択するか、またはコンボ ボックスを "閉じる" ことができます。

  • 折りたたんだ状態のコンボ ボックスのラベル:

    折りたたまれたコンボ ボックスにラベルが付いている [表示とサウンド] 出力ウィンドウのスクリーンショット。

  • 展開された状態のコンボ ボックスのラベル:

    展開されたコンボ ボックスにラベルが付いている [表示とサウンド] 出力ウィンドウのスクリーンショット。

スクロール可能なコントロール

スクロール可能なコントロールの場合、その各辺の中央にスクロール コマンド用の音声ヒントが表示されます。 音声ヒントは、操作可能なスクロール方向についてのみ表示されます。たとえば、垂直スクロールが利用できない場合、"上にスクロール" や "下にスクロール" は表示されません。 複数のスクロール可能領域が存在する場合、VES は序数を使用してそれらを区別します (例:「右にスクロール 1」、「右にスクロール 2」など)。

水平方向にスクロールする UI の左スクロールと右スクロールの音声ヒントのスクリーンショット。

曖昧性の除去

同じ名前の UI 要素が複数ある場合や、音声認識エンジンが複数の候補と一致した場合、VES は不明瞭解消モードに移行します。 このモードでは、ユーザーが適切な要素を選択できるよう、関連する要素の音声ヒント ラベルが表示されます。 ユーザーは "キャンセル" と言うことで、不明瞭解消モードを取り消すことができます。

次に例を示します。

  • アクティブ リスニング モードで、不明瞭解消前に、ユーザーが "Am I Ambiguous (あいまいですか)" と言います。

    [表示された内容を言えるようになる] オプションが表示され、ボタンにラベルが表示されていないことを示すアクティブ リスニング モードのスクリーンショット。

  • 両方のボタンが一致し、不明瞭解消モードが開始します。

    ボタンに [どれが必要でしたか] オプションが表示され、項目 1 と項目 2 のラベルが付いているアクティブなリスニング モードのスクリーンショット。

  • "2 を選択" と言うと、クリック操作が行われたことがわかります。

    [今すぐ表示] オプションが表示され、最初のボタンに [自分があいまいです] というラベルが付いているアクティブなリスニング モードのスクリーンショット。

サンプル UI

以下に示したのは、XAML ベースの UI の例です。AutomationProperties.Name がさまざまな方法で設定されています。

<Page
    x:Class="VESSampleCSharp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:VESSampleCSharp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Button x:Name="button1" Content="Hello World" HorizontalAlignment="Left" Margin="44,56,0,0" VerticalAlignment="Top"/>
        <Button x:Name="button2" AutomationProperties.Name="Launch Game" Content="Launch" HorizontalAlignment="Left" Margin="44,106,0,0" VerticalAlignment="Top" Width="99"/>
        <TextBlock AutomationProperties.Name="Day of Week" x:Name="label1" HorizontalAlignment="Left" Height="22" Margin="168,62,0,0" TextWrapping="Wrap" Text="Select Day of Week:" VerticalAlignment="Top" Width="137"/>
        <ComboBox AutomationProperties.LabeledBy="{Binding ElementName=label1}" x:Name="comboBox" HorizontalAlignment="Left" Margin="310,57,0,0" VerticalAlignment="Top" Width="120">
            <ComboBoxItem Content="Monday" IsSelected="True"/>
            <ComboBoxItem Content="Tuesday"/>
            <ComboBoxItem Content="Wednesday"/>
            <ComboBoxItem Content="Thursday"/>
            <ComboBoxItem Content="Friday"/>
            <ComboBoxItem Content="Saturday"/>
            <ComboBoxItem Content="Sunday"/>
        </ComboBox>
        <Button x:Name="button3" HorizontalAlignment="Left" Margin="44,156,0,0" VerticalAlignment="Top" Width="213">
            <Grid>
                <TextBlock AutomationProperties.Name="Accept">Accept Offer</TextBlock>
                <TextBlock Margin="0,25,0,0" Foreground="#FF5A5A5A">Exclusive offer just for you</TextBlock>
            </Grid>
        </Button>
    </Grid>
</Page>

上記のサンプルを使用したときに、音声ヒント ラベルがある状態とない状態の UI がどのように表示されるかを以下に示します。

  • アクティブ リスニング モードで、ラベルが表示されていないとき:

    [ラベルを表示するには]、[ラベルの表示] オプションが表示され、ラベルが表示されていない状態のアクティブリスニング モードのスクリーンショット。

  • アクティブ リスニング モードで、ユーザーが "ラベルを表示して" と言った後:

    [完了したら、リッスンを停止] オプションが表示され、[UI] コントロールにラベルが表示されているアクティブリスニング モードのスクリーンショット。

button1 の場合、コントロールの表示可能なテキスト コンテンツから得られるテキストを使用して、AutomationProperties.Name プロパティの値が XAML によって自動的に設定されます。 明示的に設定された AutomationProperties.Name がなくても音声ヒント ラベルが存在するのはそのためです。

button2 では、AutomationProperties.Name に、コントロールのテキスト以外の値が明示的に設定されています。

comboBox では、LabeledBy プロパティを使用して、label1 をオートメーションName のソースとして参照しています。また、label1 では、AutomationProperties.Name を画面にレンダリングされる文字列よりも自然な言い回し、つまり、"Select Day of Week (曜日を選択)" ではなく "Day of Week (曜日)" に設定しています。

最後に、button3 では、VES が最初の子要素から Name を取得します。button3 自体には AutomationProperties.Name が設定されていないためです。

関連項目