外观
浏览器软电话与坐席 SIP 接入
系统二的坐席可以直接在浏览器(callout-webpage 坐席通话台)用 SIP 软电话外呼客户, 全程获得实时字幕、打字转语音、保持 / 恢复、DTMF 与结束控制。本文说明这条链路的 组成、配置与接口;单个接口的请求 / 响应结构见 api-reference.md 「浏览器软电话与坐席 SIP」一组。
1. 链路组成
text
坐席浏览器 (callout-webpage 坐席通话台)
│ 1. GET /api/agents/me/sip-config ← 读取本坐席 SIP 注册参数
│ 2. POST /api/softphone-sessions ← 创建会话,拿 sessionId + sipExtraHeaders
│ 3. SIP UA 经 sipWsUrl 注册后拨 softphone.serviceNumber(携带 sipExtraHeaders)
▼
FreeSWITCH ──socket──▶ callflow-esl `browser-softphone-assist-business`
│ 按 SIP Header 里的 sessionId 找回会话 → 建独立会议(坐席=host)
│ → originate 客户入会 → 开会议转写
▼
callout-server(控制面代理,全部落 agent_call_records)
│ GET /api/softphone-sessions/:id/events ← SSE:session / message / tts / error
│ POST /api/softphone-sessions/:id/messages ← 坐席打字文本 → TTS 注入客户腿
│ POST /api/softphone-sessions/:id/controls ← hold / resume / dtmf / transfer
│ POST /api/softphone-sessions/:id/notes ← 会话备注
│ POST /api/softphone-sessions/:id/end ← 结束会话callout-server 自己不碰媒体流:会话的实时状态由 callflow-esl 的 browser-softphone-session-hub 维护(callflow-esl HTTP 端口上有一组同名内部端点, token 头鉴权),callout-server 只做代理 + 权限校验 + 旁路落库。
2. 坐席 SIP 配置
callout.agents 表为每个坐席保存一组浏览器 SIP 注册参数:
| 字段 | 说明 |
|---|---|
phoneExtension | 唯一 SIP 注册账号,同时也是 FreeSWITCH directory 用户、拨号分机和转人工标识 |
sipPassword | SIP 注册密码 |
sipRealm | SIP realm / domain |
sipWsUrl | WebSocket SIP 地址(wss://.../ws,浏览器 UA 用) |
sipDisplayName | 显示名 |
sipEnabled | 是否启用浏览器软电话(0/1) |
读取接口(均要求 agent:operate 权限):
GET /api/agents/me/sip-config:当前登录用户绑定坐席的 SIP 配置 (坐席与登录用户是一对一硬绑定,只认agents.userId)。GET /api/agents/sip-configs:当前用户可见的已启用 SIP 配置列表 (admin / supervisor 可见全部)。
坐席的创建 / 编辑接口(POST /api/agents、PATCH /api/agents/:agentId) 可写入上述 SIP 字段。启用软电话时,phoneExtension、sipPassword、sipRealm 与 sipWsUrl 必须完整。
3. 会话生命周期
- 创建:前端
POST /api/softphone-sessions(携带客户号码与线路选择)。 callout-server 先落一条agent_call_records,再请求 callflow-esl 创建 内存 Hub 会话,返回sessionId、serviceNumber与sipExtraHeaders。 - 拨号:浏览器 SIP UA 拨
serviceNumber(配置softphone.serviceNumber), 必须原样携带sipExtraHeaders——callflow-esl 业务靠这些 Header 里的 sessionId / 客户号码找回会话;缺失会被播错误提示后挂断。 - 接通:
browser-softphone-assist-business建会议(坐席=host)、开录音、 originate 客户入会(conference-guest-business),开启会议转写。 - 实时事件:前端订阅
GET /api/softphone-sessions/:id/events(SSE), 事件类型:session(状态 / 会议 / 录音信息)、message(按角色归并的 对话消息,实时字幕)、tts(打字消息的 queued/playing/completed/failed)、error。 - 控制:
messages(打字文本 TTS 注入客户腿)、controls(hold/resume对坐席腿 deaf/undeaf、dtmf发客户腿、transfer转接)、notes(备注落库)。 - 结束:任一侧挂机或
POST .../end;转写片段写入transcript_segments, 通话记录(含录音短文件名)保留在agent_call_records,事后可查GET /api/softphone-calls(列表)与GET /api/softphone-calls/:id(详情)。
4. 配置
callout-server config.json:
json
{
"callflowEsl": {
"baseUrl": "http://127.0.0.1:9912",
"authToken": "esl-0x21"
},
"softphone": {
"serviceNumber": "5020"
}
}| 字段 | 说明 |
|---|---|
callflowEsl.baseUrl | callflow-esl HTTP 地址(其 http-server 端口,默认 9912),软电话会话代理的目标 |
callflowEsl.authToken | 与 callflow-esl http-server.authToken 对应的共享令牌,代理请求放在 token 头 |
softphone.serviceNumber | 浏览器 SIP UA 实际拨打的业务号(代码默认 8800,仓库配置 5020) |
环境变量覆盖:CALLOUT_CALLFLOW_ESL_BASE_URL、CALLOUT_CALLFLOW_ESL_AUTH_TOKEN、 CALLOUT_SOFTPHONE_SERVICE_NUMBER。
FreeSWITCH 侧要求:serviceNumber 必须能经拨号计划进入 callflow-esl 的 outbound socket,并路由到 browser-softphone-assist-business(在 callflow.call_business_number_mappings 把该号码映射到此业务,或在拨号计划中 设置 business_code 通道变量);坐席 SIP 账号需在 FreeSWITCH directory 注册, 且开启 WebSocket(wss)SIP 入口。
ICE / TURN
两个软电话页面在 SIP 注册前调用受登录鉴权保护的 GET /api/softphone/ice-config。 仓库默认 turn.enabled=false,响应为 { enabled: false, iceServers: [], expiresAt: null },浏览器使用 host candidate 完成本地 直连。关闭状态不缓存、不安排刷新,后续注册、拨号或接听会重新请求,因此服务端启用 TURN 后无需等待旧状态过期。
生产环境启用 TURN 时,响应为 { enabled: true, iceServers: [...], expiresAt: "<ISO time>" },其中包含 STUN、 TURN/UDP、TURN/TCP 和 coturn REST 短期凭据。前端在过期前 5 分钟刷新,同一 callout 标签页的多个软电话组件共用一份凭据缓存。旧凭据过期且刷新失败时,新的注册、拨出与接听 会显示“ICE/TURN 配置获取失败”并在 SDP 创建前停止,不会静默降级为空数组。
TURN 直接监听 123.57.205.60:3478,relay 范围为 31000–31040/UDP,不经过 FRP。 shared secret 只能由服务器私有配置或 CALLOUT_TURN_SHARED_SECRET 注入。 必须同时提供 turn.enabled=true 与真实 shared secret;启用但配置不完整时接口返回 503 ICE_CONFIG_UNAVAILABLE。两种成功响应均使用 Cache-Control: no-store。
5. 关联文档
- 通话侧业务实现:
apps/callflow-esl/docs/existing-businesses.md的browser-softphone-assist-business一节 - 接口请求 / 响应结构:api-reference.md
- AI 通话转人工(会议 ACD,与本链路共用会议与坐席模型): transfer-to-human.md