三种典型拓扑

拓扑 A:单机一体(开发 / 演示)

1
2
3
4
┌──────────────────────────────────────────────────┐
│ Single Host │
│ FreeSWITCH + callflow-esl + ASR + TTS + MySQL │
└──────────────────────────────────────────────────┘
  • 适合:本地开发、PoC 演示、小并发自用
  • 全部走 127.0.0.1,零网络
  • 配置最简单
  • 缺点:FS 与 ASR/TTS 抢 CPU;并发上不去;单点

拓扑 B:FS 与业务/AI 分离(推荐生产起点)

1
2
3
4
5
6
7
┌─────────────────────────┐         ┌────────────────────────────┐
│ FreeSWITCH Host │ ◄────► │ Application Host │
│ (Linux, 公网 / SIP) │ ESL │ - callflow-esl │
│ mod_audio_fork │ WS │ - sherpa-asr-online-srv │
│ │ HTTP │ - sherpa-tts-server │
└─────────────────────────┘ │ - MySQL │
└────────────────────────────┘
  • 适合:本项目当前主推的生产模式
  • FS 只做软交换与媒体,专注稳定;业务/AI 在一台机器上集中处理
  • 单台 application host 8 核 16G 可承载几十路并发
  • 横向扩展:起多个 application host,配多个 dialplan / originate 分流

拓扑 C:全分布式(高并发)

1
2
3
4
5
6
7
8
9
10
┌──────────────┐   ┌──────────────┐   ┌─────────────────┐
│ FreeSWITCH×N │──►│ callflow-esl │──►│ TTS Server×M │
│ (LB / SIP) │ │ ×K (LB) │ └─────────────────┘
└──────────────┘ │ │
│ │ │ ┌─────────────────┐
└──────────►│ │──►│ ASR Server×M │
WS audio └──────────────┘ └─────────────────┘


MySQL Cluster
  • 适合:百路并发以上、要求高可用
  • 需要前端 LB(haproxy / nginx)做 ESL / HTTP / WS 路由
  • ASR / TTS 都是无状态服务,可任意横向扩
  • callflow-esl 当前是无业务 sticky 状态(一条通话对应一条 ESL 连接),适合水平扩

端口与防火墙

方向 协议 端口 用途
外部 → FS SIP/UDP 5060 呼入
外部 → FS RTP/UDP 16384-32768(FS 默认) 媒体
FS → callflow-esl TCP 9911 outbound ESL
callflow-esl → FS TCP 8021 inbound ESL
调用方 → callflow-esl HTTP 9912 POST /outbound-calls
FS (mod_audio_fork) → ASR WS 10096 音频上行
callflow-esl → TTS HTTP 9080 合成请求
FS → TTS HTTP 9080 wav 下载
任意 → ASR HTTP 10096 /health

跨主机部署时务必把上述端口在防火墙打开。

网络与地址陷阱

注意

部署最容易翻车的两个配置项:

1. callbackHost / callbackPort

在 callflow-esl config.jsonfreeswitch 节:

1
2
3
4
5
6
7
8
9
{
"freeswitch": {
"host": "<FS 机器 IP>", // callflow-esl 主动连 FS 用
"port": 8021,
"password": "ClueCon",
"callbackHost": "<本机 IP>", // FS 回拨 callflow-esl 用
"callbackPort": 9911
}
}
  • callbackHost 是 FS 进程发起 outbound 回连时用的目标地址
  • 必须是 FS 进程能 ping 通的 IP
  • 千万不要写 127.0.0.1,除非 FS 与 callflow-esl 同机

2. publicBaseUrl(TTS 服务)

在 sherpa-tts-server config.json

1
2
3
4
5
{
"listenHost": "0.0.0.0",
"listenPort": 9080,
"publicBaseUrl": "http://<TTS 机器对外可访问 IP>:9080"
}
  • 返回给 callflow-esl 的 wavUrl 用这个前缀拼
  • callflow-esl 把 wavUrl 交给 FS,FS 用这个 URL 拉 wav
  • FS 必须能从自己网络访问到 publicBaseUrl
  • 一旦不通,表现就是接通后没有声音

远程联调模式

