クライアントまたはサーバーサイドのフルフィルメントを使用してビルドを継続する

基本を学んだので、Canvas 固有のメソッドを使用してアクションを拡張し、カスタマイズすることができます。Actions プロジェクトの作成時に、クライアント フルフィルメント モデルとサーバーサイド フルフィルメント モデルのどちらでアクションを開発するかを選択できます。これらのオプションの詳細については、Interactive Canvas を有効にするをご覧ください。

クライアント フルフィルメント モデル オプションを選択した場合は、アクションで以下を使用できます。

サーバー フルフィルメント モデルのオプションを選択した場合は、アクションで以下を使用できます。

一部の Interactive Canvas API は、特定のフルフィルメント モデルでの使用はおすすめしません。次の表に、クライアント フルフィルメント オプションを選択したときに有効になる API と、各モデルでこれらの API が推奨されるか推奨されないかを示します。

API 名 サーバー フルフィルメント モデルでのサポート クライアント フルフィルメント モデルでのサポート
sendTextQuery() サポート対象ですが、非推奨(詳細については sendtextQuery() をご覧ください)
outputTts()
triggerScene() ×
createIntentHandler(), expect(), clearExpectations(), prompt() ×
createNumberSlot(),createTextSlot, createConfirmationSlot, createOptionsSlot() ×
setHomeParam(), getHomeParam(), setUserParam(), getUserParam() ×

以降のセクションでは、Interactive Canvas アクションでクライアントとサーバーサイドのフルフィルメント モデル用の API を実装する方法について説明します。

クライアントサイド フルフィルメントを使用する

ウェブアプリのロジックには、次の Interactive Canvas API を実装できます。

outputTts()

この API を使用すると、Actions Builder から静的プロンプトを送信したり Webhook を呼び出すことなく、デバイスからテキスト読み上げ(TTS)を出力できます。TTS に関連付けられたサーバーサイド ロジックが不要な場合は、クライアントサイドから outputTts() を使用して、サーバーへの移動をスキップし、ユーザーへの応答時間を短縮できます。

クライアントサイドの outputTts() は、サーバーサイド TTS を中断またはキャンセルできます。サーバー側の TTS の中断を回避するには、次の点に注意してください。

  • セッションの開始時に outputTts() を呼び出さないようにします。代わりに、アクションの最初の会話ターンでサーバーサイド TTS を使用します。
  • ユーザーの操作が間に合わないときに、outputTts() を連続して呼び出さないようにしてください。

次のスニペットは、outputTts() を使用してクライアントサイドから TTS を出力する方法を示しています。

interactiveCanvas.outputTts(
      '<speak>This is an example response.</speak>', true);

また、outputTts()onTtsMark() を使用して、SSML マーカーをテキスト シーケンス内に配置することもできます。onTtsMark() を使用すると、次のスニペットに示すように、SSML TTS 文字列の特定のポイントでウェブアプリ アニメーションまたはゲーム状態が同期されます。

interactiveCanvas.outputTts(
      '<speak>Speak as <mark name="number" /> number <break time="700ms"/>' +
      '<say-as interpret-as="cardinal">12345</say-as> <break time="300ms"/> ' +
      'Speak as <mark name="digits" /> digits <break time="700ms"/>' +
      '<say-as interpret-as="characters">12345</say-as></speak>', true);

上記の例では、レスポンスをカスタマイズする 2 つのマークが TTS でウェブアプリに送信されます。

クライアントでインテント フルフィルメントを処理する

Interactive Canvas のサーバー フルフィルメント モデルでは、すべてのインテントを Webhook で処理する必要があるため、アクションのレイテンシが増加します。Webhook を呼び出す代わりに、ウェブアプリ内でインテントのフルフィルメントを処理できます。

