培训包现已包含完整语音克隆能力,支持:
当前版本:
https://server.fmode.cn/api/voice/indextts2构建命令:
node scripts/build-training-package.mjs
拷贝整个 dist/qiwei-training/ 目录到培训机,确保包含:
dist/qiwei-training/
├── qiwei-workbench.exe # 96MB 主程序(含语音依赖)
├── .env.local # 本机凭据配置
├── README.md # 使用说明
├── qiwei.runtime.config.mjs
├── web/ # 工作台前端
└── knowledge/ # 客服知识库
编辑 .env.local:
QIWEI_AUTH_TOKEN=sk-xxx # 必填:Fmode Token(从 https://server.fmode.cn 获取)
QIWEI_UID= # 可选:登录后自动填充
QIWEI_GUID= # 可选:登录后自动填充
双击 qiwei-workbench.exe,浏览器会自动打开 http://127.0.0.1:4320。
要求:
示例话术:
"您好,我是您的专属顾问小王。很高兴为您服务。关于您咨询的房源信息,我这边已经为您整理好了详细资料,包括户型图、价格和周边配套。如果您方便的话,我可以现在发给您,也可以约个时间带您实地看房。请问您这边什么时间比较合适呢?"
通过工作台或 MCP 工具调用:
// 方式 1:工作台 UI(推荐)
// 在工作台「语音克隆」面板上传参考音频
// 方式 2:MCP 工具调用
qiwei_enroll_voice({
filePath: "D:/recording/reference.wav",
guid: "your-guid" // 可选,多账号时指定
})
结果:
outputs/voice/<guid>/profile.jsonoutputs/voice/<guid>/reference-*.wavqiwei_send_cloned_voice({
toId: "wmAbCdEfGhIjKlMnOpQrSt", // 企微联系人 ID
text: "您好,关于您咨询的房源,我已经整理好资料了。",
tone: "auto", // 自动识别语气:natural/friendly/apology/empathetic/reminder
confirmed: true // 必须明确确认(真实发送操作)
})
流程:
indextts2 合成 WAV 音频语音合成费用(从 Fmode 飞马余额扣费):
示例:
余额查询:
curl -H "Authorization: Bearer sk-xxx" \
https://server.fmode.cn/api/product/balance
可能原因:构建时使用了 --external 标志
解决方案:
# 重新构建,确保不带 --external
node scripts/build-training-package.mjs
原因:Token 无效或未配置
解决:
.env.local 中的 QIWEI_AUTH_TOKENsk- 开头排查步骤:
outputs/voice/<guid>/ 下是否有 .silk 文件toId 是否正确(应为 wmXxxx 格式)现象:Error: spawn ffmpeg ENOENT 或 WxVoice encode failed
原因:二进制依赖未正确打包
解决:
# 验证打包是否完整
node scripts/verify-voice-in-training-package.js
# 如果验证失败,清理后重新构建
rm -rf dist/qiwei-training
node scripts/build-training-package.mjs
运行自动化验证:
node scripts/verify-voice-in-training-package.js
检查项:
# 准备测试音频(5-30秒 WAV)
# 启动工作台
cd dist/qiwei-training
./qiwei-workbench.exe
# 在工作台上传参考音频
# 预期:outputs/voice/<guid>/profile.json 生成
// 在工作台控制台或通过 MCP 调用
const service = new VoiceCloneService(guid);
const wavPath = await service.synthesize({
text: "这是一条测试语音",
tone: "natural"
});
// 预期:返回 WAV 文件路径,可播放验证
// 发送到测试联系人(需提前加好友)
qiwei_send_cloned_voice({
toId: "测试联系人的企微ID",
text: "您好,这是一条测试语音消息。",
confirmed: true
});
// 预期:对方收到语音消息,音色与参考音频一致
qiwei-workbench.exe (96MB)
├── bun runtime
├── 业务逻辑
│ ├── voice-clone-service.js
│ ├── agent-workbench-service.js
│ └── ...
└── 二进制依赖(已打包)
├── @ffmpeg-installer/ffmpeg (~50MB)
├── @ffprobe-installer/ffprobe
└── @binsee/wx-voice (~10MB)
用户输入文本
↓
VoiceCloneService.synthesize()
↓
POST https://server.fmode.cn/api/voice/indextts2
├── Headers: Authorization: Bearer sk-xxx
├── Body: multipart/form-data
│ ├── payload: {text, tone, model}
│ └── audio: reference.wav
└── Response: audio/wav (24kHz)
↓
ffmpeg 转换 → 24kHz 单声道 WAV
↓
WxVoice.encode() → SILK 格式
↓
企微 /msg/uploadMediaFile → fileId
↓
企微 /msg/sendVoice → 发送成功
const endpoint = String(config.endpoint ||
'https://server.fmode.cn/api/voice/indextts2').trim();
可通过环境变量覆盖:
QIWEI_VOICE_ENDPOINT=http://127.0.0.1:7338/api/voice/indextts2 # 本地开发
如果方案 A 验证通过,可考虑将 SILK 编码移到后端:
新接口:POST /api/voice/qiwei/send
请求:
{
"text": "您好,关于您咨询的房源...",
"tone": "friendly",
"referenceAudio": "base64...",
"toId": "wmAbCdEfGhIjKlMnOpQrSt"
}
响应:
{
"messageId": "xxx",
"fileId": "xxx",
"silkSize": 45678
}
优势:
文档版本:v1.0
更新时间:2026-08-20
维护者:Fmode 团队