Alexaの音声の中断を制御する



Alexaの音声の中断を制御する

Alexaに対するスキルの応答に出力音声が含まれている場合は、新しい音声により、Alexaが現在話している音声を中断するかどうかを制御できます。このトピックでは、この動作を制御する理由とその際に使用するアトリビュートについて説明します。

概要

Alexaが現在話している音声を中断させたい場合があります。たとえば、トリビアスキル付きの点灯式プッシュボタンガジェットがあるとします。Alexaが質問している最中にユーザーがブザーを鳴らすと、Alexaに質問を中断させ、「プレイヤー1さん、答えは何ですか?」と発話させる場合があります。

また、Alexaに発話を続けさせてから、新しい音声を読み上げさせる場合もあります。先ほどの例の続きで、トリビアスキルを開始するときには、「ロールコール」としてすべてのプレイヤーに各自のボタンを押させることが考えられます。 ボタンが押されるたびに、Alexaは「こんにちは、プレイヤー[n]さん」と応答します。 この場合、Alexaには、プレイヤー1への挨拶を終えてから、プレイヤー2への挨拶を行わせます。

CustomInterfaceControllerインターフェースをサポートするスキルの場合、デフォルトの動作では、Alexaは音声を中断します。そのほかのスキルの場合、デフォルトでは、音声は中断されません。この動作は、次に説明するように変更できます。

音声の中断を制御する方法

Alexaに対するスキルの応答に含まれているoutputSpeechオブジェクトには、playBehaviorというオプションのアトリビュートが用意されています。このアトリビュートを使用して、新しい音声によりAlexaの現在の音声を中断するかどうかを制御できます。

playBehaviorは、次の3つの値のいずれかに設定できます。

  • ENQUEUE: Alexaの現在の音声を中断しません。代わりに、この音声をキューの最後に追加します。CustomInterfaceControllerインターフェースを使用しないすべてのスキルで、これがデフォルト値になります。
  • REPLACE_ALL: 現在の音声およびキューに追加された音声を置き換え、この音声の再生をすぐに開始します。CustomInterfaceControllerインターフェースを使用しているすべてのスキルで、これがデフォルト値になります。
  • REPLACE_ENQUEUED: Alexaの現在の音声を中断しません。キューのすべての音声をこの音声に置き換えます。

デフォルトの動作が既に目的の動作である場合は、応答でplayBehaviorを設定する必要はありません。

このセクションでは、playBehaviorアトリビュートを使用して、Alexaが現在話している音声を中断するかどうかを制御する応答の例を示します。

playBehaviorアトリビュートの設定は、次のSDKバージョンでサポートされています。

  • Node.js SDK v2.4.0以降
  • Java SDK v2.11.3以降
  • Python SDK v1.7.0以降

音声を中断する例

次の応答に含まれる音声では、Alexaが現在話している音声を中断し、現在キューにある音声を完全に置き換えます。

スキルがCustomInterfaceControllerインターフェースをサポートしている場合、CustomInterfaceControllerインターフェースをサポートするスキルではREPLACE_ALLがデフォルト設定であるため、playBehaviorアトリビュートを設定する必要はありません。

クリップボードにコピーされました。

{
    "outputSpeech": {
        "type": "SSML",
        "ssml": "<speak>この音声により、Alexaが現在話している音声を中断します。"/></speak>"
    },
    "shouldEndSession": false,
    "playBehavior": "REPLACE_ALL",
    "directives": [ ]
}

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Node.js(v2)を使用しています。

const Alexa = require('ask-sdk-core');
 
const MyIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && handlerInput.requestEnvelope.request.intent.name === 'MyIntent';
  },
  handle(handlerInput) {
      const speechText = "この音声により、Alexaが現在話している音声を中断します。";
      const playBehavior = "REPLACE_ALL";
 
      // 応答を組み立てます
      const response = handlerInput.responseBuilder
          .speak(speechText, playBehavior)
          .withShouldEndSession(false)
          .getResponse();
 
      // CloudWatchへの応答を記述します
      console.log("===応答=== "+ JSON.stringify(response));
 
      // 応答を返します
      return response;
   }
};
 

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Javaを使用しています。

