跳到正文

配置参考

配置

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": {
    "llm-chat-business": {
      "endpoint": "http://127.0.0.1:8000/v1/chat/completions",
      "apiKey": "",
      "model": "qwen3.5:2b",
      "requestTimeoutMs": 60000
    },
    "kb-audio-chat-business": {
      "endpoint": "http://127.0.0.1:9930/api/v1/conversation",
      "strategy": "kb-mock",
      "token": "chat-token",
      "requestTimeoutMs": 10000
    },
    "verification-code-business": {
      "endpoint": "https://app.yuntl.cc/push_sms",
      "requestTimeoutMs": 5000,
      "maxAttempts": 3
    }
  },
  "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:9930",
      "token": "chat-token",
      "requestTimeoutMs": 60000
    }
  },
  "db": {
    "url": "postgres://postgres:postgres@localhost:5432/freeswitch"
  },
  "redis": {
    "url": "redis://default:redis@127.0.0.1:6379/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 适合大多数 ASR
  • bidirectionalAudioEnabled / 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 /ttsprofiles.shout.endpoint 对应 POST /tts-streamprofiles.shout.playbackPrefix 在启用 mod_shout 时通常为 "shout://"。 逐字段说明与播放目标映射(wav-url / file-path)见 TTS 对接

businessConfig

按 registry / 数据库中的稳定业务编码保存各业务的文件层默认配置。容器和每个子项都必须是 JSON 对象;出现未注册业务编码会在启动期直接报错,避免拼写错误被静默忽略。

llm-chat-business 子项为可选项,包含:

  • endpoint:完整 OpenAI POST /v1/chat/completions 地址(GPUStack 部署模型的对外协议)
  • apiKey:可选模型鉴权 Key;非空时写入 Authorization: Bearer <key>
  • model:单阶段流式对话模型名称(GPUStack 注册的模型名)
  • requestTimeoutMs:单轮请求超时(正整数毫秒)

若在配置文件中填写,启动期会严格校验 URL、模型和超时格式(非法或不是 /v1/chat/completions 时报错退出); 若配置文件中未填写,启动期允许缺省。llm-chat-business 还支持数据库覆盖,call_businesses.businessConfigcall_business_number_mappings.mappingConfig 直接填写上述字段。最终配置按 config.json.businessConfig["llm-chat-business"] < call_businesses.businessConfig < call_business_number_mappings.mappingConfig 深合并:普通对象递归合并,数组、标量和 null 由高层整体覆盖。显式 business_code 路由不会读取号码映射层。若三层合并后最终值仍无效,通话记录 business_config_invalid、播放“系统错误”并结束,且不会请求模型。

kb-audio-chat-business 子项可省略;一旦填写,endpointstrategy 和正整数 requestTimeoutMs 必须有效,token 可选且不会写入启动日志。路由命中该业务时仍会 对三层合并结果再次校验;若文件层缺省且数据库层不能补齐,通话按 business_config_invalid 结束,不发送知识库请求。

verification-code-business 子项为可选项,用于验证码识别结果外部 HTTP 表单上报与防重复呼叫拦截:

  • endpoint:必填,合法 HTTP(S) URL 接口地址
  • requestTimeoutMs:可选单次上报请求超时(正整数毫秒,缺省 5000)
  • maxAttempts:可选最大尝试次数包含首次(正整数,缺省 3)
  • antiDuplicate:可选防重复呼叫拦截配置:
    • enabled:可选布尔值,是否启用防重拦截(缺省 true)
    • windowSeconds:可选正整数秒,滑动时间窗口大小(缺省 60)
    • maxCalls:可选正整数次,时间窗口内最大允许呼叫数(缺省 1)

若未在配置中指定 endpoint,业务在通话挂机后会跳过上报并记录日志,不影响正常识别打印与挂机收尾。 若触发防重复呼叫拦截,通话在接通前直接挂机释放(NORMAL_CLEARING),不启动录音、识别与上报。

recording

  • directory:FreeSWITCH 进程可写的录音目录
  • ctx.startRecording() 只返回 FreeSWITCH 落盘路径 filePath 和短文件名 fileName;完整播放 URL 由调用方媒体配置拼接

callout

外部依赖按 calloutServernluchat 三个服务边界配置,为选配(Optional); 未接入 callout-servercallai-server 时可整体缺省。nluchat 在当前部署里都指向 同一个 callai-server(默认 9930),但仍作为两组独立配置维护,便于分别设置超时与令牌。 若配置,每组统一包含:

  • baseUrl:服务基地址,只允许 HTTP(S),可带反向代理路径前缀;启动时去除尾斜杠, 不允许用户名、密码、query 或 fragment
  • token:该服务独立共享令牌;非空时请求携带 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、超时。

示例 token 仅用于本地联调;生产环境必须逐服务替换为高强度凭证,并限制配置文件读取权限。

db

  • url:PostgreSQL 连接串(当前配置只使用该字段)。业务路由会查 call_businessescall_business_number_mappings,schema 见 src/db/schema.ts

redis

Redis 跨实例协调配置,是 callflow-esl 的必选依赖:会议协调、坐席实时盯屏 会话注册表、运行时配置重载广播都建立在它之上。缺配置或启动时连不上会阻止服务启动 (进程以非零码退出,交给 systemd/k8s 重启):

  • url:Redis 连接 URL,仅支持 redis: / rediss: 协议,例如 redis://default:redis@127.0.0.1:6379/0
  • keyPrefix:会议运行态、实例心跳、盯屏会话、reload 频道等 key/channel 的统一前缀
  • ttlMs:会议运行态、实例心跳、盯屏会话等 key 的 TTL(毫秒)

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