クライアントサイドでインテントを処理するには、次の API を使用します。

  • createIntentHandler(): Actions Builder で定義されたカスタム インテントに対して、ウェブアプリ コードでインテント ハンドラを定義できるメソッド。
  • expect(): ユーザーがインテントをマッチングできるように、インテント ハンドラを有効化または登録するメソッド。
  • clearExpectations(): 現在アクティブになっているすべてのインテントの期待値を消去する方法。これにより、ユーザーがインテントに一致する発話を発話した場合でも、インテントが一致しなくなります。
  • deleteHandler(): 個々のインテント ハンドラを無効にして、これらのインテントが一致しないようにするメソッド。

これらの API を使用すると、Interactive Canvas アクションのさまざまな状態に応じて、インテントを選択的に有効または無効にできます。これらのインテントを有効にするには、インテント ハンドラで expect() を使用する必要があります。

インテント ハンドラを有効にする

インテント ハンドラの有効化は、2 段階のプロセスです。まず、Actions Builder でインテントを定義する必要があります。次に、インテントをマッチング可能にするために、インテント ハンドラで expect() を呼び出す必要があります。

クライアントサイドでインテント ハンドラを構成して有効にする手順は次のとおりです。

  1. Actions Console でプロジェクトを開き、カスタム インテントを追加します。
  2. [Is this a global intent?] で [Yes] を選択します。

  3. インテントを構成して、[Save] をクリックします。

  4. 次のスニペットに示すように、ウェブアプリのロジックでインテントのハンドラを定義します。

    /**
    * Define handler for intent.
    */
    const bookTableIntent = interactiveCanvas.createIntentHandler('reserveTable',
      matchedIntent => {
        console.log("Intent match handler to reserve a table was triggered!");
      });
    
    /**
    * Define handler for intent with an argument.
    */
    const bookTableIntent = interactiveCanvas.createIntentHandler('reserveTable',
      matchedIntent => {
        const numberOfPeople = matchedIntent.getIntentArg('numberOfPeople');
        console.log(`Intent match handler to reserve a table for ${number of people} was triggered!`);
      });
    
  5. 次のスニペットに示すように、expect() メソッドを呼び出してインテント ハンドラを登録します。

    /**
    * Define handler for intent and expect() it.
    */
    const bookTableIntent = interactiveCanvas.createIntentHandler('reserveTable',
      matchedIntent => {
        console.log("Intent match handler to reserve a table was triggered!");
      });
    var handler = interactiveCanvas.expect(bookTableIntent);
    

インテント ハンドラを無効にする

インテント ハンドラを定義したら、アクションの必要に応じてインテントを有効化または無効化できます。expect() を呼び出してインテントを有効にすると、deleteHandler() メソッドを含むオブジェクトが返されます。これを使用して、新しく作成されたハンドラを無効にできます。インテントが現在アクティブでない場合でも、インテント ハンドラの定義は保持されるため、必要に応じてインテントを再度有効にすることができます。

インテント ハンドラを無効にするには、次のスニペットに示すように、インテント ハンドラで deleteHandler() を呼び出します。

    /**
    * Define handler for intent and expect() it.
    */
    const bookTableIntent = interactiveCanvas.createIntentHandler('reserveTable',
      matchedIntent => {
        console.log("Intent match handler to reserve a table was triggered!");
      });
    var handler = interactiveCanvas.expect(bookTableIntent);
    
    // Delete the handler for `bookTableIntent`.
    handler.deleteHandler();
    

次のスニペットに示すように、expect() を呼び出すと、無効化されたインテント ハンドラを再度追加できます。

    // Re-add the `bookTableIntent` handler.
    handler = interactiveCanvas.expect(bookTableIntent);

インテントを一括で無効にするには、clearExpectations() メソッドを使用します。このメソッドは、現在有効になっているすべてのインテントを無効にします。次のスニペットは、すべてのインテント ハンドラに対する想定を明確化する方法を示しています。

interactiveCanvas.clearExpectations();

クライアントでスロットフィルを処理する

Actions Builder 内でシーンにスロットフィルを追加する代わりに、ウェブアプリで直接スロットフィルを処理できます。