package com.amazon.ask.buttongadget.handlers;
import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.Response;
import static com.amazon.ask.request.Predicates.intentName;
import java.util.Optional;
import com.amazon.ask.model.ui.PlayBehavior;

public class MyIntentHandler implements RequestHandler {

    @Override
    public boolean canHandle(HandlerInput handlerInput) {
        return handlerInput.matches(intentName("MyIntent"));
    }

    @Override
    public Optional<Response> handle(HandlerInput handlerInput) {
      // 応答を組み立てます。
      Optional<Response> response = handlerInput.getResponseBuilder()
        .withSpeech("この音声により、Alexaが現在話している  "
                     + "音声を中断します。",
                     PlayBehavior.REPLACE_ALL)
        .withShouldEndSession(false)
        .build();

      // CloudWatchへの応答を記述します。
      String responseLog = response.toString();
      responseLog = responseLog.replace("\n", " ").replace("\r", " ");
      System.out.println("===応答=== " + responseLog);

      // 応答を返します。
      return response;
    }
}

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Pythonを使用しています。

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_intent_name
from ask_sdk_core.handler_input import HandlerInput

from ask_sdk_model.ui import PlayBehavior
from ask_sdk_model import Response


class MyIntentHandler(AbstractRequestHandler):
    """ハローワールドインテント用ハンドラー"""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return is_intent_name("MyIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response

        # 応答を組み立てます
        speech_text = ("この音声により、Alexaが現在話している"
                       "音声を中断します。")
        play_behavior = PlayBehavior.REPLACE_ALL

        handler_input.response_builder.speak(
            speech=speech_text,
            play_behavior=play_behavior).set_should_end_session(
            False)

        # CloudWatchへの応答を記述します
        response = handler_input.response_builder.response
        print(response)

        # 応答を返します
        return response

音声をキューに追加する例

次の応答に含まれる音声では、Alexaが現在話している音声を中断しません。新しい音声はキューの最後に追加されます。

スキルがCustomInterfaceControllerインターフェースをサポートしていない場合、CustomInterfaceControllerインターフェースをサポートしていないスキルではENQUEUEがデフォルト設定であるため、playBehaviorアトリビュートを設定する必要はありません。

クリップボードにコピーされました。

{
    "outputSpeech": {
        "type": "SSML",
        "ssml": "<speak>この音声によってAlexaの音声は中断されません。この音声はキューに追加されます。"/></speak>"
    },
    "shouldEndSession": false,
    "playBehavior": "ENQUEUE",
    "directives": [ ]
}

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Node.js(v2)を使用しています。

const Alexa = require('ask-sdk-core');

const MyIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && handlerInput.requestEnvelope.request.intent.name === 'MyIntent';
  },
  handle(handlerInput) {
      const speechText = "この音声によってAlexaの音声は中断されません。 "
                          + "この音声はキューに追加されます。";
      const playBehavior = "ENQUEUE";

      // 応答を組み立てます
      const response = handlerInput.responseBuilder
          .speak(speechText, playBehavior)
          .withShouldEndSession(false)
          .getResponse();

      // CloudWatchへの応答を記述します
      console.log("===応答=== "+ JSON.stringify(response));

      // 応答を返します
      return response;
   }
};

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Javaを使用しています。

package com.amazon.ask.buttongadget.handlers;
import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.Response;
import static com.amazon.ask.request.Predicates.intentName;
import java.util.Optional;
import com.amazon.ask.model.ui.PlayBehavior;

public class MyIntentHandler implements RequestHandler {

    @Override
    public boolean canHandle(HandlerInput handlerInput) {
        return handlerInput.matches(intentName("MyIntent"));
    }

    @Override
    public Optional<Response> handle(HandlerInput handlerInput) {
      // 応答を組み立てます。
      Optional<Response> response = handlerInput.getResponseBuilder()
        .withSpeech("この音声によってAlexaの音声は中断されません。"
                     + "この音声はキューに追加されます。",
                     PlayBehavior.ENQUEUE)
        .withShouldEndSession(false)
        .build();

      // CloudWatchへの応答を記述します。
      String responseLog = response.toString();
      responseLog = responseLog.replace("\n", " ").replace("\r", " ");
      System.out.println("===応答=== " + responseLog);

      // 応答を返します。
      return response;
    }
}

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Pythonを使用しています。

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_intent_name
from ask_sdk_core.handler_input import HandlerInput

