VoiceXML 中的提示排队
在 VoiceXML 中,每当执行提示时,它实际上都放在队列中。VoiceXML 解释器仅在等待用户输入或退出时才会刷新提示队列(即播放它)。VoiceXML W3C 文档的Prompt Queuing and Input Collection部分详细描述了此行为。
在您的情况下,您的提示在进行长时间操作之前是排队的,并且仅在下一次交互期间播放。这是一种典型的情况,在 Rivr 中有经典的 VoiceXML 解决方案具有它们的等价物。
解决方案 1:使用强制刷新提示队列fetchaudio
VoiceXML 规范声明提示队列将被刷新...
当解释器开始获取指定了 fetchaudio 的资源(例如文档)时。在这种情况下,将在 fetchaudio 之前排队的提示播放到完成,然后,如果确实需要获取资源(即它在缓存中不是未过期的),则播放 fetchaudio 直到获取完成。
因此,为了确保播放提示,只需在<submit>
用于获取长操作结果的元素上设置一个 fetchaudio 即可。大意是“请稍等”。消息将被播放,然后,在 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);
}
如果操作很长,最好使用 JavaFutureTask
类在后台处理您的请求,允许您对话每隔 X 秒向您的调用者发送消息,而不是阻塞performLongOperation()