クライアント側でスロットフィルを処理するには、まず次のいずれかの API を使用してスロットを作成する必要があります。

  • createNumberSlot(callback, hints): ウェブアプリのコードで番号スロットを定義できるメソッド。ユーザーに番号の入力を求めるために使用します。
  • createTextSlot(callback, hints): ウェブアプリのコードでテキスト スロットを定義できるメソッド。ユーザーに単語の入力を求めるために使用します。
  • createConfirmationSlot(callback, hints): ウェブアプリのコードに確認スロットを定義できるメソッド。ユーザーに確認(はい/いいえ)を求めるために使用します。
  • createOptionsSlot(options, callback, hints): ウェブアプリのコードでオプション スロットを定義できるメソッド。事前定義されたオプションのリストから選択するようユーザーに促すために使用します。

スロットを作成する際は、必要に応じて triggerHints を定義できます。これは、アクションの自然言語理解(NLU)システムを改善するキーワードです。これらのキーワードは、ユーザーがスロットを埋めるときに発話する可能性のある短い単語にする必要があります。たとえば、番号スロットの triggerHints キーワードは years です。会話の中の年齢に関する質問に「I am thirty years of」(30 歳)というレスポンスが返ってくると、アクションはそのユーザーがスロットを適切に埋めていると認識する可能性が高くなります。

スロットを作成したら、prompt API を使用してユーザーにスロットの入力を求めるプロンプトを表示できます。

  • prompt(tts, slot): スロットが埋められるか尋ねるプロンプトをユーザーに TTS を出力するメソッド。

prompt() を呼び出すと、塗りつぶしスロットのステータスと値を含む Promise が返されます。

番号スロットを作成

番号スロットを使用すると、会話中にユーザーに番号を尋ねるように求めることができます。スロットフィルの詳細については、Actions Builder ドキュメントのスロットフィルのセクションをご覧ください。

クライアントサイドでユーザーに番号スロットへの入力を求めるメッセージを表示する手順は次のとおりです。

  1. createNumberSlot() メソッドを呼び出して、ウェブアプリ ロジックに番号スロットを作成します。

    /**
     * Create number slot.
     */
    const triggerHints = { associatedWords: ['guess number', 'number'] };
    const slot = interactiveCanvas.createNumberSlot(
      number => {
        console.log(`Number guessed: ${number}.`);
      }, triggerHints);
    
    
  2. 次のスニペットに示すように、prompt() メソッドを呼び出してユーザーにスロットの入力を求め、返された Promise のスロット値を処理します。

    const promptPromise = interactiveCanvas.prompt(
      { text: 'What number am I thinking of between 1 and 10?' }, slot);
    
    promptPromise.then(
      answer => {
        if (answer.status == interactiveCanvas.AnswerStatus.ANSWERED) {
          // answer === {value: 5, status: ANSWERED}
          // Do something with answer.value
        } else {
          console.error('Promise returned unsuccessful status ' + answer.status);
        }
      });
    

テキスト スロットを作成

テキスト スロットを使用すると、会話中にユーザーに単語の入力を求められます。スロットフィルの詳細については、Actions Builder ドキュメントのスロットフィルのセクションをご覧ください。

クライアントサイドでユーザーにテキスト スロットへの入力を求めるメッセージを表示する手順は次のとおりです。

  1. createTextSlot() メソッドを呼び出して、ウェブアプリ ロジックにテキスト スロットを作成します。

    /**
     * Create text slot.
     */
    const triggerHints = { associatedWords: ['favorite color', 'color'] };
    const slot = interactiveCanvas.createTextSlot(
      text => {
        console.log(`Favorite color: ${text}.`);
      }, triggerHints);
    
    
  2. 次のスニペットに示すように、prompt() メソッドを呼び出してユーザーにスロットの入力を求め、返された Promise のスロット値を処理します。

    const promptPromise = interactiveCanvas.prompt(
      { text: 'What is your favorite color?' }, slot);
    
    promptPromise.then(
      answer => {
        if (answer.status == interactiveCanvas.AnswerStatus.ANSWERED) {
          // answer === {value: "red", status: ANSWERED}
          // Do something with answer.value
        } else {
          console.error('Promise returned unsuccessful status ' + answer.status);
        }
      });
    

