按”现象 → 根因 → 处理”组织,覆盖部署、识别、合成、外呼几类高频问题。
部署 / 拉起
Q: callflow-esl 连不上 FreeSWITCH(ECONNREFUSED)
现象:启动日志报 inbound ESL connect failed。
根因:
freeswitch.host/port/password不对- FS 的
event_socket.conf.xml没监听0.0.0.0或绑了内网 IP apply-inbound-acl限制了来源 IP
处理:
1 | # 在 callflow-esl 所在机器测试 |
确认端口可达、密码正确、ACL 允许。
Q: FS 拨号没反应,看不到 callflow-esl 收到 outbound
根因:
- dialplan socket 地址不对
- callflow-esl 监听
127.0.0.1,FS 不在同机 - 防火墙拦 9911
处理:
1 | # 在 FS 机器测试 |
确认 dialplan socket 用 callflow-esl 实际 IP,且 callflow-esl server.host: "0.0.0.0"。
Q: outbound 连进来但立刻断
根因:业务路由失败。
- channel variable
biz_id没设,且destination_number在call_business_number_mappings里查不到 business_name在business-registry里没注册
处理:
看 callflow-esl 日志 route business= 行;进 MySQL 确认表里有对应记录;确认 src/runtime/business-registry.ts 已 export 业务函数。
识别(ASR)
Q: 接通后没声音 + ASR 也没 transcription
根因:
audioFork.wsUrl不对,FS 连不到 ASR 服务- ASR 服务没启动 / 健康检查失败
- 子协议不匹配
处理:
1 | # 在 FS 机器测试 ASR 可达 |
如果手动 start 报 connect_failed,看 ASR 服务日志是否拒绝握手。
Q: ASR 持续 partial,但没有 final
根因:
- VAD 阈值太低,背景噪声当作”还在说话”
- 上游一直发音频帧,没有触发 endpoint
endpointRuleN配置过于宽松
处理:
打开调试:
1 | { |
观察 speechActive=true 持续多久;若一直 true,调高 vadMinSilenceDuration 或 vadThreshold。
业务侧也可主动 flush:发 0 长度二进制帧,或挂机自动 flush。
Q: ASR partial 全是乱码 / 字错率极高
最常见根因:采样率不匹配。
处理:
- 确认 FS 发的是 16kHz(
audioFork.sampleRate: "16k") - 确认 ASR 服务
sampleRate: 16000 - 录音对比:
recordAudioEnabled: true后听 ASR 端落盘的 wav,再用sherpa-demo/demo_online_asr.exe离线复现 - 如果 demo 也错,是模型 / 输入问题;如果 demo 对、服务错,是采样率 / 帧顺序问题
Q: mod_audio_fork::transcription 事件收不到
根因:FreeSWITCH 默认按 event plain CUSTOM mod_audio_fork::transcription 订阅,在某些 FS 版本下不稳定。
处理:在 callflow-esl config.json:
1 | { |
"all" 是当前推荐的、唯一稳定下发 transcription 的策略。
合成(TTS)
Q: speak 后用户没听到声音 / FS 报 playback 404
根因:FS 拉不到 wav URL。
处理:
1 | # 在 FS 机器测试 TTS wav 可达 |
如果 404 / connect refused:
- 检查
sherpa-tts-server/config.json的publicBaseUrl是否填了FS 能访问的地址(不是 127.0.0.1) - 检查防火墙 9080 是否对 FS 开放
- 检查
listenHost是否0.0.0.0
Q: TTS 503 Server busy
根因:等待队列已满。
处理:
- 增加
workerThreads处理 HTTP 速度 - 增加
ttsPoolSize并行合成数 - 增加
maxQueuedRequests(默认 0 不限,如果手动配过限制,调大) - 检查是否有”循环合成同一段长文本”的业务 bug
Q: TTS 同一句话每次都重新合成(不命中缓存)
根因:缓存 key 是 text + speakerId + speed 的 FNV-1a 哈希。如果业务每次传的 text 有微小差异(带时间戳、加随机标记),缓存就不命中。
处理:业务侧把文本规范化(去掉时间戳/请求 ID);或针对动态文本的业务,接受不命中。
Q: TTS RTF 偏高(合成时间 > 实时时间)
根因:单线程 CPU 推理在小机器上偏慢。
处理:
- 在 sherpa-tts-server / sherpa-asr-online-server 的
numThreads改为 2 或 4,重新构建 - 升级机器
- 或缩短业务里 TTS 文本长度
外呼
Q: POST /outbound-calls 返回 ok 但电话没拨出去
根因:
- inbound ESL 的 originate 在 FS 端失败
originateDialStringTemplate不对(gateway / user 配置问题)- 主叫号码不被 SIP trunk 接受
处理:
1 | # 看 FS 日志 |
Q: 接通后 callflow-esl 收不到 B leg outbound 连接
根因:callbackHost 不可达。
处理:
- 在 FS 机器 telnet 测试
<callbackHost>:9911 - 不通就检查防火墙 / 网络
- 不要写
127.0.0.1(除非同机)
Q: originateWithRingbackDetection 经常误判
根因:
- 运营商提示音被 ASR 识别成了别的文本
- 没有 ringback / early-media,业务在 ringing 阶段拿不到音频
处理:
- 业务里降低对
carrierPromptKind的强依赖,把detectedText拿出来做关键词正则匹配 - 在 dialplan 里启用
ringback:<action application="set" data="ringback=${us-ring}"/>
中文与编码
Q: PowerShell 终端中文 ASR 输出乱码
1 | chcp 65001 |
Q: 业务里中文文本经过 ESL 后变成 ?
根因:channel variable 在 FS 内部默认是 latin-1,复杂字符可能被吞。
处理:
- 业务里直接用 TS 字符串 +
ctx.speak({ kind: "tts", text }),不要把中文写入 channel variable 再读出来 - 必须用 channel variable 传中文时,base64 编码后传
模型 / 性能
Q: 服务启动报 missing TTS model file: ... 或 Failed to create OnlineRecognizer
根因:模型路径不对,或文件缺失。
处理:
- 看日志打印的绝对路径,进文件系统确认存在
- 用
sherpa-onnx/win_x64/bin/sherpa-onnx-version.exe验证 sherpa-onnx 本体完整 - 用
sherpa-demo的对应 demo 验证模型本身能跑
Q: ASR / TTS 服务启动后内存占用很高
根因:每个 sessionPoolSize / ttsPoolSize 都会预热一个独立的模型实例,约 600MB-800MB 每个。
处理:
- 业务并发量不大时把池大小调小(比如
ttsPoolSize: 1) - 不必要的预热可以关掉(注意启动后第一次请求会冷启动慢)
Q: FS 跟 ASR 之间的 WebSocket 频繁断连
根因:
- 网络抖动 / NAT 超时
- 单连接持续时间过长(超过 NAT keepalive)
- FS 端没设 keep-alive
处理:
- 业务侧不要在一通通话里反复 start / stop audio_fork;用
callHear整通保持 - 中间设备如果有 idle timeout,业务定期发 ping 帧
- 内网部署优先,减少经过的中间设备
数据库
Q: MySQL 连不上 / 表不存在
处理:
1 | # 1. 测连接 |
Q: 业务路由偶尔失败,但 MySQL 表里有记录
根因:destination_number 字符串匹配,前后空格 / + 号不一致。
处理:业务侧或路由层做规范化(去空格、去 +86)。
调试组合
排查端到端识别延迟:
1 | 1. callflow-esl 日志:speak 完成时间 / hear 启动时间 |
排查”接通后没反应”:
1 | 1. callflow-esl 日志看是否走到 ctx.execute("answer") |
没列出来的问题
去看仓库内对应 README 的 “Notes” / “Troubleshooting” 章节,那里通常有更细节的处理思路。也欢迎提 issue 反馈。