外观
配置参考
配置
config.json 字段:
json
{
"esl-server": {
"host": "0.0.0.0",
"port": 9911,
"commandTimeoutMs": 15000,
"asrTimeoutMs": 30000,
"settleDelayMs": 1000
},
"logging": {
"dir": "./logs",
"level": "info",
"maxSize": "20m",
"maxFiles": "14d"
},
"http-server": {
"host": "0.0.0.0",
"port": 9912,
"authToken": ["esl-0x21"]
},
"freeswitch": {
"host": "192.168.2.184",
"port": 8021,
"password": "ClueCon",
"callbackHost": "192.168.2.246",
"callbackPort": 9911,
"originateDialStringTemplate": "user/{{destinationNumber}}"
},
"audioFork": {
"wsUrl": "ws://192.168.2.246:10096/audio",
"bugName": "callflow_asr",
"mixType": "mono",
"sampleRate": "16k",
"bidirectionalAudioEnabled": false,
"bidirectionalAudioStreamEnabled": false,
"bidirectionalAudioStreamSampleRate": 16000,
"connectTimeoutMs": 5000,
"eventSubscriptionMode": "all"
},
"tts": {
"defaults": {
"speakerId": 0,
"speed": 1,
"requestTimeoutMs": 10000
},
"use": {
"call": "shout",
"conference": "wav"
},
"profiles": {
"wav": {
"endpoint": "http://127.0.0.1:9080/tts",
"playbackTarget": "wav-url",
"fsPlaybackBaseDir": ""
},
"shout": {
"endpoint": "http://127.0.0.1:9080/tts-stream",
"playbackPrefix": "shout://"
}
}
},
"businessConfig": {
"ollama-chat-business": {
"endpoint": "http://127.0.0.1:11434/api/chat",
"model": "qwen3.5:2b",
"requestTimeoutMs": 60000
},
"kb-audio-chat-business": {
"endpoint": "http://127.0.0.1:9931/api/v1/conversation",
"strategy": "kb-mock",
"token": "chat-token",
"requestTimeoutMs": 10000
}
},
"recording": {
"directory": "/usr/local/freeswitch/record"
},
"callout": {
"calloutServer": {
"baseUrl": "http://127.0.0.1:9920",
"token": "callout-token",
"requestTimeoutMs": 10000
},
"nlu": {
"baseUrl": "http://127.0.0.1:9930",
"token": "nlu-token",
"requestTimeoutMs": 30000
},
"chat": {
"baseUrl": "http://127.0.0.1:9931",
"token": "chat-token",
"requestTimeoutMs": 60000
}
},
"db": {
"url": "postgres://postgres:postgres@localhost:5432/freeswitch"
},
"redis": {
"host": "127.0.0.1",
"port": 6379,
"username": "default",
"password": "redis",
"db": 0,
"keyPrefix": "callflow",
"ttlMs": 600000
}
}esl-server
host/port:ESL outbound 监听地址与端口commandTimeoutMs:ESL 命令等待 reply 的超时asrTimeoutMs:单轮 hear 的默认等待超时(业务可在hear()入参覆盖)settleDelayMs:手动answer后建议的等待,给信令稳定
http-server
host/port:HTTP 监听地址,承载/outbound-calls与运行时配置端点authToken:HTTP 接口共享令牌数组。未配置或为空时不启用鉴权;配置一个或多个 非空值时,请求必须在token请求头中携带其中一个匹配值,否则返回 401
freeswitch
host/port/password:inbound ESL(用于 originate)callbackHost/callbackPort:FreeSWITCH 在外呼接通后回拨当前 ESL 服务 使用的地址,必须可以从 FreeSWITCH 进程访问到originateDialStringTemplate:所有外呼场景的默认拨号串模板,必须包含占位符;业务可在调用入参中传dialStringTemplate覆盖(同样需包含占位符)
audioFork
wsUrl:mod_audio_fork 要连接的 ASR WebSocket 地址(即sherpa-asr-online-server)bugName:media bug 名称,用于uuid_audio_fork stop精确定位mixType/sampleRate:上行音频通道与采样率,mono/16k适合大多数 ASRbidirectionalAudioEnabled/bidirectionalAudioStreamEnabled:下行音频通 道,hear-only 模式保持关闭connectTimeoutMs:等待 WebSocket 连接成功事件的超时eventSubscriptionMode:ESL 事件订阅策略"all":event plain ALL,再在应用侧按 UUID 过滤;最稳但高并发下 事件量较大"channel-plus-custom":myevents+ CUSTOM,保留当前通道基础事件并额外 订阅 audio_fork / conference 相关 CUSTOM 事件
tts
采用 defaults / use / profiles 三段结构:defaults 是业务未指定时的合成默认值 (speakerId / speed / requestTimeoutMs);use.call / use.conference 分别选择 单呼与会议使用的 profile("wav" 或 "shout");profiles.wav.endpoint 对应 sherpa-tts-server 的 POST /tts,profiles.shout.endpoint 对应 POST /tts-stream, profiles.shout.playbackPrefix 在启用 mod_shout 时通常为 "shout://"。 逐字段说明与播放目标映射(wav-url / file-path)见 TTS 对接。
businessConfig
按 registry / 数据库中的稳定业务编码保存各业务的文件层默认配置。容器和每个子项都必须是 JSON 对象;出现未注册业务编码会在启动期直接报错,避免拼写错误被静默忽略。
ollama-chat-business 子项包含:
endpoint:完整 OllamaPOST /api/chat地址model:单阶段流式对话模型名称requestTimeoutMs:单轮请求超时(正整数毫秒)
该配置为必填项并在进程启动期校验。字段缺失、URL 非法或不是 /api/chat、模型为空、 超时非正整数时进程直接退出,不会静默回退到 localhost。启动日志 esl_server_started 会记录实际 endpoint、model 和 timeout。
ollama-chat-business 还支持数据库覆盖,call_businesses.businessConfig 与 call_business_number_mappings.mappingConfig 直接填写上述三个字段,不额外包业务编码。 最终配置按 config.json.businessConfig["ollama-chat-business"] < call_businesses.businessConfig < call_business_number_mappings.mappingConfig 深合并:普通对象递归合并,数组、标量和 null 由高层整体覆盖。显式 business_code 路由不会读取号码映射层。最终值无效时记录 business_config_invalid、播放“系统错误”并结束,且不会请求 Ollama。
kb-audio-chat-business 子项可省略;一旦填写,endpoint、strategy 和正整数 requestTimeoutMs 必须有效,token 可选且不会写入启动日志。路由命中该业务时仍会 对三层合并结果再次校验;若文件层缺省且数据库层不能补齐,通话按 business_config_invalid 结束,不发送知识库请求。
recording
directory:FreeSWITCH 进程可写的录音目录ctx.startRecording()只返回 FreeSWITCH 落盘路径filePath和短文件名fileName;完整播放 URL 由调用方媒体配置拼接
callout
外部依赖按 calloutServer、nlu、chat 三个服务边界配置。每组统一包含:
baseUrl:服务基地址,只允许 HTTP(S),可带反向代理路径前缀;启动时去除尾斜杠, 不允许用户名、密码、query 或 fragmenttoken:该服务独立共享令牌;非空时请求携带X-Callout-Internal-Token,为空则不发requestTimeoutMs:该服务独立的正整数请求超时
API 路径由代码固定维护,不再写入配置。callout-server 使用 /api/call-results、 /api/call-progress、/api/transfers/route、/api/transfers/end 和 /api/v1/scripts/{id}/runtime;NLU 使用 /api/v1/nlu;Chat 使用 /api/v1/chat/stream。三个服务之间不会回退或混用 token、超时。
旧版 resultCallbackEndpoint、nluEndpoint、chatEndpoint 等扁平字段不再兼容, 启动时会给出迁移错误。示例 token 仅用于本地联调;生产环境必须逐服务替换为高强度凭证, 并限制配置文件读取权限。
db
url:PostgreSQL 连接串(当前配置只使用该字段)。业务路由会查call_businesses与call_business_number_mappings,schema 见src/db/schema.ts
redis
Redis 跨实例协调配置,是 callflow-esl 的必选依赖:会议协调、坐席实时盯屏 会话注册表、运行时配置重载广播都建立在它之上。缺配置或启动时连不上会阻止服务启动 (进程以非零码退出,交给 systemd/k8s 重启),不再有进程内 Map 降级模式:
host/port/username/password/db:连接参数keyPrefix:会议运行态、实例心跳、盯屏会话、reload 频道等 key/channel 的统一前缀ttlMs:会议运行态、实例心跳、盯屏会话等 key 的 TTL(毫秒)