"Wait a second" Java 的 Rivr VoiceXML 消息

"Wait a second" message in Rivr VoiceXML for Java

我需要在互动后立即播放“请稍等……”消息。我需要这个,因为在返回给用户之前我必须执行一些耗时的任务。应用流程是:

1) 播放欢迎信息 (TTS) 2)收集用户语音(Rivr语音记录交互) 3) Play "wait a second" TTS message 因为处理语音和相关业务流程比较耗时(需要几秒) 4)【耗时任务】 5) 播放(TTS) 过程结果,说再见。

一切正常,但 "Wait a second" 消息会在耗时的任务和过程的合成结果一起播放(我的意思是,用户说话并且必须等待),即使在我的对话框中也是如此它放在 "Time Consuming task" 之前的代码。出于某种原因,Rivr 或 VoiceXML 引擎正在缓冲两条消息(3 和 5)一起播放。

我怎样才能使 Rivr "flush" 步骤 3 并在录制交互后立即播放 "Wait a second" 消息,以便用户知道他应该稍等片刻?

有些平台会等到输入或 a 才开始说话。如果您的平台支持 fetchaudio 属性,请将其作为繁重的主机任务的一部分进行播放。

VoiceXML 提示排队

在 VoiceXML 中,无论何时执行提示,实际上都将其放入队列中。只有在等待用户输入或退出时,VoiceXML 解释器才会刷新提示队列(即播放它)。 VoiceXML W3C 文档的 Prompt Queueing and Input Collection 部分详细描述了此行为。

在你的情况下,你的提示在执行长操作之前排队,并且仅在下一次交互期间播放。这是一种典型情况,在 Rivr 中有 classical VoiceXML 解决方案。

解决方案 1:使用 fetchaudio

强制刷新提示队列

VoiceXML 规范声明提示队列将被刷新...

when the interpreter begins fetching a resource (such as a document) for which fetchaudio was specified. In this case the prompts queued before the fetchaudio are played to completion, and then, if the resource actually needs to be fetched (i.e. it is not unexpired in the cache), the fetchaudio is played until the fetch completes.

因此,为了确保播放提示,可以简单地在用于获取长操作结果的 <submit> 元素上设置一个 fetchaudio。效果是播放"Please wait a moment."消息,然后循环播放fetchaudio中指定的文件,直到服务器returns结果。通常,您会使用提示正在处理某些内容的声音。

如果您不想在 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 class 在后台处理你的请求可能是明智的,允许你对话发送消息给你的调用者每 X 秒而不是阻塞 performLongOperation()