確認スロットを作成

確認スロットを使用すると、ユーザーに確認を求めることができます(ユーザーは「はい」または「いいえ」でスロットを埋めることができます)。スロットフィルの詳細については、Actions Builder ドキュメントのスロットフィルのセクションをご覧ください。

クライアント側で確認スロットに入力するようユーザーに促す手順は次のとおりです。

  1. createConfirmationSlot() メソッドを呼び出して、ウェブアプリ ロジックに確認スロットを作成します。

    /**
     * Create confirmation slot (boolean).
     */
    const triggerHints = { associatedWords: ['user confirmation', 'confirmation'] };
    const slot = interactiveCanvas.createConfirmationSlot(
      yesOrNo => {
        console.log(`Confirmation: ${yesOrNo}`);
      }, triggerHints);
    
    
  2. 次のスニペットに示すように、prompt() メソッドを呼び出してユーザーにスロットの入力を求め、返された Promise のスロット値を処理します。

    const promptPromise = interactiveCanvas.prompt(
      { text: 'Do you agree to the Terms of Service?' }, slot);
    
    promptPromise.then(
      answer => {
        if (answer.status == interactiveCanvas.AnswerStatus.ANSWERED) {
          // answer === {value: true, status: ANSWERED}
          // Do something with answer.value
        } else {
          console.error('Promise returned unsuccessful status ' + answer.status);
        }
      });
    

オプション スロットの作成

オプション スロットを使用すると、事前定義のオプションのリストから選択するようユーザーに促すことができます。スロットフィルの詳細については、Actions Builder ドキュメントのスロットフィルのセクションをご覧ください。

クライアント側でオプション スロットに入力するようユーザーに促す手順は次のとおりです。

  1. createOptionsSlot() メソッドを呼び出して、ウェブアプリ ロジックにオプション スロットを作成します。

    /**
     * Create options slot (list selection).
     */
    const triggerHints = { associatedWords: ['select fruit', 'choose fruit'] };
    // Define selectable options
    const options = [{
      key: 'apple',
      synonyms: ['apple', 'large apple', 'gala apple'],
    }, {
      key: 'banana',
      synonyms: ['banana', 'green banana', 'plantain'],
    }];
    const slot = interactiveCanvas.createOptionsSlot(
      options,
      selectedOption => {
        console.log(`You have selected ${selectedOption} as your fruit.`);
      }, triggerHints);
    
    
  2. 次のスニペットに示すように、prompt() メソッドを呼び出してユーザーにスロットの入力を求め、返された Promise のスロット値を処理します。

    const promptPromise = interactiveCanvas.prompt(
      { text: 'Would you like a banana or an apple?' }, slot);
    
    promptPromise.then(
      answer => {
        if (answer.status == interactiveCanvas.AnswerStatus.ANSWERED) {
          // answer === {value: 'apple', status: ANSWERED}
          // Do something with answer.value
        } else {
          console.error('Promise returned unsuccessful status ' + answer.status);
        }
      });
    

triggerScene()

triggerScene() API を使用すると、クライアントサイド フルフィルメントから Interactive Canvas アクションの別のシーンに移行できます。また、triggerScene() を使用すると、Webhook を必要とする Actions Builder のシステムシーンにユーザーがアクセスする必要がある場合に、クライアント側のフルフィルメントからサーバー側のフルフィルメントに切り替えることができます。たとえば、ユーザーがアカウントをリンクしたり、通知を受信したりする必要があるときに、triggerScene() を呼び出すことができます。その後、そのシーンから Canvas プロンプトを使用してクライアントサイド フルフィルメントに戻ることができます。

次のスニペットは、アクションに triggerScene() を実装する方法を示しています。

