Administrator
发布于 2026-11-02 / 3 阅读
0
0

FreeSWITCH的IVR怎么配:按键分流、超时和输错处理|实战05

English
中文

这一期做一个能拨进去的语音菜单:拨7180,按1找7101,按2找7102,按0进入7190队列,按9重听,按星号结束。一直不按键或者连续输错,都会转到7190。前四期的分机、队列和呼入路由继续使用。

本期先在内网完成,公网NAT暂时不参与讨论。

菜单文件和入口文件分开放

IVR是交互式语音应答。这里用mod_dptools提供的ivr应用播放菜单、收取DTMF按键;分机仍是SIP用户,7190仍进入training@default,菜单不会额外创建agent或tier。

在fs_cli查询实际目录和现有落点:

eval $${conf_dir}
eval $${sounds_dir}
sofia status profile internal reg
callcenter_config queue list agents training@default

下面用CONF代表配置目录,SOUNDS代表声音目录。7101、7102先完成注册、互拨,7190先能进入队列。确认7180尚未被其他规则占用,再备份将要修改的文件。

CONF/autoload_configs/ivr.conf.xml负责包含菜单目录。vanilla已有下面结构,已有就保留;缺少包含指令时补到menus内部,不要再套一份configuration。

<configuration name="ivr.conf" description="IVR menus">
  <menus>
    <!-- 以当前配置文件目录为起点,读入ivr_menus下的菜单 -->
    <X-PRE-PROCESS cmd="include" data="../ivr_menus/*.xml"/>
  </menus>
</configuration>

default目录的文件则由CONF/dialplan/default.xml包含。两条包含链都要在:一个让FS找到菜单,一个让7180找到调用它的动作。

先准备三段本地提示音

在SOUNDS下新建training目录,准备单声道PCM WAV文件:ivr-main.wav读“欢迎,找7101请按1,找7102请按2,人工队列请按0,重听请按9,结束请按星号”;ivr-invalid.wav读“输入有误,请重新选择”;ivr-bye.wav读“感谢来电,再见”。可用8kHz、16bit单声道PCM作为本例素材,文件扩展名改成wav并不会自动完成编码转换。

让FS运行用户对目录有进入权限、对文件有读取权限,实例中需有可读WAV的文件模块。三段声音都放在本机,本例不依赖中文语音包、phrase宏或TTS服务。$${sounds_dir}在XML预处理时展开;如果实例使用了不同声音目录,以查询结果为准。

新建完整菜单

新建CONF/ivr_menus/05_training_main.xml,内容如下。提示音和菜单选项要一致,后面改了按键,也要重录对应声音。

<include>
  <!-- 独立菜单名,供拨号计划中的ivr应用引用 -->
  <menu name="training_main_05"
      greet-long="$${sounds_dir}/training/ivr-main.wav"
      greet-short="$${sounds_dir}/training/ivr-main.wav"
      invalid-sound="$${sounds_dir}/training/ivr-invalid.wav"
      timeout="5000"
      inter-digit-timeout="2000"
      max-failures="2"
      max-timeouts="2"
      digit-len="1"
      exec-on-max-failures="transfer 7190 XML default"
      exec-on-max-timeouts="transfer 7190 XML default">
    <!-- 按1:重新进入default里的7101拨号规则 -->
    <entry action="menu-exec-app" digits="1"
           param="transfer 7101 XML default"/>
    <!-- 按2:同样调用现有7102规则,不在此复制bridge -->
    <entry action="menu-exec-app" digits="2"
           param="transfer 7102 XML default"/>
    <!-- 按0:交给7190,由已有规则执行callcenter -->
    <entry action="menu-exec-app" digits="0"
           param="transfer 7190 XML default"/>
    <!-- 按9:回到顶层菜单,本例只有一层 -->
    <entry action="menu-top" digits="9"/>
    <!-- 按星号:退出菜单,后面的拨号计划负责告别与挂机 -->
    <entry action="menu-exit" digits="*"/>
  </menu>
</include>

name是菜单标识,不是拨入号码,调用ivr时使用它。greet-long是首次提示;greet-short用于后续轮次,本例重用完整提示,正式使用可换成短提示文件。invalid-sound在收到未匹配输入时播放,空等超时走另一条计数逻辑。

timeout="5000"设置无输入等待的毫秒值,5000就是5秒,不是整通电话最多5秒。inter-digit-timeout="2000"是多位输入的位间等待,本例单键已能完成选择,它主要留给后面的多位分机实验。提示音播放、重播和转接还会占时间,不能把它们算成固定的总等待时长。

max-failures="2"表示无效输入达到阈值后的处理,max-timeouts="2"控制无输入超时达到阈值后的处理。两个exec-on-max属性的值都是“应用名加参数”,这里执行transfer,把电话交给7190 XML default。0不是“永远等待”的通用写法;本例两个阈值都明确填正整数。

digit-len="1"让本例按一位收号。entry里的digits是按键,action决定做什么,param是动作参数。menu-exec-app执行拨号应用;transfer后依次写目标号码、XML、context,继续复用现有分机或队列规则。按0与两种超限兜底都进入同一个队列,队列里有没有可接单座席仍由agent状态、tier和整理时间决定。

给7180接上菜单

新建CONF/dialplan/default/05_training_ivr.xml:

