# 企微声音克隆与语音发送 ## 范围 客服为当前企微账号初始化一次本人录音,之后在客服工作台输入文本、自动选择受控语气,并在人工确认后生成和发送原生企微语音。第一版只允许人工触发,不接入全自动回复。试听功能禁用,避免为同一条消息额外调用一次付费合成。 ## 链路 ```text 本人参考录音 -> 16kHz 单声道 WAV 档案 -> Fmode /api/voice/indextts2 -> 24kHz 单声道 SILK -> Fmode /api/qiwei/doFileApi 直传 -> /msg/sendVoice ``` 参考录音限制为 5~30 秒、最大 20MB。档案存放在 `outputs/voice/profiles//`,不同企微账号相互隔离。 ## Payload 策略 默认参数: ```json { "input": "客服回复文本", "emo_control_method": 0, "use_random": false } ``` 识别到特殊客服场景时使用文本情绪控制: ```json { "input": "非常抱歉给您带来了不好的体验。", "emo_control_method": 3, "emo_alpha": 0.5, "emo_text": "真诚、耐心、克制,带有适度歉意,语速稍慢,不夸张", "use_random": false } ``` | 语气 | 场景 | `emo_alpha` | | --- | --- | ---: | | 自然 | 普通说明或无法判断 | 不传 | | 友好 | 欢迎、感谢、成功、好消息 | 0.40 | | 真诚致歉 | 投诉、道歉、服务失误 | 0.50 | | 温和关怀 | 遗憾、安慰、身体不适 | 0.45 | | 明确提醒 | 截止、到期、时间安排 | 0.40 | 不启用情绪音频和八维情绪向量,不开放愤怒、厌恶、恐惧或强烈悲伤。`use_random` 固定为 `false`。 ## Dashboard API | 路由 | 用途 | | --- | --- | | `GET /api/agent/voice/status` | 查询服务和声音档案状态 | | `POST /api/agent/voice/profile` | 上传 Base64 音频并初始化声音 | | `DELETE /api/agent/voice/profile` | 删除当前账号声音档案 | | `POST /api/agent/conversations/:id/voice-send` | 合成并真实发送企微语音;可传当前 `draftId` | | `GET /api/agent/messages/:id/voice-audio` | 回放指定已发送语音,支持 HTTP Range | 真实发送继续执行私聊、白名单和人工确认校验,并写入工作台消息与审计表。 ### 草稿与消息状态 Dashboard 从待审核草稿发送语音时,在 `voice-send` 请求中携带该草稿的 `draftId`。服务端在合成和企微发送成功后执行以下状态更新: 1. 插入 `msgType=16` 的 outbound 语音消息并保存 WAV 路径、时长和发送结果; 2. 将对应草稿内容更新为实际发送文本,状态更新为 `sent`; 3. 写入 `reviewed_at`、`reviewer=human:voice` 和 `sent_message_id`; 4. 前端刷新后不再显示「批准并发送」,恢复「让 Agent 处理」。 显式传入的 `draftId` 不存在、已处理或属于其他会话时,在合成和外发前拒绝请求。没有待审核草稿时仍允许作为人工语音发送。 ### 消息展示与回放 - 已发送语音显示为带时长和播放状态的语音气泡,点击气泡播放或暂停;同一时间只播放一条语音。 - 气泡左侧提供「转文字」按钮,默认收起,点击后展开合成时保存的原文;该操作不调用 ASR。 - 播放接口只返回数据库已关联且位于 `outputs/voice//