通过 AOQ 接入 qwen3.5-omni-plus-realtime,由客户端控制语音起止,实现按键通话和可选的拍照提问。客户端代码以 iOS Swift 为例。
方案概述
Qwen-Omni-Realtime 支持由服务端 VAD 自动划分轮次,也支持由客户端控制轮次的 Manual 模式。本教程将 session.turn_detection 设为 null:用户按下按钮时发送音频,松开按钮时提交音频并显式触发模型回复。
Manual 模式适用于硬件按键对讲、屏幕按住说话、噪声环境下由业务自行判停,以及在一轮语音中按需附带图片等场景。音频通过 AOQ Audio 轨传输,不需要发送 input_audio_buffer.append。
| 对比项 | VAD 模式 | Manual 模式 |
|---|---|---|
| 语音起止 | 服务端通过 server_vad 或 semantic_vad 检测 | 客户端根据按键或业务状态控制 |
| 会话配置 | turn_detection 为 VAD 参数 | turn_detection 为 null |
| 提交音频 | 服务端自动提交 | 客户端发送 input_audio_buffer.commit |
| 触发回复 | 服务端自动触发 | 客户端发送 response.create |
| 图片输入 | 视频轨持续推流或 Data 轨按需发图 | 视频轨持续推流或 Data 轨按需发图 |
准备工作
- 开通千问AI平台,并按获取与配置 API Key获取 API Key。API Key 只保存在业务 AppServer,不要写入客户端代码或提交到代码仓库。
- 根据业务部署地域确认 AOQ Endpoint。地域和接入地址的选择方法请参见选择地域、服务部署范围和接入域名。
- 从 SDK 下载获取最新版 AOQ Client SDK。
- 搭建业务 AppServer,并按 Token 鉴权实现服务端代理鉴权。每次建立新连接前,客户端都应从 AppServer 获取新的连接凭证。
导入 SDK
根据开发平台导入对应 SDK。后续客户端代码以 iOS Swift 为例,其他平台使用相同的接口设计和事件流程。本文以 PCM 音频流为例。Opus 编码由插件提供;如果需要使用 Opus 编码上行,请导入 Opus 插件。
- Android
- iOS
- HarmonyOS
- Linux (Python)
- 将 AoqClientSdk-release.aar 放入 app/libs,并在 app/build.gradle 中配置依赖和 SDK 支持的 ABI:
- 在 AndroidManifest.xml 中声明以下权限:
- 在使用相应设备前动态申请 RECORD_AUDIO、CAMERA 权限。
实现流程
- AppServer 通过 Realtime Token 地址获取 qwen3.5-omni-plus-realtime 的 AOQ 连接参数。
- 客户端创建引擎,配置音频编解码与轨道;如需持续视觉理解,再配置 Video 轨。
- 客户端启动本地采集和播放,默认关闭 Audio 轨发送,然后建立 AOQ 连接并发送 session.update。
- 收到 session.updated 后,持续视频方案开启 Video 轨;Audio 轨仍保持关闭,直到用户按下说话按钮。
- 用户按下按钮时开启 Audio 轨;松开时先关闭 Audio 轨,再按需发送图片,然后依次发送 input_audio_buffer.commit 和 response.create。
- 收到 response.done 后可开始下一轮;结束使用时停止设备、断开连接并销毁引擎。
- 视频轨持续推流
- Data 轨按需发图
发布 Video 轨并在 session.updated 后开启视频发送。模型持续看到最新画面;每轮语音只需提交音频并触发回复。

