基于VoiceXML技术的可视化IVR系统设计和实现(三)
上海易谷网络科技有限公司 查玮 2009/12/29
在系统分析和系统总体设计之后,就进入了系统实现阶段。该阶段主要是对IVR系统业务编辑工具和执行引擎部分进行实现。
从图4.4所示结构中,通过主窗体可以访问其它窗体操作,同时控制窗体与类模块的信息交互。系统中的各个窗口的实现均是基于基础类包的。下面详细介绍IVR系统流程工具各个部分的实现。其实现工具的内容详见文献[31]。
主程序是IVR系统流程定义工具的主体,它包括各个窗口的定义、流程类的定义、节点类定义等。主程序通过主窗体类定义将其它各个类窗体组织在一起,同时负责各子窗体之间的信息交互。主窗体类则定义了流程间的组织结构,它通过用户界面操作协助用户完成流程制作,同时生成含有VoiceXML标签的Web页面交给执行引擎进行解释执行。
主窗体主要负责各个窗体和类模块之间的信息交互和访问控制。图4.2描述IVR系统业务流程定义工具的主窗体界面。分为工具箱窗体、菜单窗体、流程编辑(画布)窗体、属性窗体,同时包括流程节点的访问控制。
图4.2 IVR系统流程定义工具主窗体
工具箱窗体:工具箱窗体提供系统支持节点类型控件的选择,用户通过拖拽方式添加节点以制作流程。工具箱窗体类主要包括工具箱窗体的事件响应和主窗体交互部分,提供每种实现方法。
菜单窗体:菜单窗体是提供关于整个系统流程的打开、编辑等操作。
属性设置窗体:属性窗体为每一类节点提供属性设置功能,其中包括属性窗体操作、与主窗体信息交互两大类,提供各个节点所涉及到的每种属性窗体的实现方法。
流程编辑(画布)窗体:此窗体类提供了制作流程的画布操作。在此窗口定义了一个画布控件;流程编辑窗体接收画布对象的事件,提交给主窗体,同时通过与主窗体的信息交互控制在画布上确保正确制作流程。
主程序除了上述4种主要的模块定义之外,还有一些窗体类和类模块定义,主要负责各种属性的设置和操作:同时为使流程制作更加人性化,主程序增加了一些通用编辑功能。
以上为主程序的设计及其部分实现。在实现中通过引用窗体控件和画布窗体类定义,集成了对画布控件和节点控件的访问操作。
4.2 IVR系统执行引擎的实现
IVR系统执行引擎是整个IVR系统的核心系统,它负责对之前由IVR系统流程定义工具生成的中间文件(含有VoiceXML标签的Web页面)解释和驱动。本文设计的IVR系统是基于VoiceXML技术,以开源OpenVXI项目为基础,设计并实现的IVR系统执行引擎部分。
OpenVXI[32] 是一种简便的开源库,用来解释VoiceXML对话标记语言(dialog markup language)。为了避免其它私有的标准,它严格支持VoiceXML
2.0 草案(现在已经支持部分3.0的标准),同时OpenVXI是一个跨平台的开发系统。
OpenVXI本身只是VoiceXML平台的一个组件[32],它只是提供了简单的语音识别、语音提示和TTS(text-to-speech)功能。而对于电话功能,由于语音卡的种类繁多,同时VoIP(Voice
over IP)技术的快速发展,就需要使用者自己提供实际的组件和函数进行整合。既便如此,OpenVXI还是提供一个强大的基本框架让使用者构建自己的语音平台。
4.4.1 OpenVXI的系统架构
根据图2.3描述的VoiceXML平台的基本体系结构分析,OpenVXI符合基本架构,具体的系统架构图如图4.3所示。整个平台执行VoiceXML页面,并提供与电话网络连接的服务,平台总共分4个部分:
1.主进程、操作管理和维护系统:一个收集系统管理和错误报告的工具。这个核心组件通过创建线程的方式来唤醒VoiceXML浏览器。
2.OpenVXI:负责解释VoiceXML标记语言和语音平台返回的呼叫标志信息(通过返回相应的事件信息)。
3.OpenSpeech Browser PIK:提供了为系统运行所必要的高层次(high-level)服务,包括识别引擎、语音引导引擎、Internet
fetch库(提供通过URL对web服务器访问的库)、ECMA Script[32]引擎。OpenVXI通过系统提供的函数接口来访问这些组件,这些接口不需要定义和实现各种机制来满足与底层电话系统软件系统之间的通讯,而是通过使用支持Client/Server模式的TCP/IP协议来实现。
4.Telephony and base services:需要能接收到电话的基本操作系统服务和电话服务。
图4.3 OpenVXI系统架构图
4.4.2 OpenSpeech Browser PIK组件结构
图4.4描述了OpenSpeech Browser PIK 的架构和组件构成,包括为完成语音识别和TTS功能整合的产品SpeechWorks。
所有的组件都被设计成很容易的去访问。这个语音浏览器(Speech Browser)包括:
1.VXI:解析所有的VoiceXML标记,并且担当程序中的主控作用。VXI实现了VoiceXML 1.0中所有必需(mandatory)的部分和大部分的可选功能。
2.XML Parser Interface:提供对XML DOM解析器的访问,现在的实现方式是通过直接调用开源的Apache Xerces
SAX and DOM parse解析接口。
3.Internet Interface:通过http://和file://的方式访问应用文档(即URL的方式访问Web页面),同时也支持POST的方式给应用服务器返回数据。这方面的实现是整合了开源W3C
Libwww开发库。
4.ECMAScript(JavaScript) Interface :提供了对ECMAScript执行服务的访问。相关的实现整合了Mozilla
SpiderMonkey开源引擎。
5.Logging Interface:用来报告系统级别的错误、事件和诊断信息。它是将日志存储成日志文件,并且可以选择进行标准的输出。
核心浏览器中与语音平台相关的API主要包括:
1.Recognizer Interface:提供语法管理和由VoiceXML指定的识别服务(例如:收取DTMF码),包括动态语法创建和语法构建。它通过Telephony
Service来获取呼叫信息,并且已经在OpenSpeech Browser中整合。
2.Prompting Interface:提供完整的放音服务,包括播放可变语音。它必须处理语音文件并且提供语音服务。OpenSpeech
Browser PIK已经整合了支持几种语言的TTS。
3.Telephony Interface:提供呼叫控制服务,包括发送语音平台的时间、转接和挂断电话。OpenSpeech Browser
PIK已经实现了与底层的语音平台交互,并抽象了API来提供呼叫控制服务。
4.Object Interface:提供了对对象的访问。通过对象元素,平台可以访问定义的那些对VoiceXML语音的扩展。对象可以很容易的被定义成适合语音平台需要的呼叫控制扩展、CTI系统的弹屏显示或者其它一些需求。
图4.4 OpenSpeech Browser PIK 组件构成图
通过对OpenVXI的描述,可以看出:模块化和分层次的设计使得在平台里的各个组件之间即相对独立,又相互联系、互相协作来完成整个平台的功能。使用者可以通过实现平台提供的各种接口来实现对基于各种硬件或者软件的语音系统的整合。本文设计的IVR系统所涉及到的是模拟语音卡,所以对与录音、放音、取键都由语音卡所提供的API来完成即可。
4.4.3 接口实现(取键、录音、放音、转接)
OpenSpeech Browser PIK自身就是支持标准的VoiceXML 2.0的标准,同时对VoiceXML的解析能力比较强大,又同时整合了Apache的XML解析器、W3C的LIBWWW进行Web访问和Mozilla
Spider Monkey作为ECMA Script的执行器,本文主要是通过实现相应的语音平台接口来实现IVR系统的执行引擎。没有对VoiceXML解析功能做过多的修改。
Recognizer Interface(识别接口)的实现
对应Recognizer的接口,OpenVXI分别针对收取用户按键(DTMF码)和语音识别(speech recognize)的接口,但是由于现在语音识别的技术并不是很成熟,特别是对中文的识别率不是很高,本文设计的IVR系统就没有涉及到该功能,只是留下接口等待以后实现。需要实现的具体接口函数有收取用户按键和录音。
收键接口,函数体描述如下:
VXIpromptResult Recognize (struct VXIrecInterface* pThis,
const VXIMap* properties,
VXIrecRecognitionResult** recogResult)
图4.5描述了实现该接口的流程图。
图4.5 使用Recognize接口实现收DTMF码流程图
1)获取连接实例,其数据是从语音卡检测到的信令,发送给语音平台。通过GetImplementaionName来获得实例名称,进入下一步;
2)使用BeginSession来创建session,并且通过LoadGrammarURI来装载语法。这时候开始启动收键,进入下一步;
3)启动计时器,等待事件触发;
4)如果接收到SC_EVENT_DISCCONET事件,表示用户主动放弃,返回REC_FAILURE,调用EndSession,流程结束;如果接收到SC_EVENT_TIMEOUT事件,表示用户在计时器的时间内没有输入,返回REC_NOINPUT,调用EndSession,流程结束;如果接收到SC_EVENT_DTMF_RECEIVED事件,表示用户输入完毕,进入下一步;
5)检查语法的符合性,通过检查是否满足在.gram文件里设置的正则表达式来判断,如果符合转6,不符合转7;
6)符合语法,返回REC_SUCESS,调用EndSession,流程结束;
7)不符合语法,返回REC_NOMATCH,调用EndSession,流程结束。
录音接口,接口函数体描述如下:
VXIrecResult Record (struct VXIrecInterface* pThis,
const VXIMap* propertites,
VXIrecRecordResult** recordResult)
图4.6描述了实现该接口的流程图。
图4.6使用Record接口实现录音流程图
1)获取连接实例,其数据是从语音卡检测到的信令,发送给语音平台。通过GetImplementaionName来获得实例名称,进入下一步;
2)创建录音文件名,进入下一步;
3) 使用BeginSession来创建session,并且通过LoadGrammarURI来装载语法。这时候开始启动录音功能,进入下一步;
4)启动计时器,等待事件触发;
5)如果接收到SC_EVENT_DISCCONET事件,表示用户主动放弃,转到步骤7;如果接收到SC_EVENT_TIMEOUT事件,表示用户在计时器的时间内没有输入,返回REC_NOINPUT,调用EndSession,流程结束;如果接收到SC_EVENT_RECORD_RECEIVED事件,表示用户录音完毕,进入下一步;
6)返回REC_SUCCESS,进入下一步;
7)检查录音文件是否有数据。如果录音文件没有数据不存在数据,表示录音不成功,返回REC_FAILURE,调用EndSession,流程结束;如果录音文件有数据,表示录音成功,返回成功,调用EndSession,流程结束。
Prompting Interface(放音接口)的实现
对于放音接口,所需要关注的是3个函数的实现:Queue()接口、Play()接口和Wait()接口。
Queue接口仅仅是将所要播放或者重复播放的语音文件放入队列中,并不担当放音的功能, Play()接口才是启动播放动作的。这个调用会一直阻塞直到放音数据返回以便于调用者可以确认是否需要重播。接口函数体描述如下:
VXIpromptResult Queue (struct VXIproptInterface* pThis,
const VXIchar* type,
const VXIchar* content,
const VXIchar* text,
const VXIMap* properties)
在实现过程中,本文设计的IVR系统只是涉及到语音文件的播放,所以只是需要通过调用语音卡API将语音文件放入播放队列即可,而需要重复播放的语音文件,只要重复放入到语音队列当中便可实现。
Play接口是完成放音动作的接口。实现非常简单,只需要调用语音卡放音API去播放存在播放队列里的语音文件。接口函数体描述如下:
VXIpromptResult Queue (struct VXIproptInterface* pThis)
Wait接口是等待所有的放音文件都结束,去捕获放音时间结束。接口函数体描述如下:
VXIpromptResult Wait (struct VXIproptInterface* pThis
VXIpromptResult* playResutl)
图4.7描述了这三个接口实现流程图。
图4.7 Queue、Play、Wait接口实现流程图
Queue接口实现如下:
1)获取连接实例,其数据是从语音卡检测到的信令,发送给语音平台,进入下一步;
2)判断语音文件是否合法,如果合法转3,不合法返回PROMPT_FAILURE,流程结束;
3)将要播放的文件名放入播放队列中等待播放,返回PROMPT_SUCCESS,流程结束。
Play接口实现如下:
1)获取连接实例,其数据是从语音卡检测到的信令,发送给语音平台,进入下一步;
2)判断播放队列是否为空,如果为空返回PROMPT_SUCCESS,流程结束;如果不为空,转3;
3)调用语音卡放音API实现放音功能,转2。
Wait接口实现如下:
1)获取连接实例,其数据是从语音卡检测到的信令,发送给语音平台,进入下一步;
2)启动计时器,等待事件触发;
3)如果收到SC_EVENT_DISCONNECT事件,表示话路断开,返回PROMPT_FAILURE,流程结束;如果收到SC_EVENT_PROMPT_END,返回PROMPT_SUCCESS,流程结束。
Telephony Interface(转接接口)的实现
对于电话接口,需要实现的方法有GetStatus、Disconnect、TransferBlind,而TransferBridge指的是通过桥接的方式去转接。首先,他需要平台的支持,其次还要进行大量的配置,同时占有很多的资源,非常的不实用。对于IVR系统来说,不需要这么复杂的操作。对于大型的呼叫中心,IVR系统只是前置于整个呼叫平台,更多的话路操作还需要交给CTI系统去完成。
下面给出每个接口实现的流程图,如图4.8所示。
图4.8 GetStatus、Disconnect、TransferBlind接口流程图
GetStatus函数体描述如下:
VXItelResult GetStatus(struct VXItelInterface* pThis,
VXItelStatus* status)
接口实现如下:
1)获取连接实例,其数据是从语音卡检测到的信令,发送给语音平台,进入下一步;
2)调用语音卡API去查看通道状态,进入下一步;
3)将获得状态返回,如果通道中有电话返回VXI_STATUS_ACTIVE;如果通道是空闲状态则返回VXI_STATUS_INACTIVE流程结束。
Disconnect函数体描述如下
VXItelResult Disconnect(struct VXItelInterface* pThis)
接口实现如下:
1)获取连接实例,其数据是从语音卡检测到的信令,发送给语音平台,进入下一步;
2)调用语音卡API去检查语音连接是否存在,如果存在,则进入下一步;如果不存在,转4;
3)调用语音卡API去挂断电话,进入下一步;
4) 调用语音卡API释放所有资源,流程结束。
TransferBlind函数体描述如下
VXItelResult TransferBlind (struct VXItelInterface* pThis,
const VXIMap* properties,
const VXIChar* transferDestination,
VXIMap** resp)
接口实现如下:
1)获取连接实例,其数据是从语音卡检测到的信令,发送给语音平台,进入下一步;
2)调用语音卡API去检查语音连接是否存在,如果存在,则进入下一步;如果不存在,转4;
3)调用语音卡API去转接电话(因为是采用的是“盲转”方式转接,IVR系统只要将电话转移到话机上即可,不需要管理转接后的状态),返回成功,流程结束;
4)返回失败,流程结束。
4.3本章小结
本章在基于整个IVR系统的详细设计基础上,基于MFC技术和OpenVXI的开源项目,实现了IVR系统可视化的过程定义工具和IVR系统的执行引擎。
基于VoiceXML技术可视化IVR设计和实现(四)
作者独家提供CTI论坛稿件,其它媒体谢绝转载
CTI论坛报道
基于VoiceXML的可视化IVR系统设计和实现(一) 2009-09-22 |
上海易谷与Genesys达成大中华区长期合作伙伴关系 2009-04-17 |
联络中心与3G应用 2009-04-09 |