Сообщение "Подождите секунду" в 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, запустите его как часть тяжелой задачи хоста.