Сообщение "Подождите секунду" в Rivr VoiceXML для Java

Мне нужно воспроизвести сообщение "Подождите секунду..." сразу после взаимодействия. Мне это нужно, так как мне приходится выполнять некоторые трудоемкие задачи, прежде чем вернуться к пользователю. Поток приложения:

1) Воспроизвести сообщение приветствия (TTS) 2) Собрать голос от пользователя (взаимодействие с голосовой записью Rivr) 3) Воспроизвести сообщение TTS "подождите секунду", поскольку обработка голоса и связанный с ним бизнес-процесс занимает много времени (занимает несколько секунд) 4) [Время трудоемкая задача] 5) Сыграйте (TTS) результат процесса и попрощайтесь.

Все работает хорошо, но сообщение "Подождите секунду" воспроизводится сразу после трудоемких задач вместе с синтезированным результатом процесса (я имею в виду, что пользователь говорит и должен ждать), даже если в моем коде диалога оно помещено перед "Трудоемкая задача". По какой-то причине движок Rivr или VoiceXML буферизует оба сообщения (3 и 5), воспроизводя их вместе.

Как я могу заставить Rivr "очистить" шаг 3 и воспроизвести сообщение "Подождите секунду" сразу после записи, чтобы пользователь знал, что он должен подождать минуту?

2 ответа

Решение

Быстрое создание очереди в VoiceXML

В VoiceXML всякий раз, когда выполняется запрос, он фактически помещается в очередь. Интерпретатор VoiceXML будет сбрасывать очередь приглашения (т.е. воспроизводить ее) только при ожидании ввода пользователя или при выходе. Это поведение подробно описано в разделе " Очередь запросов и сбор ввода" документации VoiceXML W3C.

В вашем случае ваш запрос ставится в очередь перед выполнением длинной операции, и он воспроизводится только во время следующего взаимодействия. Это типичная ситуация, и существуют классические решения VoiceXML, имеющие аналог в Rivr.

Решение 1. Принудительно сбросить очередь подсказок, используя fetchaudio

В спецификациях VoiceXML указано, что очередь подсказок будет сброшена...

когда интерпретатор начинает выборку ресурса (такого как документ), для которого было указано fetchaudio. В этом случае запросы, поставленные в очередь до извлечения fetchaudio до завершения, и затем, если ресурс действительно должен быть извлечен (то есть он не является устаревшим в кэше), fetchaudio воспроизводится до тех пор, пока выборка не завершится.

Таким образом, чтобы убедиться, что подсказки будут воспроизведены, можно просто установить fetchaudio на <submit> элемент, используемый для получения результата длительной операции. Эффект таков: "Пожалуйста, подождите минутку". сообщение будет воспроизведено, а затем файл, указанный в fetchaudio, будет воспроизведен в цикле, пока сервер не вернет результат. Как правило, вы используете звук, указывающий, что что-то обрабатывается.

Если вы не хотите, чтобы что-либо было слышно, пока VoiceXML ожидает завершения операции, вы можете предоставить аудиофайл с тишиной в нем. Другой способ - указать файл, который не существует. Это работает под платформой VoiceXML. YMMV.

VoiceXML может выглядеть так:

<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml">
  <form id="form">
    <block>
      <prompt>Please wait a moment.</prompt>
      <submit fetchaudio="/audio/fetch.wav" method="post" next="/long-operation" />
    </block>
  </form>
</vxml>

С Rivr это:

context.getFetchConfiguration().getDocumentFetchConfiguration()
  .setFetchAudio("/audio/fetch.wav");

Message message = new Message("wait-message", 
  new SpeechSynthesis("Please wait a moment."));

DialogueUtils.doTurn(message, context);
performLongOperation();

Решение 2. Вставьте искусственное состояние ожидания

Другой прием для принудительного воспроизведения очереди подсказок - создание фиктивного взаимодействия с тайм-аутом, равным 0. Это заставляет интерпретатор воспроизводить сообщения. Мы должны быть осторожны, чтобы отключить вмешательство в запрос, иначе ввод DTMF может прервать сообщение. Вот пример фиктивного ввода:

<?xml version="1.0" encoding="UTF-8"?>
<vxml version="2.1" xmlns="http://www.w3.org/2001/vxml">
  <form id="form">

    <field name="dummy">
      <property name="timeout" value="0ms" />
      <grammar src="builtin:dtmf/digits" />
      <prompt>Please wait a moment.</prompt>
      <filled>
        <goto nextitem="submit" />
      </filled>
      <noinput>
        <goto nextitem="submit" />
      </noinput>
      <nomatch>
        <goto nextitem="submit" />
      </nomatch>
    </field>

    <block name="submit">
      <submit fetchaudio="audio/fetch.wav" method="post" next="/long-operation" />
    </block>

  </form>
</vxml>

А вот эквивалент Rivr:

DtmfRecognition dummyRecognition = new DtmfRecognition(new GrammarReference("builtin:dtmf/digits"));

SpeechSynthesis message = new SpeechSynthesis("Please wait a moment.");

Interaction interaction = OutputTurns.interaction("wait-message")
                .addPrompt(dummyRecognition, message).build();

DialogueUtils.doTurn(interaction, context);
performLongOperation();

И если вы хотите повторно использовать этот шаблон в своем приложении, вы можете сделать функцию:

private void forcePlayMessage(VoiceXmlDialogueContext context,
                              String messageName,
                              AudioItem... audioItems)
                throws Timeout, InterruptedException {
    DtmfRecognition dummyRecognition = new DtmfRecognition(new GrammarReference("builtin:dtmf/digits"));
    Interaction interaction = OutputTurns.interaction(messageName)
            .addPrompt(dummyRecognition, audioItems).build();
    DialogueUtils.doTurn(interaction, context);
}

Если операция очень длинная, может быть целесообразно использовать Java FutureTask класс для обработки вашего запроса в фоновом режиме, позволяющий диалоговому окну отправлять сообщения вызывающей стороне каждые X секунд вместо блокировки на performLongOperation()

Некоторые платформы ожидают ввода или ввода, чтобы начать говорить. Если ваша платформа поддерживает атрибут fetchaudio, запустите его как часть тяжелой задачи хоста.

Другие вопросы по тегам