在这一部分我们将会讲述一些关于如何建立语音菜单的东西, 语音菜单通常指的是自动服务业(auto-attendants)或IVR菜单. IVR表示Interface Voice Response(语音应答接口).通常用来表示主叫通过用电话键盘上的触碰按键来导航的系统。当主叫在他们的键盘按下一个键的时候,电话就会发出两个音频,通称DTMF音频.DTMF表示Dual Tone Multi-Frequency(双音多频).Asterisk 可以识别DTMF音频并作出相应的回应.
让我们开始学习在Asterisk拨号方案中如何建立IVR菜单:
Background and WaitExten Applications
Background()应用播放一个语音提示,但它会倾听DTMF的输入,Asterisk一直尝试地在当前的拨号方案中寻找与DTMF输入匹配的分机,如果寻找到了匹配的分机,Asterisk将会发送该路呼叫到对应的extension.
和Playback()应用一样,Background()应用只需自带语音提示文件的名字即可,因此无需添加文件的后缀名.
Multiple Promts(多语音提示)
如果在Background()应用当中需要播放多个语音,简单地用&符号将这些语语音文件的文件名串联起来即可.
exten => 6123,1,Background(prompt1&prompt2&prompt3)
在Background()应用会遇到有一个问题就是你可能会让Asterisk在播放完语音提示之后等待几秒钟.为了能够做到这一点,你可以调用WaitExten()应用.你通常会看到在Background()应用之后会立即调用WaitExten()应用.WaitExten()应用的第一个参数就是主叫在输入一个分机号前需要等待的秒数. 如果不支持第一个参数,那么Asterisk将会使用内嵌的响应超时(超时可以通过修改拨号方案函数TIMEOUT()实现).
[auto_attendant]
exten => start,1,Verbose(2,Incoming call from ${CALLERID(all)})
same =>n,Playback(silence/1)
same =>n,Background(prompt1&prompt2&prompt3)
same =>n,WaitExten(10)
same =>n,Goto(timeout-handler,1)
exten =>timeout-handler,1)
same => n,Dial(${GLOBAL(OPERATOR)},30)
same =>n,Voicemail(operator@default,${IF($[${DIALSTATUS} = BUSY]?b:u)})
same =>n,Hangup()
Goto Application and Priority Labels
在我们创建一个auto-attendant(自动服务员)菜单之前,让我们涉及几个有用的拨号方案应用. Goto()运行我们从拨号方案内的一个位置跳到另外一个.Goto()应用的参数均比我们目前为止看到的应用的参数复杂.但不要让它吓倒了.
Goto()应用可以调用一个,两个或者三个参数. 如果Goto()应用只调用一个简单的参数,那么Asterisk将会在当前的extension中调到指定的优先级(或者它的标签).如果你指定两个参数,Asterisk将会读取第一个参数作为在当前context内的跳入点,把第二个参数作为extension的优先级.如果你给应用传入三个参数,那么Asterisk将会假设他们是分别将要跳入的context, 优先级.
[startingContext]
exten => 100,1,Goto(monkeys)
same => n,NoOp(we skip this)
same =>n(monkeys),Playback(tt-monkeys)
same =>n,HangUP()
exten => 200,1,Goto(start,1) ;play tt-weasels then tt-monkeys
exten => 300,1,Goto(start,monkeys); only play tt-monkeys
exten => 400,1,Goto(JumpingContext,start,1) ;play hello-world
exten => start,1,NoOp()
same => n,Playback(tt-weasels)
same =>n(monkeys),Playback(tt-monkeys)
[JumpingContext]
exten => start ,1,NoOp()
same => n,Playback(hello-world)
same => n,Hangup()
SayDigit, SayNumber, SayAlpha, and SayPhonetic Applications
当还没有完全涉及auto-attendant菜单时,让我们介绍几个用于给主叫读取各种各样信息的应用. SayDigits()和SayNumber()应用均用于向主叫读取指定的号码.如果想用SayDigits()和SayNumber()应用,简单地将你想要播报的号码传送给它作为第一个参数.
SayDigits()应用一次只读取一个你指定的号码.例如,SayDigit(123), Asterisk将会这样都回:“one two three”. 另外一方面,SayNumber()应用将会把号码作为一个整体的数字来读回.例如:SayNumber(123),Asterisk将会这样读回:”one hundred twenty three”.
SayAlpha()和SayPhonetic()应用均用于向主叫拼写一个字母数字混合的字符串. SayAlpha()每次只读取一个指定的字符串一个字母. 例如,SayAlpha(hello)将会将会拼写“hello”的一个字母.SayPhonetic()应用将会用国际音标向主叫拼写,SayPhonetic(hello)回读为“Hotel Echo Lima Lima Oscar”.
我们将用这四个应用来通过这个指南来给主叫回读一些数据. 与此同时,你也可以尽管在你的拨号方案中添加一些例子来尝试这些应用。这里有一些例子:
exten => 6592,1,SayDigits(123)
exten => 6593,1,SayNumber(123)
exten => 6594,1,SayAlpha(hello)
exten => 6595,1,SayPhonetic(hello)
Creating a Simple IVR Menu
我们继续前进并引用我们所学到各个应用来建立一个简单的auto-attendant菜单.在一个新的context中建立一个auto-attendant或IVR菜单是惯例的做法.它与其他拨号方案内的分级保持着独立.在extensions.conf中将如下添加至你的拨号方案中用以创建一个新的demo-menu 上下文.在这个新的上下文中,我们将会创建一个简单的菜单,它提示你输入一个或两个数字并返回你刚输入的数字.
示例语音提示
请注意如下(还有这个指南中其他的例子)我们使用的示例语音提示都是extra语音包当中的.如果你早前没有安装这个extra语音包,那么你现在最好把它安装好.
[demo-menu]
exten => s,1,Answer(500)
same => n(loop),Background(press-1&or&press-2)
same =>n,WaitExten()
exten => 1,1,Playback(you-entered)
same => n,SayNumber(1)
same =>n,Goto(s,loop)
exten =>2,1,Playback(you-entered)
same => n,SayNumber(2)
same =>n,Goto(s,loop)
在我们使用上面这个demo-menu之前,我们需要添加一个分级到[docs:users]context来将主叫重定向到我们的菜单中. 这你的拨号方案中添加如下这行到[docs:users]
exten => 6598,1,Goto(demo-menu,s,1)
执行reload从新加载拨号方案 ,然后拨打6578测试auto-attendant菜单.
Handling Special Extensions
我们已经创建了一个基本的auto-attendant菜单, 我们现在将它变得更强壮一点.让它能够处理一下特殊的情况,比如主叫输入一个无效的分机,或者一个分机都没输入等情况.Asterisk用于一套用来处理上述情形的extensions.他们都用单独一个字母来命名.因此我们推荐不要创建任何用单个字母命名的extension. 通常大多数的extensions包括:
i: the invalid entry extension(无效的分级输入)
如果Asterisk无法在Background()和WaitExten()应用中找到一个与当前context中被拨打的数字匹配的extension,那么它会将这路呼叫发送到i 分机.
t: the response timeout extension(回应超时的分机)
当主叫在给Background()和WaitExten()应用输入回应之前等待的时候太长了,而且在当前的上下文中没有更多优先级了,那么呼叫将会被送到t 分机.
s: the start extension(开始分机)
当一路来自模拟线路的呼叫拨打至Asterisk,那么该呼叫将会送到s 分机. s分机也用在宏当中.
h: the hangup extension(挂断分机)
当一路呼叫被挂断了,Asterisk将会在当前的context中执行h 分机. 这一种在一路呼叫完成后拆收线路时典型的用法.
o: the operator extension(操作员分机)
当主叫正在录一条语音留言时,如果他们在的电话键盘上按的0号键,那么主叫将会被重定向到o分机. 这是一种典型的做法,因为这样可以让主叫能够通过拨打0号键找到操作员.
a: the assistant extension
这个分机与o分机类似,只是它只在主叫录语音留言的时候按*号键时才触发。这是找到assistant(助手)典型做法.
我们添加如下几行到[docs:demo-men] context中来处理无效输入和超时. 修改你的[docs:demo-menu] context来匹配如下这个:
[demo-menu]
exten => s,1,Answer(500)
same =>n(loop),Background(press-1or&press-2)
same =>n,WaitExten()
exten => 1,1,Playback(you-entered)
same =>n,SayNumber(1)
same =>n,Goto(s,loop)
exten => 2,1,Playback(you-entered)
same =>n,SayNumber(2)
same =>n,Goto(s,loop)
exten =>i,1,Playback(option-is-invalid)
same =>n,Goto(s,loop)
exten => t,1,Playback(are-you-still-there)
same =>n,Goto(s,loop)
现在再次拨打你的auto-attendant菜单 (通过拨打6598). 这时在auto-attendant菜单中尝试输入一个无效的数字(比如3).将冗余度调到3或更大你可以在Asterisk的命令行接口当中看到类似如下的信息:
– Executing [6598@users:1] Goto(“SIP/demo-alice-00000008″, “demo-menu,s,1″) in new stack
– Goto (demo-menu,s,1)
– Executing [s@demo-menu:1] Answer(“SIP/demo-alice-00000008″, “500″) in new stack
– Executing [s@demo-menu:2] BackGround(“SIP/demo-alice-00000008″, “press-1&or&press-2″) in new stack
– <SIP/demo-alice-00000008> Playing ‘press-1.gsm’ (language ‘en’)
– <SIP/demo-alice-00000008> Playing ‘or.gsm’ (language ‘en’)
– <SIP/demo-alice-00000008> Playing ‘press-2.gsm’ (language ‘en’)
– Invalid extension ’3′ in context ‘demo-menu’ on SIP/demo-alice-00000008
– Executing [i@demo-menu:1] Playback(“SIP/demo-alice-00000008″, “option-is-invalid”) in new stack
– <SIP/demo-alice-00000008> Playing ‘option-is-invalid.gsm’ (language ‘en’)
– Executing [i@demo-menu:2] Goto(“SIP/demo-alice-00000008″, “s,loop”) in new stack
– Goto (demo-menu,s,2)
– Executing [s@demo-menu:2] BackGround(“SIP/demo-alice-00000008″, “press-1&or&press-2″) in new stack
– <SIP/demo-alice-00000008> Playing ‘press-1.gsm’ (language ‘en’)
– <SIP/demo-alice-00000008> Playing ‘or.gsm’ (language ‘en’)
– <SIP/demo-alice-00000008> Playing ‘press-2.gsm’ (language ‘en’)
如果你在auto-attendant菜单中没有输入任何东西. 那么超过大约10秒的时候,你将会听到Asterisk跳转到了t分机.
Cheers!