跳到正文

FreeSWITCH 业务集成、拨号计划与录音托管专题 ​

⬅️ 返回 FreeSWITCH 容器化部署总览

本文详细介绍 FreeSWITCH 与平台后端业务系统的对接配置,包括 Event Socket Layer (ESL) 通信机制、Dialplan 拨号计划路由至 callflow-esl、RTP 端口规划与防火墙、WebRTC WSS 证书以及 Nginx 通话录音托管服务。


1. ESL (Event Socket Layer) 安全与对接配置 ​

配置文件路径:freeswitch-install/etc/freeswitch/autoload_configs/event_socket.conf.xml

FreeSWITCH 的 Inbound ESL 允许外部管理端(如 apps/callflow-esl 的管理客户端或监控组件)连接到 FreeSWITCH 端口并执行控制命令与事件订阅。

xml
<configuration name="event_socket.conf" description="Socket Client">
  <settings>
    <param name="nat-map" value="false"/>
    <!-- 监听地址::: 表示 IPv4/IPv6 双栈监听;也可填 0.0.0.0 或 127.0.0.1 -->
    <param name="listen-ip" value="::"/>
    <!-- ESL 端口:默认 8021 -->
    <param name="listen-port" value="8021"/>
    <!-- ESL 认证密码:默认 ClueCon,生产环境必须修改为强密码 -->
    <param name="password" value="ClueCon"/>
    <!-- ACL 访问控制:建议生产环境开启 ACL 仅允许 callflow-esl 所在主机 IP 访问 -->
    <!-- <param name="apply-inbound-acl" value="lan"/> -->
  </settings>
</configuration>

联调注意:修改此处的 password 或 listen-port 后,必须同步修改 apps/callflow-esl/config.toml 中的 freeswitch.password 和 freeswitch.port。


2. Outbound ESL 业务编排与拨号计划路由 ​

当用户呼入指定业务号码(如 5000~5099)或外呼接通后,FreeSWITCH 需要通过 Outbound ESL 将控制权交由 callflow-esl 业务服务接管。

2.1 内部呼叫路由 (freeswitch-install/etc/freeswitch/dialplan/default.xml) ​

在 <context name="default"> 顶部已预置 AI 语音接入路由:

xml
<!--
    【AI 语音呼叫流程接入 (Outbound ESL)】
    当分机拨打 50 开头的号码时,将通话无缝送入 callflow-esl 业务层接管,执行智能语音导航与流式交互。
-->
<extension name="callflow-esl-socket">
  <condition field="destination_number" expression="^50">
    <!-- 使用 vars.xml 中的全局解耦宏变量 $${esl_host},避免硬编码 -->
    <action application="socket" data="$${esl_host} async full"/>
  </condition>
</extension>

2.2 公网/中继呼入路由 (freeswitch-install/etc/freeswitch/dialplan/public/00_inbound_did.xml) ​

外部 DID 呼入进入 public 上下文后,优先匹配进线路由:

xml
<!-- 外部运营商 DID 呼入触发 AI 流程 (00_inbound_did.xml) -->
<extension name="public_esl_50">
  <condition field="destination_number" expression="^50">
    <!-- 关键参数: 通道空闲时持续发送静音 RTP 包,防 NAT / 运营商防火墙丢包超时 -->
    <action application="set" data="send_silence_when_idle=-1"/>
    <!-- 建立 Outbound ESL 异步连接,交由业务中台接管调度 -->
    <action application="socket" data="$${esl_host} async full"/>
  </condition>
</extension>

2.3 send_silence_when_idle=-1 底层机制与防丢包原理深度解析 ⭐️ ​

在实时 AI 语音通话(如大模型智能客服或外呼机器人)中,通话流程中存在数个典型的下行音频空白期:

  1. LLM 思考推理期:用户说话完毕触发 VAD 断句后,LLM 大模型思考、检索知识库并生成首句回答往往需要 0.3 ~ 1.5 秒;
  2. 等待用户发言期:播报完引导话术后,机器人等待用户做出回应的时间;
  3. 流程节点跳转与外部 API 查询期:ESL 业务逻辑执行数据库写入或调用第三方 HTTP 接口。

⚠️ 没有开启静音保持时的生产风险 ​

