跳到正文

开发测试手册(Windows 11)

本手册面向在 Windows 11 上进行日常开发与测试的场景。约定:除 FreeSWITCH 安装在虚拟机 外,本仓库的全部服务(ONNX C++ 服务、Bun 后端、Quasar 前端、NLU)都在本机 Win11 上启动运行, 以便快速联调。生产上线请改用 deployment-debian12.md

阅读顺序:环境准备 → 依赖服务 → 虚拟机 FreeSWITCH 与网络约定 → 构建 C++ → 启动 → 冒烟测试 → 自动化测试(typecheck / bun test)→ 收尾关闭。

1. 拓扑与网络约定

text
┌──────────────── Windows 11 开发机 ───────────────┐        ┌──── 虚拟机 ────┐
│ ONNX: ASR 10096 / TTS 9080 / Emotion 9090        │        │  FreeSWITCH    │
│ NLU 9930   callflow-esl 9911/9912                │◀──────▶│  1.10.x        │
│ callflow-server 9913   callout-server 9920       │  局域网 │  mod_audio_fork│
│ callflow-webpage 19913 callout-webpage 19920     │        │  ESL 8021      │
│ PostgreSQL 5432   Redis 6379   Ollama 11434      │        └────────────────┘
└──────────────────────────────────────────────────┘