interactiveCanvas.triggerScene('SceneName').then((status) => {
  console.log("sent the request to trigger scene.");
}).catch(e => {
  console.log("Failed to trigger a scene.");
})

クライアント上のホームストレージとユーザー ストレージ

Webhook を使用してホーム ストレージとユーザー ストレージの値を取得および設定する代わりに、クライアントサイドの API を呼び出して、ウェブアプリでホーム ストレージとユーザー ストレージを処理できます。ウェブアプリは、これらの保存済み値を複数のセッション(プロンプトや条件など)で使用し、必要に応じて特定の世帯やユーザーの値にアクセスできます。これらの API を使用すると、ストレージの値を取得および設定するために Webhook を呼び出す必要がなくなるため、Interactive Canvas アクションのレイテンシを短縮できます。

ウェブアプリのホームとユーザーのストレージは、Webhook 内のストレージと同じ一般原則に従います。家とユーザーのストレージについて詳しくは、ホーム ストレージユーザー ストレージのドキュメントをご覧ください。

クライアントサイドのホーム ストレージ

ホームストレージを使用すると、ホームグラフに基づいて世帯のユーザーの値を保存できます。このストレージは家全体のすべてのセッションで共有されます。たとえば、ユーザーが家でインタラクティブ キャンバス ゲームをプレイした場合、ゲームのスコアをホーム ストレージに保存できます。家の他のメンバーは、保存されたスコアを使用して引き続きゲームをプレイできます。

アクションでホーム ストレージをサポートする手順は次のとおりです。

  1. Actions Console で、[Deploy] > [Directory information] > [Additional Information] に移動します。
  2. [Do your Actions use home storage?] の [Yes] チェックボックスをオンにします。

ウェブアプリでホーム ストレージに値を書き込むには、次のスニペットに示すように、setHomeParam() メソッドを呼び出します。

interactiveCanvas.setHomeParam('familySize',  10).then(
      result => {
        console.log('Set home param success');
      },
      fail => {
        console.error(err);
      });

ウェブアプリでホーム ストレージから値を読み取るには、次のスニペットに示すように、getHomeParam() メソッドを呼び出します。

interactiveCanvas.getHomeParam('familySize').then(
      value => {
        console.log(JSON.stringify(result));
      },
      err => {
        console.error(err);
      }
  );

既存のホーム ストレージをすべて削除するには、次のスニペットに示すように resetHomeParam() メソッドを呼び出します。

interactiveCanvas.resetHomeParam();

クライアントサイドのユーザー用ストレージ

ユーザー ストレージでは、複数のセッションをまたいで特定の確認済みのユーザーのパラメータ値を保存できます。たとえば、ユーザーがゲームをプレイしている場合、そのユーザーのゲームのスコアを保存できます。その後のゲームプレイ セッションで、ユーザーは同じスコアでゲームをプレイし続けることができます。

ウェブアプリのユーザー ストレージに値を書き込むには、次のスニペットに示すように、setUserParam() メソッドを呼び出します。

interactiveCanvas.setUserParam('color',  'blue').then(
      result => {
        console.log('Set user param success');
      },
      err => {
        console.error(err);
      });

ウェブアプリのユーザー ストレージから値を読み取るには、次のスニペットに示すように、getUserParam() メソッドを呼び出します。

interactiveCanvas.getUserParam('color').then(
      value => {
        console.log(JSON.stringify(result));
      },
      err => {
        console.error(err);
      }
  );

既存のユーザー ストレージをすべて消去するには、次のスニペットに示すように resetUserParam() メソッドを呼び出します。

interactiveCanvas.resetUserParam();

setCanvasState()

setCanvasState() メソッドを使用すると、Interactive Canvas ウェブアプリからフルフィルメントに状態データを送信し、ウェブアプリが状態を更新されたことをアシスタントに通知できます。ウェブアプリは、更新後の状態を JSON オブジェクトとして送信します。

