xml|语音
随着XML在工业界被广泛的采用,在不同的领域不同的行业,各自派生出了一些在一些特定领域适用的XML子集。在这一系列文章中中将要主要介绍的VoiceXML就是其中之一。它和WML的地位非常相似。WML是应用于无线上网中的特种语言,VoiceXML是应用于语音浏览的特种语言。无线上网(WAP)和语音浏览是现在网络发展的两大热点,XML在它们身上都找到了用武之地。
整篇文章将比较介绍XML在语音中应用的一些重要环节。除了VoiceXML之外,还会介绍一些XML在语音技术中应用的其他方面。在这一部分中主要是背景知识的介绍。
语音浏览器,VoiceXML诞生的温床
电话的出现是为了方便通信。电脑的出现是为了计算。进入“后PC时代之”后,“电脑”同“网络”这两个词越来越靠近。现在,很多买电脑的人得以达目的就是为了上网。网络成了信息交换共享的一条捷径,人们纷纷“中弹落马”。以至于通过电话上网也提上了日程。越是简单通用的,就越是受到最广泛普通消费者的青睐。越是受到最广泛普通消费者的青睐的就越是被工业界大力推崇。
有一点是毫无疑问的,那就是现在的电话比电脑要多。随便走在一个城市的街道上,您会很轻易地发现公用电话。但我现在还不敢想象在大街上随处可见的“公用电脑亭”,五角钱三分钟上网。不光是在城市,电话并不是什么稀罕玩艺,而要买一台电脑,不少人还是要咬一咬牙。而且,电话比电脑的这种优势还在不断扩大。个人移动电话的发展正处于前所未有的高峰时期,相信将来的单人对单机并不是什么神话。
另外,电话远比电脑具有亲和力。我相信许多人对电脑的操作都具有一定工具心理。不是怕原有的界面被改动后无法还原,就是怕不知道应该在哪里去修改想要的设置。这对已经是比较友好的视窗界面就是如此了,更不要去说什么满屏黑的Unix之类。而电话就不一样了,只有非常有限的几个键,遇到麻烦把话筒一挂再重新拿起就是了。而且关键的是电话听筒里说的是“人话”。
所以我们说通过电话访问网络是非常有前途的。再加上现在还有一种发展趋势就是把多种界面访问形式,比如是语音、图像和触觉等,一起结合在电话上成为名副其实的PDA(个人数字助理),我们不得不在这里再一次对电话的发展前途夸耀一番。人们将可以在任何时间任何地点通过随手可得的“电话”,通过简单易懂的操作方法连接到网络。
语音浏览是网络的一种全新浏览方式
对于一家小有规模的公司来说,拥有一台电话总机并不是一件什么新鲜事。电话用户可以通过数字按键联络到不同的员工。还有一种普遍的电话总机功能是用或通过数字按键游离层状目录结构来获取信息。而我们要在这里探讨的语音浏览和这里的形式上有相似之处。用户主要是通过语音来发送自己的信息。我们还可以把服务的对象扩大到提供内容服务的网站上去。使用的联络网络也不一定要是专用电话网,还可以是因特网。
什么是语音浏览器
语音浏览器是以语音输入为主要输入渠道,其他形式为辅助输入渠道,翻译解释执行语音标记语言,并能产生语音输出的设备。
上面这段味如嚼蜡的解释源于W3C。就像要用一句话把人描述出来一样,它颇费周折地概述了一些空泛的共性。双腿直立行走,用上肢劳动的哺乳类动物云云。语音浏览器想要实现的是通过最具有亲和力的交流方式,把来自具有最丰富资源的网络上的信息通过声音提供给用户。
明眼人一看便知,设计完成一个语音浏览器还有语音识别、语音理解和语音合成上的技术壁垒。当用户要通过语音发出命令时,语音浏览器要知道用户在说些什么?比较简单的是命令式语音识别。系统要求你只能说“蚊子”或是“苍蝇”。其他的都认为是非法输入。复杂的要牵涉到对一段语音的理解。比如说当用户说“今天星期几?”或是“今天是一个星期中的第几天?”时要知道是同一回事。这样的话,用户就方便了不少。而这就需要语音理解技术来处理了。语音合成也是必不可少的。当你要把浏览到的信息传送给用户时时通过语音。这可以是一段事先录好的自然人语音,也可以是通过文字到语音的TTS语音合成系统。可以非常明确的说,上面要用到的技术都是需要大量的技术积累才能实现的,绝不是一日之功。对于绝大多数设计实现语音浏览器的开发上来说都会很自然的去采用一些在语音方面颇有底蕴的公司所提供的技术产品支持。主要的精力都在集成之上。
语音浏览器的主要特点是非常鲜明的。在许许多多普通的场合之下,通过近似自然对话的方式来发布命令,通过一种不同于HTML两维的浏览方式,时间上线性地收取信息。只是非常有诱惑力的。有很多情况之下,根本就不允许用眼睛来监督,如在开车的时候。用户只有通过非视觉的方式来控制。
网页浏览器提供了在不同叶面之间跳转的方法,语音浏览器也可以从一段对话跳转到另一段。网页浏览器提供了添取、发送表单的方法,语音浏览器页可以设定用户的一段语音为一次有目的的输入。事实上语音浏览器和HTML叶面浏览器有非常相似之处。用GRE类比题的方式来表示就是:语音浏览器:VoiceXML::HTML浏览器:HTML。 在这一部分中让我们来看一看语音方面现有的XML标准化进程。
W3C在语音浏览上所作的工作
作为一个权威的标准化组织,W3C和早就看上了语音浏览(Voice Browser)。W3C于1998年的10月份成立了一个名为“语音浏览器”的工作站。大家在这里可以联想一下,XML是最早于1996年底被提上议案的。工作站的目标非常明确,制定语音浏览方面的标准,迎接即将来临的语音浏览热潮。工作站的工作主要基于以下一些方面,我们还要在后面对其中的部分工作放大研究。
语音标识语言对于对话的需求说明
简单的说,为了语音浏览器能够方便的结合不同的输入输出形式,和谐的同用户交互“对话”,需要对用来表示对话数据的标识语言进行限制。可以想象,用于表现平面网页的HTML就不能胜任语音浏览器。不但是因为它繁杂混乱,而且它的二维性质也使得它不能表示交互式的对话。
标识语言当中对可重复使用对话的要求说明
好比高级程序语言编程一样,有一些小的模块会是被经常重复使用的。这些小的模块被设计成为函数或是过程,每当要用的时候就调用一次。在语音浏览器使用的标识语言当中需要有这样的类似机制,用来表示那些经常会被重复使用的部分。这一点可以在后面的文章中具体的体会到。经常会被重复使用的部分包括简单的确认、收集电话号码、日期、金额、信用卡信息和地址的信息等。
标识语言当中语音识别语法层表示的需求说明
前面我们已经提到过语音浏览器的实现和语音技术的应用密不可分。为了实现语音数据的识别输入,语音浏览器会用到现成的语音识别平台。不同的语音识别方法有着不同的平台要求。如果只是独立人的小词汇量识别,我们还可能不需花费太多的时间在识别之上。但只要要求一旦稍微放松一点,语音识别的难度一下子就会变得很高。对于非独立人的小词汇量、带语法结构的语音识别,就需要在语音识别平台的接口上对带识别的语音输入语法结构做出具体的描述。而这种情况是现在一般的语音浏览器所遇到的最普遍情况。W3C在这里定义了一套这样的语法标识表示。
标识语言中对自然语言处理的需求说明
这其实就是前面我们已经提到的语音理解方面的问题。这同上面的一点一样,和语音技术密切相关。定义了对于自然语言理解在语音浏览器实现当中的标识表示需求说明。
标识语言中对语音合成的需求说明
为了实现语音的输出,人们必须要用到语音合成。简单的把事先录制好的声音拼凑起来回放也可以视为语音合成中的一种。而实际当中用的更多的还是TTS(Text To Speech)。怎样表示要合成的语句呢?不同的语音平台有着不同的方法。W3C正是在抽象出这些特征的共性。比如说一句话中的某一个词要重读,某一句话是男声发音。通过标识语言,我们就可以统一的描述一段待合成的文字。
下面我们将对一些W3C的部分工作放大研究。
语音合成
前面我们已经谈到了一些语音合成的问题。当语音浏览器需要将输出的结果由字符变成自然语音时,我们必须时间把语音读本的一些语言特征事先标示出来提供给语音合成器。语音浏览器中这是用XML语言来实现的。
所示文字数据从语音浏览器的前段处理得到后,被一种转换机制变成标识语言。这里的转换机制其实就是代码的开销。符合语音合成器的标识语言被送入特定的语音合成器当中,最终用户就可以听到自然语音了。
请注意,语音合成方式并不是唯一的。还有简单的方法是把文字数据非拆成一些经常会被重复使用的短语段,然后通过匹配的方法读取事先录制好的语音段,拼合成为一段自然语音。但这种方法的缺点解释非常明显的。首先是对文字数据的范围限制很大,一定实效词汇量的,并且有着固定的句式。其次人工录制的开销较大,并且随着文字数据范围的扩大,开销成倍的扩大。最后,这种方法合成的自然语音并不自然。
由于不同的公司有着不同的语音应用平台,所以在从前语音合成的标识语言并不统一。但好在的是由于语音合成技术本身存在的一致性,这些不同的标识语言所标示的语音特征大同小异。差别只是在一些标识的表示方法不同之上。
下面让我们来看一下几种主要的语音合成标识语言。
1 JSML(Java Speech Markup Language)
JSML顾名思义是用来将文字输入Java语音API合成器之用的标识语言。JSML包含了被合成文字的自然语音属性。而且它使用的是Unicode字符集,所以它适用于几乎所有的语言。
例子:
<?XML version="1.0" encoding="gb2312 "?>
<JSML>
<PARA> 你一共欠了我
<EMP>
<SAYAS CLASS="number">10000元</SAYAS>
</EMP>
</PARA>
<PARA>
<EMP>
<SAYAS CLASS="literal">太夸张了</SAYAS>
</EMP>
</PARA>
</JSML>
我们不会在这里详细的介绍JSML的标识的含义,因为我们将比较详细的介绍W3C的标准。我们可以从例子当中看到这是一段对话。<PARA>表示的是这是一段话。<EMP>表示重读。<EMP>的属性LEVEL还可以设定重读的分量,上面的例子当中并没有体现。<SAYAS>用来标记文字读出的方式。具体的方式是由它的特定属性设定的。比如上面的CLASS="number"表示按照数字大方式读。CLASS="literal"表示按照分离的方式读,也就是“太夸张了”。
2 SABLE
同上面一样我们也通过一个例子来了解它。
例子:
<DIV TYPE="paragraph">这就是去年
<EMPH>你</EMPH>
为我
<PITCH BASE="high" RANGE="large">
<RATE SPEED="-20%">点的歌</RATE>
</PITCH>
</DIV>
<AUDIO SRC="easycome_easygo.wav"/>
从大体上说SABLE和JSML非常相似。我只挑出比较特别的几个标识来解释一下。<PITCH>是对音调的要求。<RATE>是对语速的要求。<AUDIO>表明的是一段以录制好的语音段。
支持SABLE典型的有Festival语音合成系统。Festival是由英国Edinburgh大学语音技术研究中心(Center for Speech Technology Research)开发的多语种语音合成系统。对于从事语音研究的人来说,CSTR值得好好钻研。因为它不但有像Festival这样的成熟语音合成系统,还有一套开放源代码的语音识别平台软件包。
下面那就让我们来看一看W3C在语音合成标识语言上的标准。
和前面所提到的两种语言一样,W3C把它所规定的标识和属性分为了三类。一类是表示语言组织结构的表识,一类是表示语音特征上的表识,还有一类是对上面两类的补充,一般是为可能的扩充留有余地。
我们将以表格的形式来介绍这些标识和属性。
下面是第一层的标识:
文件结构 文本处理 发音音素 |
speak | 根节点 |
xml:lang | 根节点中表示语种的属性 | |
paragraph和sentence | 表示段落和局字的结构节点 | |
sayas | 定义文本的预处理格式,属性为:type | |
phoneme | 定义文本的发音方法,属性为:ph | |
发音韵律 | voice | 表示不同发音方法的节点 |
emphasis | 重音发音节点 | |
break | 表示暂顿的空节点 | |
prosody | 控制语音语素语调的节点 | |
其他 | audio | 表示加入预先录好语音段的节点 |
mark | 表示异步合成当中的一个标记 |
针对一些结构选项复杂的节点,我们再来仔细的看一看:
"sayas" 节点type属性可选项值:
发音 | acronym | 首字母缩写的合成词。按单个字母分别读出。 |
sub("sayas" 节点的属性) | 值为节点值的替换。在后面列出的DTD当中并没有声明。 | |
数字 | number | 值为节点值的数字形式。可选的值有ordinal、digits等: |
时间、量度 | date | 日期控制格式 |
time | 时刻控制格式 | |
duration | 时间间隔长度设定 | |
currency | 金额控制格式 | |
measure | 表示文本为量度 | |
地址、标识 | name | 人或是公司的名称 |
net | 网络地址。可以是电子邮件或是网址 | |
address | 邮政地址 |
"voice" 节点属性值:
gender | 发声者性别 |
age: | 发声者年龄范围 |
variant | 发声者不同的发声。(可选,针对于平台的变量) |
name | 针对于平台的发声标识。(可以看作是发声者的名字) |
"break" 节点属性值:
size | 对中断边沿大小的设定 |
time | 对中断时间长度量化设定 |
"prosody" 属性属性值:
pitch | 基音调设定 |
contour | 基音调轮廓设定 |
range | 基音变化范围设定 |
rate | 语速 |
duration | 发音时间长度设定 |
volume | 发音银两大小设定 |
下面是W3C 设定的语音合成标识语言的DTD:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Speech Synthesis Markup Language v0.5 20000504 -->
<!ENTITY % allowed-within-sentence " #PCDATA | sayas | phoneme |voice | emphasis | break | prosody | audio | value | mark " >
<!ENTITY % structure "paragraph | p | sentence | s">
<!ENTITY % duration "CDATA">
<!ENTITY % integer "CDATA" >
<!ENTITY % uri "CDATA" >
<!ENTITY % phoneme-string "CDATA" >
<!ENTITY % phoneme-alphabet "CDATA" >
<!-- Definitions of the structural elements. -->
<!-- Currently, these elements support only the xml:lang attribute -->
<!ELEMENT speak (%allowed-within-sentence; | %structure;)*>
<!ELEMENT paragraph (%allowed-within-sentence; | sentence | s)*>
<!ELEMENT sentence (%allowed-within-sentence;)*>
<!-- The flexible container elements can occur within paragraph -->
<!-- and sentence but may also contain these structural elements. -->
<!ENTITY % voice-name "CDATA">
<!ELEMENT voice (%allowed-within-sentence; | %structure;)*>
<!ATTLIST voice gender (male|female|neutral) #IMPLIED
age (%integer;|child|teenager|adult|elder) #IMPLIED
variant (%integer;|different) #IMPLIED
name (%voice-name;|default) #IMPLIED >
<!ELEMENT prosody (%allowed-within-sentence; | %structure;)*>
<!ATTLIST prosody
pitch CDATA #IMPLIED
contour CDATA #IMPLIED
range CDATA #IMPLIED
rate CDATA #IMPLIED
duration CDATA #IMPLIED
volume CDATA #IMPLIED >
<!ELEMENT audio (%allowed-within-sentence; | %structure;)*>
<!ATTLIST audio
src %uri; #IMPLIED >
<!-- These basic container elements can contain any of the -->
<!-- within-sentence elements, but neither sentence or paragraph. -->
<!ELEMENT emphasis (%allowed-within-sentence;)*>
<!ATTLIST emphasis level (strong|moderate|none|reduced) ''moderate'' >
<!-- These basic container elements can contain only data -->
<!ENTITY % sayas-types "(acronym|number|ordinal|digits|telephone|date|time| duration|currency|measure|name|net|address)">
<!ELEMENT sayas (#PCDATA)>
<!ATTLIST sayas
type %sayas-types; #REQUIRED >
<!ELEMENT phoneme (#PCDATA)>
<!ATTLIST phoneme ph %phoneme-string; #REQUIRED
alphabet %phoneme-alphabet; #IMPLIED >
<!-- Definitions of the basic empty elements -->
<!ELEMENT break EMPTY>
<!ATTLIST break size (large|medium|small|none) ''medium''
time %duration; #IMPLIED >
<!ELEMENT mark EMPTY>
<!ATTLIST mark name CDATA #REQUIRED >
语音对话
所谓语音对话就是语音浏览器的对话控制部分。它是整个语音浏览器的主要“食物”。VoiceXML其实就是典型的语音浏览对话控制语言。编写VoiceXML非常类似在编写一段程序,而不像HTML那样纯粹是信息的堆砌。
因为要考虑到语音浏览器的特殊浏览方式,对于语音对话控制部分的标识语言的设计就显得特别的困难。W3C也只是对它的需求进行了说明,然后又认证由工业界提交的现成版本。因为我们将在后面详细介绍VoiceXML的结构,所以我们只在这一小节中对W3C的需求说明进行简单的介绍。
总的来看,需求说明阐明了四个大方面的需求:
形态需求:这主要是对浏览器输入输出以及中间过程上的数据形态的规定。
功能需求:这主要是对可支持的对话发式的定义。针对语音浏览会最常用到的对话方式,规定了一些语音对话标识语言必须实现的对话功能。
格式需求:在标识语言的书写格式上也有一些要求。比方是对可重复使用的常用单元的支持等。
其他方面就非常空泛了。包括触发事件句柄、语音浏览的用户制和语音用户的认证。
在这一部分中主要是VoiceXML的介绍。这里没有完全列出所有VoiceXML语法。详尽的说明请见W3C上的说明。这里只是给您一个对关键环节的了解。我相信并不是每一个网络大侠都详细学习过HTML的语法,更多的是在参照已有页面的基础上渐进掌握的。
VoiceXML基础
VoiceXML是一种编程语言。但它又不是一般的编程语言,它必须考虑到特殊的语音应用环境。下面是它的部分实现功能:
识别输入语音
识别电话按键输入
输出音频
语音合成
基本电话连接功能
上面列举出来的功能并不是由VoiceXML独自完成的。VoiceXML做到的是提供一种应用其他组件的机制。而具体的操作是由语音浏览器实现的。 值得一提的是VoiceXML实现了基本编程语言的所有基本特性,比如是程序流程控制,代码重用等等。
另外VoiceXML和HTML有非常多的相似之处。在HTML中,文件是由首尾呼应的标识来组成的;VoiceXML中也是由标识来组成的。在HTML中代码是用“页”来分别的;在VoiceXML中是用“文档”来分别的。在HTML中有链接的标识来跳转;在VoiceXML中同样可以跳转至其它文档。
每一个VoiceXML文档都是完整的XML文档。所以,构成VoiceXML文档下面的标识是必不可少的:
<?xml version = “1.0” ?>
<vxml version = “1.0” >
…………
</vxml>
正如前面说到的VoiceXML是用文档来分别的。一个VoiceXML的应用是一系列VoiceXML文档的集合。而且每一个应用都包含一个“根文档”。这有点像一个动态网站的default.asp或是index.asp。在VoiceXML应用调用的时候,“根文档”始终被调用。
在每一个文档中,都有很多的“对话”(Dialog)。在每一个特定的时刻,人机交互都处在一个特定的对话状态当中。每一个对话都可以明确的指明下一个目的对话。整个文档就是有这些对话状态组成的“有限状态机”。对话的跳转是由URI指定的。每一个文档和对话都可以被确切指定。如果没有指定具体的文档,当前文档就是默认文档。如果具体的对话没有被指定,那么目的文档的第一个对话就是默认对话。
对话分为两种,一种是Form,另一种事Menu。Form是专门用来从客户端收集信息并赋值给特定变量的。在Form当中,有很多的域(Field)。Field就相当于我们常用的变量。Form通过收集用户输入(语音或是按键),把识别出的值赋给变量。Menu的形式是为用户提供多个选项,根据不同的选择,应用进程将跳转至不同的对话。
关于Form和Menu的详细内容我们在下面的小节详细的介绍。
VoiceXML中的Form
正如Form的意义一样,它是一张表格。就好像在申请贷款时候要填具详细信息一样,在语音应用中,需要和用户来交互。用户通过电话输入表格中的每一项。
让我们通过一个具体的例子来看一看:
<?xml version="1.0"? encoding="gb2312" ?>
<vxml version="1.0">
<form id="选片">
<field name="movie">
<prompt>你想欣赏哪一部电影?</prompt>
<grammar>大话西游|国产零零七|鹿鼎记</grammar>
<filled>
<if cond=" movie ==''国产零零七''">
<prompt>国产零零七今天只有晚上十点一场放映。</prompt>
</if>
</filled>
</field>
</form>
</vxml>
在上面的例子当中,有一个Form标识,其中只有一个变量(域)需要填充。首先,系统会问用户“你想欣赏哪一部电影?”,这时用户可以回答grammar标识中限定的《大话西游》、《国产零零七》和《鹿鼎记》。输入之被赋给名字为movie的域。Filled标识用来完成当域被填充之后的操作。在这里,操作是读出“国产零零七今天只有晚上十点一场放映。”这样一句话。
VoiceXML中的Prompt
Prompt标识比较简单,它指示系统为用户读出标识内包含的语句。我们其实在前面的例子中也已经看到了。比较完备的浏览器都是通过通用的语音合成实现发音。
VoiceXML中的Grammar
Grammar标识简单的说就是给用户输入限定的范围。用户只能在grammar列举的范围内发音。当用户输入被识别出来不在grammar范围之内时,语音浏览器就产生一个出错信息。可以在VoiceXML文档中设定出错处理。
Grammar又可以分为三类:inline、external和built-in。
Inline grammar是通过显式的方式在给定的域内写明grammar。在前面的例子中就是inline grammar。 External grammar是通过外部应用的方法来指定grammar。这时候就需要用标识grammar来说明了:
<grammar src="URI" type="mime-type"/>
这里的mime-type可以缺省。因为它可以通过URI的协议来获取,还可以通过外部grammar文件的后缀来获得。即使上面的方法都不能得到,还可以从系统运行平台来指定。还有人会问,要用什么来书写外部grammar呢?比较通用的是Javaä Speech API Grammar Format (JSGF)。
built-in grammar是浏览器平台自己设定的grammar。它是具有个性化的东西。不同的厂家可能会有不同的built-in grammar。为的是方便在浏览器上的应用开发。