本项目工程规范里描述了一个常用调试模式:

本地联调优先使用仓库内可直接运行的 unimrcp/。如需对接远端 FreeSWITCH 环境,可使用 ssh debian11 登录对应服务器;该服务器上运行 FreeSWITCH。默认场景:本地 ASR/TTS/业务服务 + 远端 FreeSWITCH。

在这种模式下:

1
2
3
4
5
6
开发机(Windows)                         远端服务器(Linux)
┌──────────────────────────┐ ┌────────────────────┐
│ callflow-esl │ │ FreeSWITCH │
│ sherpa-asr-online-server │ ◄──────────► │ mod_audio_fork │
│ sherpa-tts-server │ internet/ │ │
└──────────────────────────┘ VPN └────────────────────┘

要点:

  • 开发机配 listenHost: "0.0.0.0"(所有服务),公网/VPN 可访问
  • callbackHost 填开发机的公网 IP
  • audioFork.wsUrl 填开发机公网 IP
  • publicBaseUrl 填开发机公网 IP
  • 远端 FS dialplan socket 指向开发机 IP
1
2
3
4
5
# 在 FS 端验证开发机可达
ssh debian11
fs_cli -x "show modules" | grep audio_fork
curl http://开发机:10096/health
curl http://开发机:9080/tts -d '{"text":"测试"}' -H "Content-Type:application/json"

资源规划

资源 估算
ASR 单实例内存 ~600MB(含 zipformer + silero)
TTS 单实例内存 ~800MB(含 vits-aishell3)
单路 ASR 并发 CPU ~0.3 核(RTF ~0.3 看机器)
单路 TTS 一次合成 ~0.5 秒/句(RTF ~0.5 看机器)
TTS wav 缓存增长 平均 50KB/句,按业务积累,需定期清理
callflow-esl 单连接内存 <2MB
MySQL 数据量 业务路由表,KB 级

并发估算

  • 1 台 8 核 16G application host
  • maxSessions = 16sessionPoolSize = 16ttsPoolSize = 4
  • 可稳定承载 15~20 路同时在线通话(含 ASR + 间歇性 TTS)

要更高并发:增加 application host,按 SIP 域名 / 号段做分流。

TTS wav 缓存管理

sherpa-tts-server 当前没有 LRU / TTL,wav 会持续累积在 build/Release/public/wav/

生产建议:

  • 设定时任务每日/每周清理 wav/ 下超过 N 天的文件
  • 由于命名是文本 hash,删除老文件不会破坏服务,下次请求会重新生成
  • 如果业务场景文本高度收敛(IVR 固定话术),缓存命中率会非常高,wav 增长非常慢

示例清理脚本(PowerShell,删 7 天前的 wav):

1
2
3
Get-ChildItem "C:\...\public\wav\" -Filter "*.wav" |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } |
Remove-Item

高可用 / 平滑升级

当前局限

注意

  • ASR / TTS / callflow-esl 都没有 graceful shutdown:直接 SIGTERM / Ctrl+C 会中断在途请求与连接
  • 没有内置健康检查 + auto restart;建议用 systemd / supervisor / nssm 托管
  • 没有内置鉴权;务必置于内网或加反代鉴权层(nginx + basic auth / mTLS)

推荐做法

  1. 后端 ASR / TTS 起多实例 + LB(按 hash 或 round-robin)
  2. callflow-esl 按号段分流,单实例宕机只影响新连接,老连接由 runtime 兜底清理
  3. 升级时先把流量切走,等 ESL 连接全部断开,再重启
  4. 模型升级:放新目录,改配置,重启服务;旧 wav 缓存可清也可留(覆盖时同 hash 同文件)

安全建议

风险 措施
ASR / TTS 接口被外部探测 / 占用 仅监听内网 IP;外网入口加 nginx + basic auth / mTLS
MySQL 弱口令 改强口令;只允许 application host 访问
FS ESL 暴露公网 inbound ESL 8021 必须严禁公网;用 VPN / 内网
POST /outbound-calls 滥用 加 API key / IP 白名单(nginx 层)
TLS 自签证书 内网部署可接受;公网部署必须正规证书

下一步