Adventists - API文档
    • 总览
    • 更新日志
    • 基本配置
    • 2.5 更新
    • Quick Start
    • Demos
    • 全双工模式接入指南
    • Emoji 表情定制指南
    • TCP语音对话
      • TCP接入
      • MCP协议接入
      • WebSocket快速接入
      • VAD 模式接入指南
      • Emoji 模式对接指南
      • 会议系统接口文档
      • TCP获取Token
        POST
    • 配置管理
      • 模版 与 角色
      • 名词和参数说明
      • Hippo 记忆管理服务 API 接口文档
      • 设备/角色封禁管理 API 接口文档
      • 模板
        • 查询公开模板列表
        • 查询当前组织模板(包含公开和私有模板)
        • 创建角色模板
        • 查询角色模板信息
        • 修改角色模板
        • 删除角色模板
        • 提交角色模板记忆
      • 角色
        • 创建角色(通过模板创建)
        • 创建角色
        • 查询角色
        • 修改角色
        • 删除角色
        • 发送角色记忆
        • 读取角色记忆
        • 创建角色(通过现有角色创建)
      • 技能书
        • 查询技能书列表
        • 预创建任务书
        • 上传任务书内容
        • 完成上传任务书
        • 查询技能书创建进度
      • 音色
        • 获取音色列表
        • 试听音色
        • 提交音色
        • 查询音色状态
        • 批量tts接口
      • Hippo记忆管理
        • 获取指定角色的个人知识图谱
        • 获取指定角色的人物关系数据
        • 获取指定角色的日记数据
        • 更新角色的 PKG
        • 触发做梦
        • 对话记忆接口
        • 读取对话记忆
      • 设备/角色封禁管理
        • 设备/角色封禁
        • 设备/角色解除封禁
        • 查询封禁列表
        • 查询单个封禁状态
    • 聊天辅助
      • 上传画面(Base64)
        POST
      • 上传画面(File)
        POST
      • 健康检查
        GET
    • 用量统计
      • 调用次数基本统计
    • 消息推送
      • 日志 Webhook 推送接口文档
      • 设备推送 Gateway API 接口文档
      • 设备推送
      • 语音播报(兼容旧接口)
      • 查询任务状态

    全双工模式接入指南

    Duplex 全双工模式接入指南#

    适用版本:tcpv2.5+(duplex 分支)

    概述#

    Duplex(全双工)是语音对话服务的新一代交互模式:用户可以随时打断 AI 说话,AI 也在持续"听",不需要按住说话、也不用等对方说完再开口,体验接近真人电话。
    底层二进制帧格式(##START / ##END 包裹的定长头 + 消息类型 + payload)与 tcpV2.5.md 完全一致,只是通过认证参数里的 mode:duplex 切换到这条链路。核心差异:
    服务端主导监听:认证成功后服务端主动下发一次 LISTEN start 作为音频门控,之后不再有 LISTEN stop,也没有"一轮对话"的概念。
    打断免客户端处理:用户随时开口即视为打断,客户端只需持续推流,不需要生成新 task_id 或发任何控制消息。
    task_id 降级为会话常量:全程固定为 duplex00,seq 单调递增。
    TEXT(下行)时序反转:其他模式下 TEXT 先于音频到达(预告),duplex 下 TEXT 是追认,晚于音频到达(实测约 0.8~1 秒)。

    与其他模式的差异#

    manualvad(auto)duplex
    语音结束判定客户端发 END_FRAME服务端 VAD 检测静音服务端按输出能量静默判定
    task_id客户端生成,按轮次变化客户端生成,按轮次变化固定为 duplex00
    LISTEN start(下行)无每轮开始仅一次,作为音频门控
    LISTEN stop(下行)无语音结束时下发没有这个消息
    打断方式客户端发新 LISTEN start客户端发新 LISTEN start无需客户端动作
    TEXT 到达时序先于音频先于音频晚于音频
    SPEAK 消息支持支持不支持,返回 ##ERROR

    接入地址#

    方式地址适用场景
    直连 TCP203.208.134.27:8007已有语音网关/嵌入式设备,自行编解码二进制帧
    WebSocket 网关wss://api.adventists.ai/duplex/wsWeb / App,字节流原样透传,语义与直连 TCP 一致
    参考客户端(Python,直连 TCP):tools/duplex_client.py
    浏览器端参考实现:../website/shared/adventists-client.js,可跑 demo:https://adventists.ai/demo/duplex/

    快速开始#

    1. 认证#

    在 AUTH 帧(消息类型 1)payload 里指定 mode:duplex:
    {JWT_TOKEN}##mode:duplex##format:pcm##input_audio_format:pcm
    JWT 通过 WebSocket 网关同域名下的 REST 接口获取(无需先经过其它页面):
    响应:{ "token": "eyJ..." }
    没有 npcid 的话,先用 POST https://api.adventists.ai/duplex/init(body {})创建一个测试角色,响应 { "code": 201, "data": "<npcid>" }。
    认证响应(STATUS,消息类型 5):
    成功:##INFO:认证成功,NPCID: <npcid>, 模式: duplex
    失败:##ERROR:<原因>
    失败后连接会被服务端主动关闭。

    2. 等待 LISTEN start 门控#

    服务端准备好后(约 1 秒内)下发(消息类型 8):
    {"taskid": "duplex00", "type": "listen", "state": "start", "mode": "duplex"}
    在收到这条消息之前推音频是未定义行为,必须等待。这是 duplex 全程唯一一条下行 LISTEN。

    3. 持续推流音频#

    用固定 task_id(duplex00)发送 AUDIO_FRAME(消息类型 2),必须持续发送、包括静音——断流会被服务端解读为没有声音输入。

    4. 接收回复 / 处理打断#

    正常接收 AUDIO_FRAME(下行持续音频流,空闲是静音帧)、TEXT(追认文字,晚于音频)、END_FRAME(一段话说完)。用户随时开口即视为打断,服务端自动停止旧内容、开始新内容,客户端无需任何额外动作。

    认证参数#

    参数说明默认
    mode必须是 duplex—
    format下行音频编码,pcm(推荐)或 opuspcm
    input_audio_format上行音频编码pcm
    voiceid强制指定音色(不填则用角色配置的默认音色)—
    resolution摄像头画面分辨率提示(纯文本标注)—

    LISTEN 消息协议#

    消息格式#

    [##START][MessageType:8][task_id:8字节][seq:4字节][JSON消息体][##END]

    服务端 → 客户端:LISTEN start(唯一的下行 LISTEN)#

    {"taskid": "duplex00", "type": "listen", "state": "start", "mode": "duplex"}
    会话建立完成后下发一次,作为音频门控。

    客户端 → 服务端:LISTEN(会被忽略)#

    duplex 下轮次由服务端判定,客户端发送的 LISTEN start/stop 不会产生任何效果,服务端仅回一条 ack:
    ##INFO:LISTEN start ignored in duplex mode
    从 manual/vad 模式迁移的客户端,直接删除"发送 LISTEN 控制打断"这部分逻辑即可,不发也没有副作用。

    音频与文本#

    音频#

    方向采样率编码通道帧长
    上行16000 HzPCM16(小端)或 Opus单声道建议 60ms 一帧
    下行16000 Hz跟 AUTH 里的 format 一致单声道约 100ms 一帧,持续不断
    下行音频流持续连续,空闲时是能量为 0 的静音帧而不是没有数据,播放端按"收到就播"处理即可。上行同理:静音期也要持续推流保活。

    文本(TEXT,消息类型 4)#

    duplex 下 TEXT 是"AI 已经说了什么"的追认,晚于对应音频到达(实测约 0.8~1 秒,按整句聚合后才发)。做口型同步或字幕同步的客户端不能沿用"先显示文字再等音频"的写法,字幕会明显滞后于声音;TEXT 只适合当作事后补充的文字记录。

    用户说的话#

    ##INFO:prompt:<识别出的用户原话>
    走 STATUS 通道(消息类型 5),语音识别结果的文本形式。

    图片(仅视觉类角色需要)#

    响应:
    { "status": "ok", "path": "http://.../xxx.jpg" }
    这个接口不遵守 HTTP 状态码语义——即使参数有问题也可能回 200,一定要检查 body 里的 status 字段。建议每 5 秒上传一帧,跟对话音频完全解耦。

    关键事件时序#

    连接建立#

    客户端 -> 服务端: AUTH (##mode:duplex...)
    服务端 -> 客户端: STATUS  ##INFO:认证成功,NPCID: <npcid>, 模式: duplex
    客户端 -> 服务端: MCP register   ← 可选,端侧工具注册,见 mcp-protocol.md
    服务端 -> 客户端: LISTEN {"state":"start"}   ← 收到这条才可以开始推音频
    客户端 -> 服务端: AUDIO_FRAME ...(持续推流,包括静音)
    服务端 -> 客户端: AUDIO_FRAME / TEXT / END_FRAME ...

    委派提示(可选处理)#

    AI 判断需要调用后台能力(查资料、看画面等)时,会先发一条纯文本状态帧,处理完成后(不管成功/失败)再发一条结束:
    ##INFO:delegation:start:<内部任务id>
    ##INFO:delegation:end:<内部任务id>
    真正的回复内容仍然只通过 AUDIO_FRAME/TEXT 通道到达,这两条纯粹用于显示"正在处理"的等待动画,不处理也不影响功能。参考实现:../website/demo/duplex/duplex-demo.js 的 showCallingBubble/hideCallingBubble。

    打断#

    [AI 正在说话,持续下发 AUDIO_FRAME]
    客户端 -> 服务端: AUDIO_FRAME ...(用户开始说话,正常持续推流即可)
                                                服务端检测到用户说话,自动打断
    服务端 -> 客户端: AUDIO_FRAME ...(新内容,旧内容的下发就此停止)

    一段话结束#

    服务端 -> 客户端: AUDIO_FRAME ...(说话中)
    服务端 -> 客户端: TEXT ...(追认这句话说了什么,晚于对应音频)
    服务端 -> 客户端: END_FRAME
    END_FRAME 只表示"这一段话说完了",不代表整场对话结束——duplex 下 task_id 是会话常量,分段信号统一看 END_FRAME。

    消息类型参考#

    类型值duplex 下的语义
    AUTH1认证消息,需带 ##mode:duplex
    AUDIO_FRAME2音频帧,双向持续流(含静音)
    END_FRAME3仅下行有意义:一段话说完;上行发送被忽略
    TEXT4仅下行:追认文字,晚于对应音频到达
    STATUS5认证回执 / 错误 / 用户原话回显 / 委派开始结束提示
    MCP6端侧工具注册(认证成功后约 1 秒窗口内)
    SPEAK7不支持,返回 ##ERROR
    LISTEN8仅下行会发一次 start 作为音频门控;上行发送被忽略
    EMOJI9与其他模式一致,见 Emoji 模式对接指南

    常见问题#

    Q:发了 LISTEN start 没反应?
    duplex 下客户端发送的 LISTEN 会被忽略(只回一条 ack),轮次和打断完全由服务端判定,删除这部分客户端逻辑即可。
    Q:一直没收到 LISTEN start?
    正常等待即可,启动窗口约 1 秒。超过 10 秒仍未收到再考虑重连。
    Q:AUTH 后收到 ##ERROR: 并断连?
    JWT 过期/无效,或 npcid 不存在,重新走一遍 /duplex/login 换新 token。
    Q:AI 说话说到一半突然停住?
    上行音频流意外中断(网络抖动/静音帧没发够),保持上行音频流连续,包括静音期。
    Q:字幕比声音"慢一句"?
    duplex 下 TEXT 本来就滞后于音频,不要用它驱动实时口型/字幕同步。
    Q:能用 SPEAK 让角色说指定内容吗?
    不支持,会收到 ##ERROR:duplex 模式暂不支持 SPEAK。
    Q:图片上传报 status:"fail" 但 HTTP 是 200?
    这个接口不遵守状态码语义,一定要检查 body 里的 status 字段。
    修改于 2026-09-16 10:22:50
    上一页
    Demos
    下一页
    Emoji 表情定制指南
    Built with