<include>
  <!-- 内部分机拨7180时进入本期菜单 -->
  <extension name="training-ivr-entry-05">
    <condition field="destination_number" expression="^7180$">
      <!-- 菜单播放前接听本通电话 -->
      <action application="answer"/>
      <!-- 给接听后的媒体留出200毫秒缓冲 -->
      <action application="sleep" data="200"/>
      <!-- 名称必须与菜单定义一致 -->
      <action application="ivr" data="training_main_05"/>
      <!-- 星号退出或菜单意外返回时,继续以下收尾 -->
      <action application="playback"
              data="$${sounds_dir}/training/ivr-bye.wav"/>
      <!-- 结束该通测试电话 -->
      <action application="hangup"/>
    </condition>
  </extension>
</include>

answer在播菜单前接听,sleep的200单位也是毫秒,是示例缓冲值。ivr的data引用training_main_05。星号的menu-exit只退出菜单,后面明确安排告别音与hangup;它不是“自动转人工”。成功transfer则转到目标拨号计划,后面的收尾用于菜单正常退出或意外返回。

可以先由7102拨7180,按1呼叫7101。测试按2时换7101拨入,避免拿同一部电话同时当来电方和被叫。

让上一期的呼入号码也能进菜单

要沿用04期的测试入口,可在原CONF/dialplan/public/04_training_inbound.xml的include内增加下面这一段,放在training-inbound-unassigned规则前面。55507180只是本系列虚构的实验入口,不是真实运营商号码。

<!-- 放入04_training_inbound.xml的include内,位于未分配号码规则之前 -->
<extension name="training-inbound-to-ivr-05">
  <condition field="destination_number" expression="^55507180$">
    <!-- 保存入口号码,与04期保持相同口径 -->
    <action application="set" data="inbound_did=${destination_number}"/>
    <!-- 只放行这个固定测试入口到菜单接入号 -->
    <action application="transfer" data="7180 XML default"/>
  </condition>
</extension>

04期后面的^55507[0-9]{3}$会接住这一范围里的未分配号码。新规则放到它后面,55507180就会先被拒绝;仅仅新建一个排序更后的public文件也可能遇到同样问题。测试时保留55507101和55507190原来的去向,只增加这个固定映射。

加载后怎么验收

保存后在fs_cli执行reloadxml并检查XML错误。这里只增加菜单与拨号规则,新一通电话再进入菜单即可;已有通话中的菜单不会自动变成新版本。

用7102拨7180,听完整提示再按1,7101应振铃并可双向通话。再用7101拨入按2检查7102。队列测试前记下两个agent原状态,测试来电方暂设On Break,只让另一台测试座席Available,结束后恢复。

callcenter_config agent set status agent7102 On Break
callcenter_config agent set status agent7101 Available

由7102拨入按0,应进入training@default;按8两轮检查无效输入后的队列兜底,另开一通全程不按键检查超时兜底。按9应重听顶层菜单,按星号应听告别音并结束。每个分支单独打一通,挂断后再测下一个。

核对public路由时可执行下面命令,YOUR_DOMAIN替换为第一期确认的用户域。7102先振铃,接听后才进入55507180这个public入口。

originate user/7102@YOUR_DOMAIN 55507180 XML public

还常用哪些配置

原demo模板有phrase提示、tts-engine、tts-voice、confirm-macro、confirm-key、confirm-attempts。phrase要有对应宏,TTS要有实际引擎和声音,复制模板里的flite/rms并不会安装服务。确认参数用于让用户核对已收的号码,单键分流通常不需要,本例省略。

需要多级菜单时,entry用menu-sub指向另一个已定义菜单,menu-back退上一层,menu-top回到当前调用栈的顶层;本例只有一层,9的效果就是重听。exit-sound是菜单退出提示,transfer-sound用于menu-exec-app调用transfer前的提示;本例把退出音放在拨号计划里,两边同时配会有重复播报的可能。

如果想让用户直接输入7101或7102,可做一个独立实验:把digit-len改为4,并增加下面这项。其余单键项可保留,但收号可能要等待位间超时,按1不再和单键版本一样立即分流。

<!-- 可选实验:配合菜单digit-len="4",只允许这两个四位分机 -->
<entry action="menu-exec-app" digits="/^(710[12])$/"
       param="transfer $1 XML default"/>

$1取正则捕获到的分机,本例只放行7101、7102。要开放别的号码,应明确列出业务允许的范围,不能顺手把所有数字送到内部拨号计划。多位号码和单键混合菜单要重测重叠输入、位间等待及超限逻辑;默认版本仍保持digit-len="1"。

常见卡点与回退

拨7180立即结束:先看是否命中入口,再查菜单名、ivr.conf的include和提示音文件是否可读。日志出现Unable to find menu时,优先检查名字及包含链,反复改号码没有帮助。

能听见提示但按键无效:把“没收到按键”和“收到了却没匹配”分开。对照电话的DTMF设置、协商的telephone-event及FS日志;RTP音频和DTMF事件是不同内容,能说话也可能收不到按键。RFC 4733说明了RTP事件传输。

按1后电话不响:查7101的default路由、用户域和注册;进入队列后没人响:继续查座席资格和原7190规则。单键明显变慢:看看是否为了直拨分机把digit-len调成4;public入口被404:检查它是否落在04期宽规则后面。

回退时先结束测试通话,恢复04期public文件备份,移走本期两个新增XML;若改过父include也恢复备份,再reloadxml。恢复agent原状态,复查7101/7102互拨与7190队列。提示音确认不再被使用后再处理,回退不需要重建分机或队列。

下一期接运营商gateway和外呼线路,区分注册型中继与按IP鉴权的线路。

核验资料

菜单结构与动作按官方v1.10.12模板、菜单实现及ivr调用实现核对。当前IVR手册用于补充说明。核验日期2026-11-02,其他版本需对照本机模板与模块。


评论