AppServer 获取 Token
在 AppServer 设置 DASHSCOPE_API_KEY,并使用所选地域的 Endpoint 发送请求。clientIp 为客户端的真实公网 IP;该字段可选,但建议传入,以便服务分配合适的 Relay 接入点。
如果 AppServer 无法获取客户端真实公网 IP,请删除 clientIp 字段,不要传空字符串。
| 响应字段 | SDK 字段 |
|---|---|
| aoqTokenForClient | AoqConnectConfig.token |
| sid | AoqConnectConfig.sid |
| clientRelayCertFingerprint | AoqConnectConfig.certFingerprint |
| clientRelayEndpoints | AoqConnectConfig.relayEndpoints |
| extraInfo.workspaceIdHash | AoqConnectConfig.workspaceIdHash |
实现 iOS 客户端
客户端从 AppServer 获取 AoqConnectConfig 后,按以下步骤实现 iOS 端按键语音对话。
1. 创建引擎并设置回调
创建 AOQ 单例引擎,并把业务对象注册为回调接收方。客户需要在回调中处理连接状态、服务端事件、错误和告警。
2. 启动音视频设备
初始化音频采集与播放。只有持续视频轨方案需要启动摄像头;客户需要在调用前获得麦克风和摄像头权限。
3. 配置编解码和轨道
根据接入模型和业务音频格式配置音频编解码参数,并根据图片输入方式选择轨道。以下音频与视频数值仅为示例,请按模型要求和业务场景调整。连接前必须关闭 Audio 轨发送。
- 视频轨持续推流
- Data 轨按需发图
客户需要配置 Audio、Video 和 Data 发布轨,并根据实际画质与带宽调整视频编码参数。
4. 配置 Manual 会话
连接成功后,调用 sendDataMsg 发送 session.update 事件。客户需要把 turn_detection 设为 null,并按业务选择音色、系统指令和输出模态。示例中的音频参数需要与 SDK 编解码配置保持一致。完整字段请参见客户端事件。
5. 等待会话配置生效
在 onDataMsg 回调中处理 session.updated 事件,收到该事件后才能发送媒体。持续视频轨方案此时调用 enableSendMediaStream 开启 Video 轨;Audio 轨仍保持关闭,避免用户按键前的音频进入缓冲区。
6. 实现按键语音交互
按下按钮时调用 enableSendMediaStream 开启 Audio 轨。松开按钮时先调用 enableSendMediaStream 关闭 Audio 轨,确认本轮确有音频,再按需发送图片,并调用 sendDataMsg 依次发送 input_audio_buffer.commit 和 response.create 事件。
7. 选择图片输入方式
持续视觉理解和偶发拍照提问使用不同的轨道配置与发送方式;客户需要根据带宽、功耗和交互方式选择。
- 视频轨持续推流
- Data 轨按需发送单张图片
适合视频通话、画面变化较快或模型需要持续理解视觉上下文的场景。发布 Video 轨后,不要再发送 input_image_buffer.append。
8. 断开连接并销毁引擎
结束会话时断开连接并销毁引擎。disconnect 或 destroy 会自动关闭媒体设备,无需额外调用停止接口。AoqClientEngine 为全局单例,只有 destroy 后才能重新创建。
完整示例
以下类接收已由 AppServer Token 响应转换完成的 AoqConnectConfig。请在生产代码中补充 UI 状态、权限、错误恢复和图片压缩逻辑。
运行并验证
分别完成一次纯语音按键对话和一次带图片的按键对话,预期结果如下:
- 按下按钮前不发送 Audio 轨;按住按钮时持续上行音频。
- 松开按钮后依次收到 input_audio_buffer.committed、response.created 和 response.done,模型语音通过订阅的 Audio 轨播放。
- 选择单张图片方案时,模型结合本轮图片与语音作答;选择持续视频方案时,模型使用最新视频画面。
注意事项
- AOQ 的 Audio 轨负责传输音频,不要另外发送 input_audio_buffer.append。
- input_audio_buffer.commit 只提交本轮输入,不会触发模型回复;必须随后发送 response.create。
- 空音频缓冲区不要提交,否则服务端会返回错误。
- 不要在收到 session.updated 前开启媒体发送;Manual 模式下也不要在用户按下按钮前开启 Audio 轨。
