总览

平台各组件的配置文件与环境变量统一汇总在这里。

组件 配置来源 说明
callflow-esl apps/callflow-esl/config.json ESL + HTTP + audioFork + tts + db
sherpa-asr-online-server onnx-platform/sherpa-asr-online-server/config.json WS + ASR + VAD
sherpa-tts-server onnx-platform/sherpa-tts-server/config.json HTTP + TTS pool(默认 vits-zh-ll,可切 matcha/vits/kokoro)
aliyun-speech-gateway apps/aliyun-speech-gateway/config.json + ALIYUN_NLS_* 环境变量 可选阿里云 NLS ASR/TTS 兼容网关
azure-speech-gateway apps/azure-speech-gateway/config.json + AZURE_SPEECH_* 环境变量 可选 Azure Speech ASR/TTS 兼容网关(支持独立可执行文件)
emotion-analysis-server onnx-platform/emotion-analysis-server/config.json HTTP + 文本/音频情绪模型目录
callout-server apps/callout-server/config.json + CALLOUT_* 环境变量 server + 鉴权 + 调度 + 策略 + 外部API + freeswitch + redis + db(+ 回铃检测 / 情绪分析)
callflow-server 环境变量(无 config.json) 管理台 API + 数据库连接
callflow-webpage / callout-webpage VITE_* 环境变量 前端连后端的 API 地址
mod_audio_fork 环境变量 + channel variable 运行时
FreeSWITCH conf/dialplan/*.xml 信令 + 路由

callflow-esl config.json

完整结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
{
"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
},
"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://"
}
}
},
"recording": {
"directory": "/usr/local/freeswitch/record",
"publicBaseUrl": ""
},
"callout": {
"resultCallbackEndpoint": "http://127.0.0.1:9920/api/call-results",
"resultCallbackToken": "",
"resultCallbackTimeoutMs": 40000,
"agentRouteEndpoint": "http://127.0.0.1:9920/api/transfers/route"
},
"redis": {
"enabled": true,
"host": "127.0.0.1",
"port": 6379,
"db": 0,
"keyPrefix": "callflow",
"ttlMs": 300000
},
"db": {
"url": "postgres://postgres:postgres@localhost:5432/freeswitch"
}
}

esl-server

字段 说明
host / port ESL outbound 监听地址与端口
commandTimeoutMs ESL 命令等待 reply 的超时
asrTimeoutMs 单轮 hear() 默认超时(业务可在入参覆盖)
settleDelayMs 手动 answer 后建议的等待,给信令稳定

http-server

字段 说明
host / port HTTP 监听地址,承载 /outbound-calls

freeswitch

字段 说明
host / port / password inbound ESL(用于 originate)
callbackHost / callbackPort FreeSWITCH 在外呼接通后回拨当前 ESL 服务使用的地址,必须 FS 进程可达
originateDialStringTemplate 所有外呼场景的默认拨号串模板,必须含 {{destinationNumber}}

audioFork

字段 说明
wsUrl mod_audio_fork 要连接的 ASR WebSocket 地址
bugName media bug 名称,用于 uuid_audio_fork stop 精确定位
mixType / sampleRate 上行音频通道与采样率;mono/16k 适合大多数 ASR
bidirectionalAudioEnabled / bidirectionalAudioStreamEnabled 下行音频通道;hear-only 模式保持关闭
bidirectionalAudioStreamSampleRate 下行音频流采样率
connectTimeoutMs 等待 WebSocket 连接成功事件的超时
eventSubscriptionMode ESL 事件订阅策略:"all"(推荐)/ "custom-subclass" / "channel-plus-custom"

tts

TTS 采用 defaults + use + profiles 三段结构。流式与否不再由单独开关控制,
而是由 use.call / use.conference 选择走哪个 profile("shout" = 流式 MP3,
"wav" = 整段 wav)。

字段 说明
defaults.speakerId / defaults.speed ctx.speak({kind:"tts"}) 未指定时的默认音色与语速
defaults.requestTimeoutMs 请求 sherpa-tts-server 的 HTTP 超时(含 /tts/tts-stream link)
use.call 普通通话场景使用的 profile 名("shout""wav"
use.conference 会议场景使用的 profile 名(会议播报通常走 "wav",避免 mod_shout 与会议混音冲突)
profiles.wav.endpoint sherpa-tts-server 的 POST /tts 地址(整段 wav)
profiles.wav.playbackTarget "wav-url"(默认,让 FS 直接拉 wav URL)或 "file-path"(先落 FS 本地再播)
profiles.wav.fsPlaybackBaseDir playbackTarget=file-path 时使用的目录前缀;为空且选 file-path 会报错
profiles.shout.endpoint sherpa-tts-server 的 POST /tts-stream 地址(流式 MP3 link)
profiles.shout.playbackPrefix 流式链接交给 FreeSWITCH playback 前追加的前缀,已启用 mod_shout 时为 "shout://"

旧版扁平字段 sherpaHttpEndpoint / sherpaStreamEndpoint / streamingEnabled /
streamPlaybackPrefix / playbackTarget 已移除,迁移时改写为上面的 profiles 结构。

recording

字段 说明
directory FreeSWITCH 进程可写的录音目录
publicBaseUrl 可选公开访问前缀;为空时 ctx.startRecording() 返回 fileUrl=null

callout

智能外呼 服务对接的回写 / 转人工集成,供 callout-platform-demo-business
及 AI 转人工业务使用:

字段 说明
resultCallbackEndpoint callout-server 的 POST /api/call-results 地址,业务回写通话 / 业务结果
resultCallbackToken 与 callout-server internalApi.callResultToken 对应的共享令牌,非空时回写 / 路由请求带 X-Callout-Internal-Token
resultCallbackTimeoutMs 回写 / 路由请求的客户端超时(毫秒)
agentRouteEndpoint callout-server 的 POST /api/transfers/route 地址,AI 通话转人工时请求空闲坐席入会;详见 转人工与坐席

redis

跨 callflow-esl 实例的会议状态协调(conference-coordinator.ts 基于 Redis Pub/Sub)。
单实例部署可 enabled=false,协调器自动降级为 no-op;多实例部署必须启用
否则跨实例的会议 audio_fork 同步、playback 抢占停止、成员状态广播会失效。
详见 转人工与坐席

字段 说明
enabled 是否启用 Redis 协调层;false 时所有跨实例协调降级为 no-op
host / port / db Redis 连接信息
keyPrefix 协调层 Hash / Pub/Sub channel 的键前缀
ttlMs 会议成员 / 监听者 / playback 运行态在 Redis 中的 TTL

db

PostgreSQL 连接信息。当前 Drizzle schema 使用 callflow schema:
callflow.call_businessescallflow.call_business_number_mappings
callflow.callflow_runtime_configs,定义见 apps/callflow-esl/src/db/schema.ts


sherpa-asr-online-server config.json

config.json 按域分组:server / concurrency / socket / logging /
recording / asr / vad(与仓库 onnx-platform/sherpa-asr-online-server/README.md
ASR 服务 一致)。下表只列关键字段与默认值,完整字段表见 ASR 服务

1
2
3
4
5
6
7
8
9
{
"server": { "host": "127.0.0.1", "port": 10096, "healthPath": "/health", "wsPath": "/audio", "wsSubprotocol": "audio.drachtio.org" },
"concurrency": { "maxSessions": 16, "ioWorkers": "CPU 核心数", "sessionPoolSize": 16, "numThreads": 1, "acceptBacklog": "SOMAXCONN", "workerPollTimeoutMs": 10 },
"socket": { "tcpNoDelay": true, "maxFrameBytes": 4194304, "readBufferBytes": 65536, "writeBufferBytes": 65536, "recvBufferBytes": 262144, "sendBufferBytes": 262144 },
"logging": { "dir": "logs", "debugTextFrames": false, "debugAudioFrames": false, "debugRecognitionState": false },
"recording": { "enabled": false, "dir": "recordings" },
"asr": { "activeModel": "sherpa-onnx-streaming-zipformer-zh-int8-2025-06-30", "models": { "…": "…" }, "provider": "cpu", "sampleRate": 16000, "sendPartialResults": true, "partialMinIntervalMs": 300, "decodeBatchMs": 80 },
"vad": { "model": "silero_vad.onnx", "threshold": 0.5, "minSilenceDuration": 0.5, "minSpeechDuration": 0.25, "windowSize": 512, "maxSpeechDuration": 20.0 }
}
分组 关键字段 说明
server host / port / healthPath / wsPath / wsSubprotocol 监听与 WebSocket 升级路径;wsSubprotocol 空则不强制
concurrency maxSessions / ioWorkers / sessionPoolSize / numThreads 并发会话上限、I/O worker、预热 session、ONNX 推理线程
socket maxFrameBytes / recvBufferBytes / sendBufferBytes 帧大小上限(超即 1002)、SO_RCVBUF / SO_SNDBUF(0=不调整)
logging debugTextFrames / debugAudioFrames / debugRecognitionState 三档调试日志开关(高吞吐慎开 debugAudioFrames
recording enabled / dir 上行音频录制开关与目录(相对配置文件所在目录解析)
asr activeModel / models / provider / sampleRate / sendPartialResults 模型 profile 选择与识别参数,详见下文
vad model / threshold / minSilenceDuration / maxSpeechDuration silero-vad 参数;强制启用,无开关

asr — 模型选择

ASR 模型采用 asr.activeModel + asr.models profile 表结构:在 asr.models
声明多个模型 profile,用 asr.activeModel 指定当前加载哪一个。切换模型只改
asr.activeModel,无需改动各 profile 的文件路径。每个 profile 含 modelDir /
encoder / decoder / joiner / tokens / bpeVocab? / modelType / modelingUnit
modelDir 相对仓库 onnx-platform/models/ 解析,绝对路径原样使用。

默认配置声明两个 profile(中文 int8 流式 zipformer 为默认、中英双语):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
"asr": {
"activeModel": "sherpa-onnx-streaming-zipformer-zh-int8-2025-06-30",
"models": {
"sherpa-onnx-streaming-zipformer-zh-int8-2025-06-30": {
"modelDir": "sherpa-onnx-streaming-zipformer-zh-int8-2025-06-30",
"encoder": "encoder.int8.onnx",
"decoder": "decoder.onnx",
"joiner": "joiner.int8.onnx",
"tokens": "tokens.txt",
"modelType": "",
"modelingUnit": "cjkchar"
},
"sherpa-onnx-streaming-zipformer-bilingual-zh-en": {
"modelDir": "sherpa-onnx-streaming-zipformer-bilingual-zh-en",
"encoder": "encoder-epoch-99-avg-1.onnx",
"decoder": "decoder-epoch-99-avg-1.onnx",
"joiner": "joiner-epoch-99-avg-1.onnx",
"tokens": "tokens.txt",
"modelType": "zipformer",
"modelingUnit": "cjkchar"
}
}
}
}

vad — 强制启用,无开关

VAD 强制启用,没有 enableVad 开关;endpoint 检测走 sherpa 默认,不在配置中暴露
enableEndpoint / endpointRule* 字段

旧版扁平顶层字段 listenHost / listenPort / maxSessions / ioWorkers / maxFrameBytes /
socketRecvBufferBytes / socketSendBufferBytes / debugLogTextFrames /
debugLogAudioFrames / debugLogRecognitionState / recordAudioEnabled / recordAudioDir /
activeAsrModel / asrModels / vadModel / vadThreshold / vadMinSilenceDuration /
vadWindowSize / vadMaxSpeechDuration / enableVad / enableEndpoint / endpointRule* /
numThreads / sampleRate 已移除,迁移时改写为上述分组结构。完整字段见
ASR 服务


sherpa-tts-server config.json

config.json 按域分组:server / concurrency / timeouts / transport /
mp3 / tts(与仓库 onnx-platform/sherpa-tts-server/README.mdTTS 服务
一致)。下表只列关键字段与默认值,完整字段表见 TTS 服务

1
2
3
4
5
6
7
8
{
"server": { "listenHost": "127.0.0.1", "listenPort": 9080, "publicBaseUrl": "http://127.0.0.1:9080", "logDir": "logs", "startupScanCache": true },
"concurrency": { "workerThreads": "CPU 核心数", "ttsPoolSize": "max(CPU/2,1)", "ttsModelNumThreads": 2, "maxQueuedRequests": 0, "maxActiveStreams": 24 },
"timeouts": { "socketReadMs": 5000, "socketSendMs": 15000, "ffmpegExitMs": 5000, "streamMaxDurationMs": 60000 },
"transport": { "wavSendChunkBytes": 65536, "maxRequestBodyBytes": 1048576 },
"mp3": { "encoderPath": "ffmpeg", "bitrateKbps": 192, "volumeGainDb": 3.0 },
"tts": { "activeModel": "vits-zh-ll", "models": { "…": "…" } }
}
分组 关键字段 说明
server listenHost / listenPort / publicBaseUrl / logDir 监听地址;publicBaseUrl 是返给客户端的 wav URL 前缀,反代后必须改
concurrency workerThreads / ttsPoolSize / ttsModelNumThreads / maxQueuedRequests / maxActiveStreams HTTP 线程、预热 OfflineTts 实例数、单实例 ONNX 线程、连接队列上限、流式 GET 并发上限
timeouts socketReadMs / socketSendMs / ffmpegExitMs / streamMaxDurationMs socket 读写超时、ffmpeg 退出回收超时、流式 watchdog 总时长
transport wavSendChunkBytes / maxRequestBodyBytes GET /wav/... 分块大小、单请求体上限
mp3 encoderPath / bitrateKbps / volumeGainDb 流式 MP3 编码器路径、CBR 码率(64..320)、响度增益(-20..20,正增益启用 limiter)
tts activeModel / models 模型 profile 选择,详见下文

tts — 模型选择

TTS 模型与 ASR 一样采用 tts.activeModel + tts.models profile 表结构:在
tts.models 下声明多个模型 profile(每个 profile 的 backend 才是 sherpa-onnx
后端类型 matcha / vits / kokoro),用 tts.activeModel 指定当前加载哪一个。
切换模型只改 tts.activeModel。默认配置同时声明四个 profile(matcha-icefall-zh-en
vits-aishell3vits-zh-llkokoro-multi-lang-v1_1),仓库默认 tts.activeModel
vits-zh-ll(5 说话人中文 VITS)。

concurrency.maxActiveStreams(流式 GET 并发上限)与 concurrency.maxQueuedRequests
(连接队列上限)是两层独立保护:前者限制同时编码推流的连接数,后者限制排队等待
worker 的连接数。调优时注意 concurrency.ttsModelNumThreads × concurrency.ttsPoolSize
的乘积不应明显超过 CPU 核心数。缓存 wav 与实时合成两条流式路径共用同一套
mp3.bitrateKbps / mp3.volumeGainDb

旧版扁平顶层字段 listenHost / listenPort / publicBaseUrl / workerThreads /
ttsPoolSize / ttsModelNumThreads / maxQueuedRequests / maxActiveStreams /
socketReadTimeoutMs / socketSendTimeoutMs / ffmpegExitTimeoutMs /
streamMaxDurationMs / wavSendChunkBytes / maxRequestBodyBytes / logDir /
startupScanCache / mp3EncoderPath / mp3BitrateKbps / mp3VolumeGainDb /
ttsModelType / ttsKokoro* / ttsMatcha* / ttsVits* / ttsModelDir /
activeTtsModel / ttsModels 已移除,不再做兼容转换,迁移时必须改写为上述
分组结构。详见 TTS 服务


aliyun-speech-gateway config.json

阿里云语音网关是可选组件,默认不在根目录 bun run dev 中启动。它提供兼容
mod_audio_fork 的 ASR WebSocket 和兼容本地 TTS 的 HTTP 接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
"aliyun": {
"appKey": "",
"token": "",
"url": "wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1"
},
"asr": {
"host": "0.0.0.0",
"port": 10097,
"healthPath": "/health",
"wsPath": "/audio",
"wsSubprotocol": "audio.drachtio.org",
"maxSessions": 64,
"sampleRate": 16000,
"format": "pcm"
},
"tts": {
"host": "0.0.0.0",
"port": 9081,
"publicBaseUrl": "http://127.0.0.1:9081",
"sampleRate": 24000,
"defaultVoice": "aixia",
"voices": []
}
}
字段 说明
aliyun.appKey / aliyun.token / aliyun.url 阿里云 NLS 应用、临时 token 与网关地址;建议用环境变量覆盖
asr.host / asr.port ASR HTTP/WebSocket 监听地址,默认 10097
asr.wsPath / asr.wsSubprotocol WebSocket 路径与子协议,默认兼容 mod_audio_fork
asr.maxSessions 最大 ASR 并发会话数
asr.sampleRate / asr.format 发给阿里云识别 SDK 的音频格式,默认 16k PCM
tts.host / tts.port TTS HTTP 监听地址,默认 9081
tts.publicBaseUrl 返回给调用方的 wav/stream 公开地址前缀,跨主机部署必须改
tts.defaultVoice / tts.voices 默认音色与 speakerId 映射
logging.* 日志目录、级别、轮转大小与保留时间

环境变量覆盖:

环境变量 说明
ALIYUN_NLS_APP_KEY 覆盖 aliyun.appKey
ALIYUN_NLS_TOKEN 覆盖 aliyun.token
ALIYUN_NLS_URL 覆盖 aliyun.url

切换到阿里云网关时,把 callflow-eslaudioFork.wsUrl 改成
ws://<gateway-host>:10097/audio,把 tts.profiles.wav.endpoint
tts.profiles.shout.endpoint 改成 http://<gateway-host>:9081/tts
http://<gateway-host>:9081/tts-stream

详见 阿里云语音网关


azure-speech-gateway config.json

Azure 语音网关是可选组件,默认不在根目录 bun run dev 中启动,接口形态与阿里云网关一致,
但底座换成 Azure Speech,并支持 bun build --compile 打成独立可执行文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
"azure": {
"region": "uksouth",
"endpoint": "https://uksouth.api.cognitive.microsoft.com/",
"ttsEndpoint": "https://uksouth.tts.speech.microsoft.com/cognitiveservices/v1",
"subscriptionKey": ""
},
"asr": {
"host": "0.0.0.0",
"port": 10098,
"healthPath": "/health",
"wsPath": "/audio",
"wsSubprotocol": "audio.drachtio.org",
"maxSessions": 64,
"maxQueuedAudioBytes": 524288,
"startTimeoutMs": 10000,
"autoDetectLanguages": ["zh-CN", "en-US"],
"sampleRate": 16000,
"bitsPerSample": 16,
"channels": 1,
"format": "pcm"
},
"tts": {
"host": "0.0.0.0",
"port": 9082,
"publicBaseUrl": "http://127.0.0.1:9082",
"sampleRate": 16000,
"defaultVoice": "zh-CN-XiaoxiaoNeural",
"outputFormat": "riff-16khz-16bit-mono-pcm",
"streamOutputFormat": "audio-16khz-128kbitrate-mono-mp3",
"requestTimeoutMs": 30000,
"maxTextLength": 1000,
"voices": []
}
}
字段 说明
azure.region / azure.endpoint / azure.ttsEndpoint Azure Speech 区域、资源 endpoint 与 TTS REST endpoint
azure.subscriptionKey Azure Speech key;仓库样例值仅供本地,生产请用环境变量注入
asr.host / asr.port ASR HTTP/WebSocket 监听地址,默认 10098
asr.wsPath / asr.wsSubprotocol WebSocket 路径与子协议,默认兼容 mod_audio_fork
asr.maxSessions / asr.maxQueuedAudioBytes / asr.startTimeoutMs 并发上限、启动期音频缓存上限与 Azure SDK 启动超时
asr.autoDetectLanguages 多语言自动识别候选,默认 ["zh-CN", "en-US"]
asr.sampleRate / bitsPerSample / channels / format 输入音频格式,默认 16k / 16bit / 单声道 / PCM
tts.host / tts.port / tts.publicBaseUrl TTS 监听地址、端口(默认 9082)与公开访问基址,跨主机部署必须改
tts.defaultVoice / tts.voices 默认音色与 speakerId 到 Azure voice 映射
tts.outputFormat / tts.streamOutputFormat WAV 与流式 MP3 输出格式
tts.requestTimeoutMs / tts.maxTextLength TTS 请求超时与单次合成文本长度上限
logging.* 日志目录、级别、轮转大小与保留时间

环境变量覆盖:

环境变量 说明
AZURE_SPEECH_KEY 覆盖 azure.subscriptionKey
AZURE_SPEECH_REGION 覆盖 azure.region
AZURE_SPEECH_TTS_ENDPOINT 覆盖 azure.ttsEndpoint
AZURE_SPEECH_GATEWAY_CONFIG_PATH 指定独立可执行文件读取的 config.json 路径

切换到 Azure 网关时,把 callflow-eslaudioFork.wsUrl 改成
ws://<gateway-host>:10098/audio,把 tts.profiles.wav.endpoint
tts.profiles.shout.endpoint 改成 http://<gateway-host>:9082/tts
http://<gateway-host>:9082/tts-stream

详见 Azure 语音网关


emotion-analysis-server config.json

通话后情绪分析服务(C++ HTTP,默认 127.0.0.1:9090)。是否调用由外呼侧
emotionAnalysis.enabled 决定,本服务自身只有少量配置:

1
2
3
4
5
6
7
8
9
{
"listenHost": "127.0.0.1",
"listenPort": 9090,
"workerThreads": 2,
"maxQueuedRequests": 32,
"maxRequestBodyBytes": 2097152,
"textModelDir": "emotion-text",
"audioModelDir": "emotion-audio"
}
字段 默认 说明
listenHost / listenPort 127.0.0.1 / 9090 HTTP 监听地址
workerThreads 2 HTTP 处理线程数
maxQueuedRequests 32 等待队列上限,超出 503
maxRequestBodyBytes 2097152 单请求体最大字节数
textModelDir / audioModelDir emotion-text / emotion-audio 相对 onnx-platform/models/ 的模型目录

详见 情绪分析服务


callout-server config.json

外呼子系统配置较多,按功能分组。下面是仓库默认 config.json(完整字段与环境变量覆盖以
apps/callout-server/src/config.ts智能外呼 为准):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"server": {
"host": "0.0.0.0",
"port": 9920,
"allowedOrigins": ["http://localhost:19920", "http://127.0.0.1:19920"]
},
"auth": { "enabled": true, "sessionTtlSeconds": 86400 },
"scheduler": { "enabled": true, "intervalMs": 5000, "batchSize": 20 },
"redis": {
"host": "127.0.0.1", "port": 6379, "username": "default", "password": "redis",
"db": 0, "keyPrefix": "callout", "lockTtlMs": 60000
},
"emotionAnalysis": {
"enabled": true, "endpoint": "http://127.0.0.1:9090/analyze",
"timeoutMs": 30000, "intervalMs": 5000, "maxConcurrency": 2,
"retryIntervalMs": 60000, "maxRetries": 3
},
"internalApi": { "callResultToken": "" },
"freeswitch": {
"host": "192.168.2.184", "port": 8021, "password": "ClueCon",
"callbackHost": "192.168.2.246", "callbackPort": 9911,
"originateDialStringTemplate": "user/{{destinationNumber}}",
"commandTimeoutMs": 15000
},
"db": { "url": "postgres://postgres:postgres@localhost:5432/freeswitch" }
}
分组 说明
server HTTP 监听地址;allowedOrigins 为管理台跨域白名单(可用 CALLOUT_CORS_ALLOWED_ORIGINS 覆盖)
auth 管理 API 角色鉴权开关与会话有效期;默认开启,本地联调可 CALLOUT_AUTH_ENABLED=false 关闭,启用后自动创建引导管理员
scheduler 后台派发器开关、轮询间隔、每轮每活动批量
redis 多实例分布式锁(缺省时单实例运行;CALLOUT_REDIS_ENABLED=false 可强制关闭)
emotionAnalysis 通话后情绪分析开关、emotion-analysis-server 端点、超时/轮询/并发/重试
internalApi.callResultToken callflow-esl 回写 /api/call-results 的共享令牌(请求头 X-Callout-Internal-Token
freeswitch inbound ESL + 回拨地址 + 拨号串模板(agentDialStringTemplate 为坐席软电话呼出模板,默认 user/{{agentExtension}}
db.url PostgreSQL;callout 从中派生 calloutcallflow 两个 schema

此外 config.ts 还支持这些带内置默认值、按需添加的分组:lifecycleReconcile(卡死联系人补偿)、
conferenceReconcile(转人工会议僵尸会话对账,默认 30s 一轮 / 60s 宽限)、importJobs(异步导入 worker)、
notifications(运行事件告警 webhook)、ringbackDetection(回铃音 / 嘟声检测),以及
freeswitchEvents(inbound ESL 接听/挂机兜底)。

可用 CALLOUT_ 前缀环境变量覆盖(如 CALLOUT_SERVER_PORTCALLOUT_FREESWITCH_HOST
CALLOUT_ORIGINATE_DIAL_STRING_TEMPLATECALLOUT_AUTH_ENABLEDCALLOUT_EMOTION_ANALYSIS_ENABLED)。
回铃音检测ringbackDetection 配置块控制(代码默认关闭,但仓库内 config.json 默认开启,含
mod_spandsp 嘟声检测),也可用 CALLOUT_RINGBACK_DETECTION_ENABLED..._WS_URL..._MIX_TYPE
..._SAMPLE_RATE..._TIMEOUT_MS..._TONE_ENABLED..._TONE_FREQUENCY..._TONE_HITS 覆盖。活动 /
联系人 / 线路级策略(并发、重试、工作时段、禁呼、频控等)存在数据库里,不在配置文件中,详见 智能外呼

管理台与前端环境变量

callflow-server(管理控制台 API,无 config.json,全部走环境变量):

环境变量 默认 说明
CALLFLOW_SERVER_HOST / CALLFLOW_SERVER_PORT 0.0.0.0 / 9913 HTTP 监听地址
FREESWITCH_DB_URL …@192.168.2.246:5432/freeswitch FreeSWITCH 数据库(只读视图)
CALLFLOW_DB_URL …@localhost:5432/freeswitch?options=-c search_path=callflow callflow 数据库(读写)
CALLFLOW_ESL_BASE_URL http://127.0.0.1:9912 callflow-esl HTTP,用于运行时配置重载

前端(Quasar,构建/开发期注入 VITE_*):

应用 环境变量 默认 dev 端口
callflow-webpage VITE_CALLFLOW_API_BASE http://127.0.0.1:9913 19913
callout-webpage VITE_CALLOUT_API_BASE_URL http://127.0.0.1:9920 19920

管理控制台把 TTS / 录音运行时配置写进 callflow-esl 同一套 callflow schema,再触发
热重载,因此控制台与 callflow-esl 必须连到同一个 callflow 数据库。

mod_audio_fork 环境变量

变量 默认 说明
MOD_AUDIO_FORK_SUBPROTOCOL_NAME audio.drachtio.org WebSocket 子协议名
MOD_AUDIO_FORK_SERVICE_THREADS 1 服务线程数(1-5)
MOD_AUDIO_FORK_BUFFER_SECS 2 缓冲秒数(1-5)

mod_audio_fork channel variable

可在 dialplan 或 uuid_setvar 中设置:

变量 用途
MOD_AUDIO_BASIC_AUTH_USERNAME WSS 端的 Basic Auth 用户名
MOD_AUDIO_BASIC_AUTH_PASSWORD WSS 端的 Basic Auth 密码
MOD_AUDIO_FORK_ALLOW_SELFSIGNED TLS 允许自签证书
MOD_AUDIO_FORK_SKIP_SERVER_CERT_HOSTNAME_CHECK 跳过 TLS hostname 校验
MOD_AUDIO_FORK_ALLOW_EXPIRED 允许过期证书

FreeSWITCH dialplan 关键片段

把通话路由到 callflow-esl:

1
2
3
4
5
6
<extension name="route-to-callflow">
<condition field="destination_number" expression="^(.+)$">
<action application="set" data="hangup_after_bridge=true"/>
<action application="socket" data="<callflow-esl-host>:9911 async full"/>
</condition>
</extension>

可选:在 dialplan 提前设 channel variable,业务侧可读:

1
2
<action application="set" data="campaign_id=may-test"/>
<action application="set" data="business_code=my-business"/>

启用 mod_audio_fork:

1
2
<!-- conf/autoload_configs/modules.conf.xml -->
<load module="mod_audio_fork"/>

ESL inbound(callflow-esl 调用 FS 用):

1
2
3
4
5
6
7
8
9
<!-- conf/autoload_configs/event_socket.conf.xml -->
<configuration name="event_socket.conf" description="Socket Client">
<settings>
<param name="listen-ip" value="0.0.0.0"/>
<param name="listen-port" value="8021"/>
<param name="password" value="ClueCon"/>
<param name="apply-inbound-acl" value="localnet.auto"/>
</settings>
</configuration>

配置变更速查

想做 改哪个
改 ASR 监听端口 sherpa-asr-online-server/config.json server.port + audioFork.wsUrl
改 TTS 监听端口 sherpa-tts-server/config.json server.listenPort + tts.profiles.wav.endpoint + tts.profiles.shout.endpoint + server.publicBaseUrl
切换到阿里云 ASR/TTS 启动 bun run dev:aliyun-speech,再改 audioFork.wsUrltts.profiles.wav.endpointtts.profiles.shout.endpoint 指向网关
切换到 Azure ASR/TTS 启动 bun run dev:azure-speech,再改 audioFork.wsUrl:10098/audio)、tts.profiles.*.endpoint:9082)指向网关
改 callflow-esl ESL/HTTP 端口 esl-server.port / http-server.port + FS dialplan socket 地址
改 FS 反向回拨地址 freeswitch.callbackHost
改 ASR 模型 sherpa-asr-online-server/config.json asr.activeModel(在 asr.models 里声明 profile)
改 TTS 模型 sherpa-tts-server/config.json tts.activeModel(在 tts.models 里声明 profile)
改 hear 默认超时 esl-server.asrTimeoutMs(业务可在 hear() 入参覆盖)
改 ASR 并发 concurrency.maxSessions + concurrency.sessionPoolSize
改 TTS 并发 concurrency.workerThreads + concurrency.ttsPoolSize + concurrency.ttsModelNumThreads;流式连接另受 concurrency.maxActiveStreams 限制
切换流式 / 整段 TTS tts.use.call / tts.use.conference"shout"(流式)或 "wav"(整段);流式需 FS 启用 mod_shout
切换 ffmpeg 路径 sherpa-tts-server/config.json mp3.encoderPath
开启 ASR 上行录音 recording.enabled: true
切换业务路由 PostgreSQL 表 callflow.call_businesses + callflow.call_business_number_mappings
改外呼 API 端口 apps/callout-server/config.json server.port(或 CALLOUT_SERVER_PORT
调外呼并发 / 重试 / 工作时段 活动级字段(存数据库),见 智能外呼
启用回铃音检测 CALLOUT_RINGBACK_DETECTION_ENABLED=true + ..._WS_URL
启用通话后情绪分析 callout emotionAnalysis.enabled=true + endpoint;并启动 emotion-analysis-server,见 情绪分析服务
启用会议跨实例协调 callflow-esl redis.enabled=true,多实例部署必需,见 转人工与坐席
改管理台 API 端口 CALLFLOW_SERVER_PORT + 前端 VITE_CALLFLOW_API_BASE
在线调 TTS / 录音配置 管理控制台 /callflow 页保存后点重载,见 管理控制台
不拨电话测试 ASR 管理控制台 /asr-test 页上传音频或录音,端点可指向本地 ASR 或阿里云网关