如果通道在上述阶段没有下发任何音频,FreeSWITCH 默认会完全停止发送下行 RTP UDP 报文:

  • NAT 端口老化被关:大多数云厂商 NAT 网关、运营商 SBC、以及客户端路由器对 UDP 连接的会话老化淘汰时间(UDP Session Aging Timeout)极为严格(通常仅 30 ~ 60 秒,某些特定专线甚至仅 15 秒)。一旦无包发送,NAT 会话表项立即被网关清除;
  • 下行断音与丢包:随后当 TTS 生成完毕下发音频时,首批 RTP 包因无法穿越已被释放的 NAT 映射而直接被丢弃,导致用户听到吞字、声音爆卡或单通;
  • 运营商异常拆线:运营商 IMS 核心网或企业级 SBC 普遍内置了严苛的 RTP 媒体无包探测看门狗(RTP Timeout Watchdog),连续数秒无 RTP 流量会直接判定呼叫异常断死,主动向 FreeSWITCH 发送 BYE 强行切断通话!

💡 send_silence_when_idle=-1 的工作原理 ​

  • -1 表示永久持续生效(若设为正整数则代表持续若干毫秒);
  • 当通道处于空闲状态(当前既无文件 playback,也无流式 TTS 灌包)时,FreeSWITCH 内核时钟会自动按照当前协商的编解码器(如 PCMA/PCMU/G.722/Opus)标准包频(每 20ms 一包),持续向对端生成并发送标准的舒适静音(Comfort Noise)或全零静音载荷;
  • 使得整条 UDP RTP 链路在呼叫全生命周期内保持高频双向心跳,100% 根治因静音等待引发的 NAT 断流、防火墙阻断与运营商强制挂机问题。

变量解耦配置说明: 统一使用宏变量 $${esl_host}(在 vars.xml 中定义,如 192.168.2.246:9911 或 127.0.0.1:9911)。无论 callflow-esl 跑在本地 WSL、宿主机还是独立应用服务器,仅需在 vars.xml 修改单点即可全局生效。


3. RTP 媒体流端口范围与防火墙安全组 ​

配置文件路径:freeswitch-install/etc/freeswitch/autoload_configs/switch.conf.xml

xml
<configuration name="switch.conf" description="Core Configuration">
  <settings>
    <!-- 设置 FreeSWITCH RTP 动态端口范围 -->
    <param name="rtp-start-port" value="30000"/>
    <param name="rtp-end-port" value="30199"/>
  </settings>
</configuration>

重要约束:

  1. 严禁端口冲突:如果同时部署了 coturn 服务,coturn 的 relay 端口范围(如 31000-31040/UDP)绝对不能与 FreeSWITCH 的 RTP 端口范围重叠。
  2. 防火墙放行:云服务器公网安全组必须放行 30000-30199/UDP 端口段。

4. WebRTC 与 TLS / WSS 证书配置 ​

  1. WebRTC 监听端口(位于 sip_profiles/internal.xml):
    xml
    <!-- SIP over WS 端口 -->
    <param name="ws-binding" value=":5066"/>
    <!-- SIP over Secure WSS 端口 -->
    <param name="wss-binding" value=":7443"/>
  2. 证书替换: freeswitch-install/etc/freeswitch/tls/ 目录中的 wss.pem 和 dtls-srtp.pem 为开发测试自签名样例证书。生产环境使用 WebRTC 时,必须替换为正式域名证书:
    • wss.pem:包含服务器证书与私钥的合成 PEM 文件;
    • dtls-srtp.pem:DTLS-SRTP 媒体流加密证书。

5. 通话录音持久化与 Nginx 托管 ​

  1. 录音持久化路径: 通话录音默认保存于宿主机 freeswitch-install/var/recordings/。
  2. Nginx 静态托管: docker-compose.yml 中已编排 fs-recordings-nginx 服务,将该目录只读挂载至 Nginx,监听宿主机 8088 端口:
    • 配置文件:nginx/conf.d/recordings.conf
    • Web 访问路径:http://<server-ip>:8088/recordings/<call-uuid>.wav
    • 支持跨域(Access-Control-Allow-Origin: *)与 Accept-Ranges: bytes 音频拖拽播放。
  3. 平台服务联动: 在 apps/callout-server/config.toml 或 apps/callflow-server/config.toml 中,将录音基础 URL 配置为:
    toml
    recordingBaseUrl = "http://<fs-host>:8088/recordings"

6. 内部分机用户管理 (directory/default/) ​

  • 预置分机文件:1000.xml ~ 1019.xml(共 20 个测试分机)。
  • 注册密码:默认继承 vars.xml 中的 $${default_password},也可在单个分机 XML 中单独指定 <param name="password" value="YourPass"/>。

文档与代码在同一仓库维护,现有 Markdown 是唯一内容源。