setCanvasState() を呼び出してもインテントは呼び出されません。setCanvasState() を呼び出した後に、sendTextQuery() が呼び出された場合、またはユーザークエリが会話のインテントと一致する場合、前の会話ターンで setCanvasState() を使用して設定されたデータが、後続の会話ターンで使用できるようになります。

次のスニペットでは、ウェブアプリが setCanvasState() を使用して Canvas の状態データを設定しています。

JavaScript

this.action.canvas.setCanvasState({ score: 150 })
    

Webhook からキャンバスの状態を参照する

保存された Canvas の状態値は、フルフィルメント コードで参照できます。値を参照するには、conv.context.canvas.state.KEY 構文を使用します。ここで、KEY はキャンバスの状態値が設定されたときに指定されたキーです。

たとえば、以前にゲームのハイスコア値をパラメータ score として Canvas の状態に保存していた場合は、conv.context.canvas.state.score を使用してその値を参照し、フルフィルメントでその値にアクセスします。

Node.js

app.handle('webhook-name', conv => {
    console.log(conv.context.canvas.state.score);
})
    

プロンプト内で Canvas の状態を参照する

保存されている Canvas の状態値をプロンプトで参照できます。値を参照するには、$canvas.state.KEY 構文を使用します。ここで、KEY はキャンバスの状態値が設定されたときに指定されたキーです。

たとえば、以前にゲームのハイスコア値をパラメータ score として Canvas の状態に保存していた場合は、$canvas.state.score を使用してその値を参照し、プロンプトでその値にアクセスします。

JSON

{
  "candidates": [{
    "first_simple": {
      "variants": [{
        "speech": "Your high score is $canvas.state.score."
      }]
    }
  }]
}
    

条件内でキャンバスの状態を参照する

保存されている Canvas の状態値を条件で参照することもできます。値を参照するには、canvas.state.KEY 構文を使用します。ここで、KEY は Canvas の状態値が設定されたときに指定されたキーです。

たとえば、以前にゲームのハイスコア値をパラメータ score として Canvas の状態に保存しており、それを条件で値 999 と比較する場合は、canvas.state.score を使用して条件の保存済み値を参照できます。この場合、条件式は次のようになります。

条件の構文

canvas.state.score >= 999
    

sendTextQuery()

sendTextQuery() メソッドは、テキストクエリを会話型アクションに送信して、プログラムでインテントを照合します。このサンプルでは、sendTextQuery() を使用して、ユーザーがボタンをクリックしたときに三角形が回転するゲームを再開します。ユーザーが [ゲームを再開] ボタンをクリックすると、sendTextQuery()Restart game インテントに一致するテキストクエリを送信し、Promise を返します。この Promise により、インテントがトリガーされた場合は SUCCESS、トリガーされていない場合は BLOCKED が返されます。次のスニペットはインテントに一致し、Promise の成功と失敗のケースを処理します。

JavaScript

…
/**
* Handle game restarts
*/
async handleRestartGame() {
    console.log(`Request in flight`);
    this.button.texture = this.button.textureButtonDisabled;
    this.sprite.spin = false;
    const res = await this.action.canvas.sendTextQuery('Restart game');
    if (res.toUpperCase() !== 'SUCCESS') {
        console.log(`Request in flight: ${res}`);
        return;
    }
    console.log(`Request in flight: ${res}`);
    this.button.texture = this.button.textureButtonDisabled;
    this.sprite.spin = false;
}
…
    

Promise の結果が SUCCESS になると、Restart game Webhook ハンドラはウェブアプリに Canvas レスポンスを送信します。

JavaScript

…
app.handle('restart', conv => {
  conv.add(new Canvas({
    data: {
      command: 'RESTART_GAME'
    }
  }));
});
…
    

この Canvas レスポンスによって onUpdate() コールバックがトリガーされ、以下の RESTART_GAME コード スニペットのコードが実行されます。

JavaScript

