目标
从零开始,在一台机器上把 4 个服务全部拉起,拨一通电话验证:用户说话能识别到文本、能听到 TTS 合成的应答。
预计耗时:首次 30 ~ 60 分钟(含模型加载与 FreeSWITCH 安装),熟练后 5 分钟。
环境前提
| 项 | 要求 |
|---|---|
| OS | Windows 10/11(推荐 ASR/TTS 服务) + Linux(推荐 FreeSWITCH 服务) |
| CPU | x64,4 核以上 |
| 内存 | 8GB+(模型加载约 1~2GB) |
| 工具 | Visual Studio 2022(含 C++ 工作负载)、CMake、Bun 1.x、PostgreSQL、FreeSWITCH 1.10.x |
| 网络 | 各服务之间能互通对应端口 |
本例为单机部署,全部跑在同一台机器。FS 部署在 Linux + ASR/TTS 部署在 Windows 的常见拓扑见 部署。
Step 1 — 安装 FreeSWITCH + mod_audio_fork
1.1 装 FreeSWITCH
参考 FreeSWITCH 官方文档,本项目验证过 Debian 11 / CentOS 7。装好后能 fs_cli 进 FreeSWITCH 终端。
1.2 编译 mod_audio_fork
1 | git clone https://github.com/Wangijun/mod_audio_fork.git |
完成后 mod_audio_fork.so 会安装到 FS 的 mod 目录。
1.3 启用模块
编辑 conf/autoload_configs/modules.conf.xml:
1 | <load module="mod_audio_fork"/> |
或运行时:
1 | fs_cli -x "load mod_audio_fork" |
验证:
1 | fs_cli -x "module_exists mod_audio_fork" |
返回 true 即成功。
Step 2 — 启动 ASR 服务
2.1 构建
1 | cd C:\path\to\ai-voice-platform\onnx-platform\sherpa-asr-online-server |
2.2 检查配置
打开 target\win_x64\config.json,确认:
1 | { |
模型路径默认相对解析到 ../models/,无需改。
2.3 启动
1 | cd target\win_x64 |
启动成功日志:
1 | [sherpa_asr_online_server] listening on 0.0.0.0:10096 ... |
2.4 验证健康检查
新开一个终端:
1 | curl http://127.0.0.1:10096/health |
返回:
1 | { "ok": true, "service": "sherpa-asr-online-server", "activeSessions": 0, ... } |
Step 3 — 启动 TTS 服务
3.1 构建
1 | cd C:\path\to\ai-voice-platform\onnx-platform\sherpa-tts-server |
3.2 检查配置
打开 target\win_x64\config.json:
1 | { |
注意
publicBaseUrl 必须填 FreeSWITCH 能访问到的地址,不要用 127.0.0.1(除非 FS 与 TTS 同机)。
3.3 启动
1 | cd target\win_x64 |
启动成功日志:
1 | [sherpa_tts_server] loaded TTS worker in 1234 ms |
3.4 验证合成
1 | curl -s -X POST http://127.0.0.1:9080/tts \ |
返回:
1 | { "wavUrl": "http://...:9080/wav/tts-xxx.wav", "fileName": "...", "sampleRate": 16000, "cached": false } |
浏览器打开 wavUrl 能直接播放即正常。
Step 4 — 启动 PostgreSQL + callflow-esl
4.1 准备 PostgreSQL
1 | CREATE DATABASE freeswitch; |
记下连接串:postgres://postgres:postgres@127.0.0.1:5432/freeswitch
4.2 安装依赖与初始化 schema
1 | cd C:\path\to\ai-voice-platform |
打开 apps/callflow-esl/config.json,按你的环境改:
1 | { |
初始化 schema:
1 | cd apps/callflow-esl |
4.3 插入一条测试业务路由
callflow-esl 启动时会把代码里的 15 个业务自动同步到callflow.call_businesses。如果要用被叫号码 1000 命中默认回显业务,可在
PostgreSQL 执行:
1 | INSERT INTO callflow.call_business_number_mappings |
4.4 启动服务
ASR / TTS 已在前面单独起好,这里只起 callflow-esl:
1 | bun run dev:callflow-esl |
仓库根目录的
bun run dev会一次并发启动全部 8 个服务(asr / tts / emotion 三个 C++ 服务
- callflow-esl / callflow-server / callflow-webpage / callout-server / callout-webpage,其中三个
C++ 服务必须已build.ps1构建好)。本快速开始只验证最小通话链路,故按服务单独启动。
启动日志:
1 | [callflow-esl] ESL TCP listening on 0.0.0.0:9911 |
Step 5 — 配置 FreeSWITCH dialplan
编辑 conf/dialplan/default.xml(或自己挂一段):
1 | <extension name="route-to-callflow"> |
重载:
1 | fs_cli -x "reloadxml" |
Step 6 — 拨打第一通电话
用任意 SIP 客户端(如 Zoiper、MicroSIP)注册到 FreeSWITCH,拨号 1000。
观察 callflow-esl 控制台:
1 | [callflow-esl] outbound session uuid=... |
接通后说一段话(中文/英文都行),ASR 服务会返回 partial / final 文本,callflow-esl 会用 TTS 把你说的话回放回来(这是 default-call-business 的行为:echo 业务)。
ASR 服务控制台会看到:
1 | [sherpa_asr_online_server] ws-1 websocket session started on worker=0 |
TTS 服务控制台:
1 | [sherpa_tts_server] generated public/wav/tts-xxx.wav in 234 ms (rtf=0.45) |
第一通电话成功后
恭喜,端到端链路打通了。下一步:
- 想看更多业务范式 → 业务开发指南
- 想看典型应用场景 → 典型场景
- 想要 Web 后台看数据 / 配号码路由 / 试听 TTS 音色 → 管理控制台
- 想批量自动外呼 → 智能外呼
- 想做生产部署 → 部署拓扑
- 出错了 → FAQ
常见拉起问题速查
| 现象 | 排查方向 |
|---|---|
| FS 拨号没反应 | dialplan socket IP/端口是否正确;callflow-esl 是否监听 0.0.0.0 |
| outbound 连进来立刻断 | 看 callflow-esl 日志业务路由是否失败(无 business_code 也无号码映射) |
| 接通但没声音 | playbackTarget=wav-url 时检查 FS 能否 HTTP 访问 publicBaseUrl |
| ASR partial 全是乱码 | 检查 audioFork 配置 mixType=mono sampleRate=16k,与 ASR 服务一致 |
| ASR 一直没 final | audioFork.eventSubscriptionMode 改 "all";看 ASR 端日志是否发出 final |
| TTS 失败 503 | maxQueuedRequests 太低,或者 ttsPoolSize 不够 |
| PostgreSQL 连不上 | db.url、账号密码、数据库名是否对得上 |
更完整的排查表在 FAQ。