from ask_sdk_model.ui import PlayBehavior
from ask_sdk_model import Response


class MyIntentHandler(AbstractRequestHandler):
    """ハローワールドインテント用ハンドラー"""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return is_intent_name("MyIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response

        # 応答を組み立てます
        speech_text = ("この音声によってAlexaの音声は中断されません。"
                       "この音声はキューに追加されます。")
        play_behavior = PlayBehavior.ENQUEUE

        handler_input.response_builder.speak(
            speech=speech_text,
            play_behavior=play_behavior).set_should_end_session(
            False)

        # CloudWatchへの応答を記述します
        response = handler_input.response_builder.response
        print(response)

        # 応答を返します
        return response

キューに追加した音声を置き換える例

次の応答に含まれる音声では、Alexaが現在話している音声を中断しません。ただし、キューに追加された音声が新しい音声に置き換えられます。

クリップボードにコピーされました。

{
    "outputSpeech": {
        "type": "SSML",
        "ssml": "<speak>この音声により、Alexaが現在話している音声は中断されませんが、キューにある音声が置き換えられます。"/></speak>"
    },
    "shouldEndSession": false,
    "playBehavior": "REPLACE_ENQUEUED",
    "directives": [ ]
}

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Node.js(v2)を使用しています。

const Alexa = require('ask-sdk-core');

const MyIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && handlerInput.requestEnvelope.request.intent.name === 'MyIntent';
  },
  handle(handlerInput) {
      const speechText = "この音声により、Alexaが現在話している"
                          + "音声は中断されませんが"
                          + "キューにある音声が置き換えられます。";
      const playBehavior = "REPLACE_ENQUEUED";

      // 応答を組み立てます
      const response = handlerInput.responseBuilder
          .speak(speechText, playBehavior)
          .withShouldEndSession(false)
          .getResponse();

      // CloudWatchへの応答を記述します
      console.log("===応答=== "+ JSON.stringify(response));

      // 応答を返します
      return response;
   }
};

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Javaを使用しています。

package com.amazon.ask.buttongadget.handlers;
import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.Response;
import static com.amazon.ask.request.Predicates.intentName;
import java.util.Optional;
import com.amazon.ask.model.ui.PlayBehavior;

public class MyIntentHandler implements RequestHandler {

    @Override
    public boolean canHandle(HandlerInput handlerInput) {
        return handlerInput.matches(intentName("MyIntent"));
    }

    @Override
    public Optional<Response> handle(HandlerInput handlerInput) {
      // 応答を組み立てます。
      Optional<Response> response = handlerInput.getResponseBuilder()
        .withSpeech("この音声により、Alexaが現在話している"
                     + "音声は中断されませんが"
                     + "キューにある音声が置き換えられます。",
                     PlayBehavior.REPLACE_ENQUEUED)
        .withShouldEndSession(false)
        .build();

      // CloudWatchへの応答を記述します。
      String responseLog = response.toString();
      responseLog = responseLog.replace("\n", " ").replace("\r", " ");
      System.out.println("===応答=== " + responseLog);

      // 応答を返します。
      return response;
    }
}

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Pythonを使用しています。

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_intent_name
from ask_sdk_core.handler_input import HandlerInput

from ask_sdk_model.ui import PlayBehavior
from ask_sdk_model import Response


class MyIntentHandler(AbstractRequestHandler):
    """ハローワールドインテント用ハンドラー"""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return is_intent_name("MyIntent")(handler_input)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response

        # 応答を組み立てます
        speech_text = ("この音声により、Alexaが現在話している"
                       "音声は中断されませんが"
                       "キューにある音声が置き換えられます。")
        play_behavior = PlayBehavior.REPLACE_ENQUEUED

        handler_input.response_builder.speak(
            speech=speech_text,
            play_behavior=play_behavior).set_should_end_session(
            False)

        # CloudWatchへの応答を記述します
        response = handler_input.response_builder.response
        print(response)

        # 応答を返します
        return response