…
RESTART_GAME: (data) => {
    this.scene.button.texture = this.scene.button.textureButton;
    this.scene.sprite.spin = true;
    this.scene.sprite.tint = 0x00FF00; // green
    this.scene.sprite.rotation = 0;
},
…
    

サーバーサイド フルフィルメントを使用する

Webhook に実装できる Interactive Canvas API は次のとおりです。

全画面モードを有効にする

デフォルトでは、Interactive Canvas ウェブアプリの画面上部のヘッダーにアクションの名前が表示されます。enableFullScreen を使用すると、ヘッダーを削除し、読み込み画面に表示される一時的なトーストに置き換えることができます。これにより、ユーザーはアクションを操作しながら全画面表示できます。トースト メッセージには、アクションの表示名、デベロッパー名、アクションの終了手順が表示されます。トーストの色は、ユーザーがデバイスでテーマとして選択した内容によって異なります。

図 1. アクションの読み込み画面に表示されるトースト メッセージ

ユーザーが頻繁にアクションとやり取りすると、トースト メッセージは一時的に読み込み画面に表示されなくなります。ユーザーがしばらくの間アクションを操作しなかった場合、そのアクションを起動するとトースト メッセージが再度表示されます。

全画面モードは、Webhook または Actions Builder の静的プロンプトで有効にできます。

Webhook で全画面モードを有効にするには、次の手順を行います。

  1. セッションの Webhook から返される最初の canvas レスポンスで、enableFullScreen フィールドを true に設定します。次のスニペットは、Node.js クライアント ライブラリを使用した実装例です。

     const { conversation, Canvas } = require('@assistant/conversation');
     const functions = require('firebase-functions');
    
     const app = conversation();
    
     app.handle('invocation_fullscreen', conv => {
       conv.add(new Canvas(
         {
           url: 'https://example-url.com',
           enableFullScreen: true
         }));
     });
    
     exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
    

Actions Builder の静的プロンプトで全画面モードを有効にする手順は次のとおりです。

  1. Actions Console でプロジェクトを開きます。
  2. ナビゲーション バーで [Develop] をクリックし、最初の canvas レスポンスを含むプロンプトを開きます。
  3. 次のスニペットに示すように、enable_full_screentrue に設定します。

     {
      "candidates": [
        {
          "canvas": {
            "url": "https://example-url.com",
            "enable_full_screen": true
          }
        }
      ]
    }
    

continueTtsDuringTouch

デフォルトでは、ユーザーがインタラクティブ キャンバス アクションの使用中に画面をタップすると、TTS の再生が停止します。TTS を有効にすると、ユーザーが continueTtsDuringTouch で画面に触れても再生が継続されるようにできます。この動作を同じセッション内でオンまたはオフにすることはできません。

この動作は、Webhook または Actions Builder の静的プロンプトに実装できます。

ユーザーが Webhook で画面をタップした後も TTS が続行されるようにするには、次の手順を行います。

  • セッションの Webhook から返される最初の canvas レスポンスで、continueTtsDuringTouch フィールドを true に設定します。次のスニペットは、Node.js クライアント ライブラリを使用した実装例です。

    const { conversation, Canvas } = require('@assisant/conversation');
    const functions = require('firebase-functions');
    
    const app = conversation();
    
    app.handle('intent-name', conv => {
      conv.add(new Canvas(
        {
          url: 'https://example-url.com',
          continueTtsDuringTouch: true
        }));
    });
    
    exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
    

Actions Builder で静的プロンプトで画面をタップした後も TTS が続行されるようにするには、次の手順を行います。

  1. Actions Console でプロジェクトを開きます。
  2. ナビゲーション バーで [Develop] をクリックし、最初の canvas レスポンスを含むプロンプトを開きます。
  3. 次のスニペットに示すように、continue_tts_during_touchtrue に設定します。

      {
       "candidates": [
         {
           "canvas": {
             "url": "https://example-url.com",
             "continue_tts_during_touch": true
           }
         }
       ]
     }