关键约束:FreeSWITCH 与开发机之间必须双向可达

  • 本机 → 虚拟机:callflow-esl / callout-serverfreeswitch.host:8021(inbound ESL)、 以及录音静态访问地址要指向虚拟机 IP。
  • 虚拟机 → 本机:FreeSWITCH 需回连开发机的
    • outbound socket:callbackHost:callbackPort(默认 9911)
    • ASR 推流:audioFork.wsUrl(默认 ws://<开发机IP>:10096/audio)
    • TTS 播放:sherpa-tts-serverpublicBaseUrl / 返回的 wav/mp3 URL

因此配置里不能用 127.0.0.1 作为回连地址。建议把虚拟机网卡设为桥接模式(或 NAT + 端口转发),让开发机与虚拟机在同一网段,然后把上述三处地址统一填成开发机的局域网 IP (ipconfig 查看)。Windows 防火墙需放通 9911 / 10096 / 9080(以及 TTS 短文件名静态端口)。

校验:在虚拟机上 curl http://<开发机IP>:10096/healthcurl http://<开发机IP>:9080/health 能通,才说明回连链路可用。

2. 环境准备(一次性)

2.1 必备工具

  • Bun 1.x —— 所有 TS/前端服务的运行时。bun --version 验证。
  • Visual Studio 2022(含 "使用 C++ 的桌面开发" 工作负载)+ CMake —— 构建 ONNX C++ 服务。
  • PowerShell(仓库脚本默认 shell,使用 $null / $env:VAR / 反引号续行)。
  • ffmpegPATH 中(流式 TTS 需要),或在 TTS 配置里指定 mp3.encoderPath

2.2 依赖服务(本机安装)

服务默认地址用途Win11 获取方式
PostgreSQLlocalhost:5432callflow / callout 两套 schema官方安装包或 Docker Desktop
Redis127.0.0.1:6379外呼分布式锁与状态Docker Desktop / Memurai / WSL
Ollama127.0.0.1:11434NLU 后端模型Windows 版 Ollama

准备步骤:

  1. PostgreSQL:创建库 freeswitch(与默认连接串 postgres://postgres:postgres@localhost:5432/freeswitch 一致),用户/密码可按需改并同步到各 config.json。callflow-esl 与 callout-server 使用同一实例上的 callflow / callout 两个 schema
  2. Redis:启动后确保密码与 apps/callout-server/config.jsonapps/callflow-esl/config.jsonredis 段一致(默认密码 redis)。
  3. Ollama:ollama pull qwen3.5:2b(与 apps/llm-nlu-server/config.jsonllm.model 一致), ollama servecurl http://127.0.0.1:11434/api/tags 验证。

2.3 安装依赖与建表

powershell
bun install                              # 安装全部 workspace 依赖
bun run --cwd apps/callflow-esl db:push  # 同步 callflow schema
bun run --cwd apps/callout-server db:push # 同步 callout schema

db:push 直接把 Drizzle schema 推到数据库,不保留迁移目录。首次建表后, 启动 callflow-esl 会把内置业务的 code/desc 写入 callflow.call_businesses

3. 配置本机联调地址

编辑以下文件,把回连相关地址改成开发机局域网 IP、FreeSWITCH 相关地址改成虚拟机 IP:

  • apps/callflow-esl/config.json
    • freeswitch.host → 虚拟机 IP,port 8021(inbound ESL)
    • freeswitch.callbackHost → 开发机 IP,callbackPort 9911
    • audioFork.wsUrlws://<开发机IP>:10096/audio
    • database.url / redis → 本机 PostgreSQL / Redis
  • apps/callout-server/config.json
    • freeswitch(inbound ESL)、callflowEsl.baseUrl(默认 http://127.0.0.1:9912 本机即可)
    • media.freeswitchRecordingBaseUrl → 虚拟机上录音静态服务地址
  • apps/llm-nlu-server/config.jsonllm.ollamaUrl 默认本机 11434 即可

不要把改后的机器专属 IP / 明文密码提交回仓库(见 CLAUDE.md 与 contributing-docs.md)。本机联调建议用未跟踪的本地覆盖或环境变量注入。

4. 构建 ONNX C++ 服务(Win11)

bun run dev:asr/tts/emotion 只从 target/win_x64/ 拉起已编译产物,产物不存在会直接退出, 所以首次必须先构建:

powershell
cd onnx-platform\sherpa-asr-online-server; .\build.ps1
cd ..\sherpa-tts-server; .\build.ps1
cd ..\emotion-analysis-server; .\build.ps1

build.ps1 用 CMake + VS 2022 生成到 build\win_x64\,并把可执行文件安装到 target\win_x64\

5. 启动服务

一次性启动(推荐日常开发)

powershell
bun run dev

默认进程范围和标签以服务目录为准。C++ 三个服务必须已构建。 Ctrl+C 一次性退出全部子进程。

单服务启动(排障 / 只调某一块)

powershell
bun run dev:asr        # 也有 dev:tts dev:emotion dev:llm-nlu dev:llm-chat
bun run dev:callflow-esl
bun run dev:callflow-server
bun run dev:callout-server
bun run dev:callflow-webpage
bun run dev:callout-webpage

云端兼容网关不在 bun run dev 默认组内,按需 bun run dev:aliyun-speech(10097/9081)、 bun run dev:azure-speech(10098/9082)。

6. 启动后冒烟测试

按依赖顺序验证,避免上游未就绪造成下游误判:

powershell
# 1. C++ 三件套健康
Invoke-WebRequest http://127.0.0.1:10096/health   # ASR
Invoke-WebRequest http://127.0.0.1:9080/health    # TTS
Invoke-WebRequest http://127.0.0.1:9090/health    # Emotion

# 2. NLU
Invoke-WebRequest http://127.0.0.1:9930/health
Invoke-WebRequest http://127.0.0.1:9930/api/v1/nlu/capabilities

# 3. Chat(capabilities 启用 token 时需附带 X-Callout-Internal-Token)
Invoke-WebRequest http://127.0.0.1:9931/health

# 4. TTS 合成(确认能返回 wavUrl,且虚拟机 FreeSWITCH 能访问该 URL)
Invoke-WebRequest -Method Post http://127.0.0.1:9080/tts -ContentType 'application/json' -Body '{"text":"测试"}'

# 5. 管理台 / 外呼后端
Invoke-WebRequest http://127.0.0.1:9913/health
Invoke-WebRequest http://127.0.0.1:9920/health
Invoke-WebRequest http://127.0.0.1:9920/api/media/config

# 5. 前端可达
Invoke-WebRequest http://127.0.0.1:19913
Invoke-WebRequest http://127.0.0.1:19920

端到端一通电话(联通性最终验证):从虚拟机 FreeSWITCH 侧发起一次呼叫路由到 callflow-esl (dialplan socket <开发机IP>:9911 async full,或走 POST http://127.0.0.1:9912/outbound-calls), 观察 callflow-esl 日志出现握手、业务命中、ASR transcription、TTS 播放。链路任何一环断, 对照第 1 节网络约定与 troubleshooting.md 排查。

7. 自动化测试(改代码后的最低验证)

本仓库没有统一测试运行器,typecheck 是所有 TS 改动的基线门槛:

powershell
bun run typecheck        # 一次性检查 6 个核心 TS/Vue 应用(两个语音网关不在内,改到时单独 typecheck)

触及运行时 / 业务逻辑且有 *.test.ts 覆盖时,追加单元测试:

powershell
bun test --cwd apps/callflow-esl                 # 跑该 app 全部 *.test.ts
bun test --cwd apps/callout-server
bun run --cwd apps/callflow-esl typecheck         # 单 app 的 tsc --noEmit
bun test apps/callflow-esl/src/xxx.test.ts        # 单文件
bun test -t "关键字"                               # 按用例名过滤

前端(Quasar/Vue3)另有:

powershell
bun run --cwd apps/callflow-webpage lint
bun run --cwd apps/callflow-webpage typecheck     # vue-tsc --noEmit

改动 Drizzle schema 后需 bun run --cwd apps/<app> db:generatedb:push 再重启对应服务。 新增 callflow-esl 业务的完整步骤见 apps/callflow-esl/README.mdapps/callflow-esl/docs/business-development.md

8. 收尾:关闭本机实例(仓库硬性约定)

测试结束必须关闭本机手动启动的服务,避免端口/资源残留:

powershell
# bun run dev 单终端:Ctrl+C 即可
# 拆分启动的补充清理:
Get-Process | Where-Object { $_.ProcessName -in @('sherpa_asr_online_server','sherpa_tts_server','emotion_analysis_server','node','bun') } | Format-Table Id,ProcessName
netstat -ano | Select-String '10096|9080|9090|9930|9931|9911|9912|9913|9920|19913|19920'

9. 常见问题速查

现象首查项
dev:asr/tts/emotion 秒退target/win_x64/ 无产物,先 build.ps1
FreeSWITCH 呼入不进 callflow-eslcallbackHost 写成 127.0.0.1;应为开发机局域网 IP,且虚拟机可达
无 ASR 结果虚拟机访问不到 audioFork.wsUrl;检查开发机防火墙 10096
TTS 不播放FreeSWITCH 访问不到 TTS 返回的 URL;publicBaseUrl 用回环地址
NLU 报错Ollama 未启动或未 pull 对应模型
建表/连库失败PostgreSQL 未建 freeswitch 库,或连接串与 config.json 不一致
外呼调度不动Redis 未启动或密码不符

更细的模块级排障见 troubleshooting.md 与各模块 README。

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