做FreeSWITCH图形化界面这套东西已经到第55期了,transfer这个应用确实是后台问题榜上的常客。很多人一看名字"transfer"就条件反射想到电话转接,结果在图形界面里配IVR跳转时也用它,配话务路由时也用它,配分机盲转时还用它,最后转来转去,要么半通,要么循环,要么听不到回铃音。
其实transfer在FreeSWITCH里就干两件事:一是把当前呼叫"踢"到另一个拨号计划的extension去执行,这就是拨号计划跳转;二是在通话中把某条腿直接转移到目标分机,这就是我们说的盲转。这两件事底层是同一套机制,只是触发场景和执行参数不一样。这篇就把transfer的底层逻辑、图形界面里的配置方法、以及transfer 52、p-early-media-support、park hold这些容易让人犯迷糊的参数一次性讲透。不管你是Windows上装个FreeSWITCH自己测试,还是服务器上跑生产环境,这篇文章都适用。
1. transfer与盲转的核心逻辑解析
1.1 别再和bridge、execute_extension搞混了
先说一个最常见的误区:很多人在图形界面里配"转接"或"跳转"时,把transfer、bridge、execute_extension当成一回事,随便选。这三种应用的执行逻辑完全不同,选错了,轻则行为不符合预期,重则整个呼叫流程乱套。
我用一张表把这个说清楚:
| 应用 | 执行方式 | 是否返回原extension | 典型场景 |
|---|---|---|---|
| transfer | 跳出当前extension,进入目标extension,原extension后续动作不再执行 | 不返回 | 路由跳转、盲转 |
| bridge | 将当前通道与目标桥接,通话结束后回到当前extension继续执行 | 通话结束才返回 | 普通外呼、呼转到分机后继续播报 |
| execute_extension | 临时去执行另一个extension,执行完再回到当前extension继续 | 返回 | 子流程复用、号码预处理 |
这里面最容易踩坑的是transfer和execute_extension。transfer就像一个分岔路口,你走上这条路,之前那条路的一切都不管你了;execute_extension像是去隔壁办公室拿个材料,拿完还要回来接着干活。很多人在图形界面里配IVR菜单,希望"播完提示音再跳到某个分机,跳完之后还能再播一段音",结果用了transfer,跳完就回不来了,后续动作全部没执行。这种场景就该用execute_extension,或者把播报音放在跳转之前。
bridge就更不一样了。桥接是当前通道一直保持着对通话的控制权,比如呼叫中心里坐席外呼,接通客户后bridge到某个SIP中继,通话挂断后还能继续执行挂机后的去电弹屏、话单推送之类的逻辑。transfer可没有这个能力,它把控制权直接交出去了。
1.2 盲转的"盲"字从哪来
盲转这个词,英文叫Blind Transfer,核心是"不等对方应答就转"。流程上,用户A和B正在通话,A想把通话转给C,A直接在话机上操作,系统立刻把B和C接起来,A挂机退出。A不会先和C通话确认"你接不接"。
和盲转相对的是协商转,也叫Attended Transfer。协商转时A会先拨通C,问一句"这个客户你接吗?"得到肯定答复后,A再挂断,B和C通话。多了一步"三方确认",用户体验更稳妥,但实现复杂度也高很多。
在FreeSWITCH里,真正干活的是uuid_transfer这个API。图形界面里点一下"盲转"按钮,系统后台做的事情大概是:
bash复制uuid_transfer <当前通话的uuid> -both <目标分机> XML default
这就有必要说说FreeSWITCH里"腿"的概念了。一次A和B的通话,在FreeSWITCH看来不是"一通电话",而是两条独立的通道:A通道(a-leg)和B通道(b-leg),两条腿通过bridge或者某种桥接机制"粘"在一起。你执行uuid_transfer时,如果不带参数,转走的往往只是你指定的那一条腿,另一条腿还留在原地,最后就会出现"转过去了但对方听不到声音""原通话还挂着"这类灵异现象。
所以图形界面里实现盲转,务必用-both参数,把两条腿一起转过去。如果是想把指定的某一条腿转走,比如转B腿,用-bleg。这个参数选错,是生产环境里"转接后一半通话静音"的头号原因。
还有一个容易被忽略的问题:很多IP话机本身有盲转功能,话机直接发一个SIP REF
