从零运行真实语音 Agent
本页从一个干净的 macOS 开发环境开始,不假设你了解 Agora 或 Qwen。完成后,浏览器 麦克风通过 Agora 进入 Muxiva Graph,由 Qwen 生成实时回复,再通过 Agora 播放出来。
只有 App ID 还不能运行
必须先准备 2 个 Agora RTC Token、百炼 API Key 和 Workspace ID。没有全部配置时,
muxiva serve 会启动失败。请先逐项完成语音凭据配置清单。
你真正需要准备的东西
Agora 需要一个账号、App ID 和两个临时 RTC Token。Qwen 不需要下载 SDK, 只需要阿里云百炼 API Key 与 Workspace ID。Muxiva 会自动下载并校验 Agora macOS SDK、在隔离 Python 环境中安装 Qwen WebSocket 依赖,并为 Demo 2 安装锁定的 Pi TypeScript Agent 包。
0. 当前支持范围
- 一键安装路径已在 Apple Silicon macOS 上验证;Agora macOS SDK 固定为
4.6.2。 - Demo 2 要求 Node.js 22.19 或更高版本,用于受管理的 TypeScript Host 和 Pi。
- Qwen Node 当前使用阿里云百炼华北 2(北京)端点,API Key 和 Workspace 必须来自同一区域。
- Windows/其他平台目前需要从 Agora SDK 官方页面
手动下载,并把解压目录传给
setup.sh。
1. 安装 Muxiva 与官方 Node
先准备 Git、Rust、Python 3、Node.js 22.19+、CMake 3.20+ 与 Xcode Command Line Tools,然后运行:
git clone https://github.com/PiyotaHu/muxiva.git
cd Muxiva
cargo install --locked --path crates/muxiva-cli
./examples/voice-agent/setup.sh
最后一条命令会:
- 从 Agora 官方 macOS SDK 仓库 对应的官方 CDN 下载 RTC Basic 所需 XCFramework;
- 对每个压缩包执行 SHA-256 校验;
- 创建
examples/voice-agent/.muxiva/venv并安装websocket-client; - 拉取独立的 Pi 编码 Agent 仓库锁定版本,在禁用 Lifecycle Script 的前提下安装 npm 依赖,并执行适配器、Agent 与文件权限测试;
- 创建 Agent 默认编码工作区;
- 编译
agora.audio_source、agora.audio_sink、agora.data_source、agora.data_sink四个 C++ Node;它们共享一个 RTC Engine 和 Bot UID。
出现以下三行才代表安装完成:
[MUXIVA][READY] Native, Python, and TypeScript Agent Node Packs are installed.
[MUXIVA][AGORA] sdk=.../build/vendor/agora-macos-4.6.2
[MUXIVA][QWEN] python=.../.muxiva/venv/bin/python (no Qwen SDK download required)
[MUXIVA][AGENT] repository=https://github.com/PiyotaHu/muxiva-pi-agent.git ref=v0.2.1 commit=...
[MUXIVA][AGENT] workspace=.../.muxiva/workspaces/pi-agent permissions=list,read,search,create,replace,web-search
如果你已经手动下载 SDK,也可以运行:
2. 申请 Agora App ID 与 Token
如果这是第一次申请,请直接按Agora App ID、Certificate、Token Builder 每个输入框的逐项指南 操作。下面只是完成标准的摘要。
- 打开 Agora Console 并注册或登录。
- 进入 Projects,点击 Create New,认证方式选择 Secured mode: APP ID + Token。
- 复制项目的 App ID。
- 选一个 Channel 名称,例如
muxiva-demo。后面所有 Token 必须使用完全相同的名称。 - 按 Agora 官方的账号与临时 Token 指南 打开项目安全配置或 Agora Token Builder, 为同一个 Channel 生成两个短期 RTC Token:
| Studio 字段 | UID | 第一次运行建议角色 | 用途 |
|---|---|---|---|
| Browser UID / Token | 1001 |
Publisher | 浏览器采集麦克风并播放音频 |
| Muxiva Bot UID / Token | 2001 |
Publisher | 同一个 C++ RTC Engine 接收麦克风并发布助手音频 |
不要暴露 App Certificate
App Certificate 只用于服务端生成 Token。不要把它填进 Studio、网页或提交到 Git。 临时 Token 适合本地体验;生产环境必须部署自己的 Token Server。
3. 申请 Qwen 凭据
如果不熟悉百炼地域与业务空间,请直接按百炼 API Key 与 Workspace ID 逐项指南 操作。Key 与 Workspace ID 必须是华北 2(北京)同一业务空间的一对值。
- 打开阿里云百炼控制台,选择 华北 2(北京)并开通服务。
- 按官方获取 API Key指南创建 Key, 创建成功后立即保存明文。
- 按官方首次调用 Qwen 指南找到同一 Workspace 的 Workspace ID。
这里没有“Qwen SDK 下载”步骤。Muxiva 的 Python Node 直接使用官方 WebSocket/HTTP
协议。Realtime 图默认使用 qwen-audio-3.0-realtime-flash;级联图在 Qwen ASR 与
Qwen TTS 之间使用由 qwen-flash 驱动的 Pi 编码 Agent。它可以在
受限工作区真实读取、搜索、创建和修改文件,也能复用相同百炼凭据按需联网搜索并返回
来源;通用接入方法见
Agent 集成 SOP。
4. 选择 Studio 或 Headless 启动方式
先从示例创建本地凭据文件并填一次。它被 Git 忽略,之后 CLI 和 Studio 都会自动读取:
cp examples/voice-agent/.env.example examples/voice-agent/.env
# 编辑 examples/voice-agent/.env,填入第 2、3 节取得的值
muxiva doctor --voice
doctor 应显示 Agora Node Pack 为 mode=agora-native,并显示 Qwen Python 与 Pi
TypeScript Agent 已就绪。出现 MISSING 表示 .env 仍缺必填值,不是可以跳过的提示。
macOS 本地开发直接运行以下命令,默认打开 Studio;Windows Git Bash 使用相同命令,
PowerShell 可执行 muxiva studio examples/voice-agent/graph.json:
在 Studio 中选择模板、点击 Run,并通过 ◎ Observe 调试 Node 与 Edge。 在 Linux、Docker、SSH,或者需要验收前后端分离链路时,终端 A 显式启动 Headless Runtime:
终端 B 只启动网页静态文件:
打开 http://127.0.0.1:4173,Backend URL 使用 Runtime 打印的
http://127.0.0.1:8080,点击 Test connection,再开始通话。网页和 Runtime 是两个
独立进程;网页关闭不会停止 Graph,Graph 停止也不会由网页静态服务器接管。
run.sh 在 macOS/Windows Shell 默认 Studio、Linux 默认 Headless;--studio 和
--headless 可显式覆盖。无 GUI Linux、SSH、公网和 Docker 的完整命令见
Headless Runtime 与独立网页。项目 Voice Room 始终独立于 Studio;
完整浏览器通话使用 Headless 模式提供的 Client API。
Realtime 跑通后,再切换 Pi Agent Full-Duplex Cascade(Demo 2),观察 Qwen Server VAD + Streaming ASR → 有状态 TypeScript Agent 与 Tool Call → Speech Formatter → 可取消 Qwen TTS。聊天框保留 Agent 原始 Markdown,TTS 只接收不含强调符号、裸 URL、 代码块和表格的自然播报文本。 可以询问当前时间或今天的天气,强制触发真实 Tool Call。助手播放时重新开口: Voice Room 应立即显示打断状态,旧文字停止增长、旧语音停止播放,新一句转写和回答随后 进入同一会话。会话会持续运行,直到点击 End session。
当前 graph.json 是 Demo 2,默认使用 vad_threshold: 0.45。需要适配麦克风或房间时,可在 Studio 画布选择
qwen-vad-asr,修改 Configuration 中的数值,然后点击 Validate 和
Save graph。数值越低越灵敏,越高越能过滤低能量声音。
运行日志与链路定位
run.sh 会同时把终端输出保存到 examples/voice-agent/.muxiva/runtime.log。遇到“已经
连接但没有回复”时,按下面的顺序找第一个没有增长的指标:
Headless 模式先以终端和 runtime.log 定位;本地设计时可另开 Studio 使用 ◎ Observe
检查同一份 Graph。指标含义、阈值与日志过滤命令见可观测性与堵点定位。
- Voice Room 显示浏览器已加入、麦克风已发布;
- 说话时 MIC LEVEL 增长;连续五秒没有语音能量时页面会直接提示检查输入设备;
- 日志出现
[MUXIVA][AGORA][participant.joined] uid=1001; - 日志出现
[MUXIVA][AGORA][audio.received],Studio 的agora-input增长;在 Observe 点击agora-audio-source,input.audio_peak_pcm16说话时必须明显大于 0; - Demo 1 的 Qwen Realtime Node 先打印 Server VAD 的
speech_started/speech_stopped, 随后出现 ASR 和response.created;Demo 2 则检查transcript-to-agent、agent-to-speech-formatter、speech-formatter-to-tts; tts-audio和audio-to-room增长,浏览器听到回复。
第一个没有出现的步骤,就是故障所在层。凭据值不会写入日志。
Voice Room 从 Agora RTC 数据流接收消息,而不是读取 Studio NotificationBus;页面会把每轮对话
显示成聊天记录:用户 ASR 在右侧,Agent 流式回复在左侧。
Qwen 增量 ASR 使用 text + stash 作为实时预览,并在
conversation.item.input_audio_transcription.completed 到达后固定最终文本。Agora Bot
只消费远端 PCM,不在运行机器的扬声器播放用户声音;助手音频以 10 ms PCM 包匀速发布。
独立页面只通过 Headless Runtime 的 /api/v1/client/session 获取浏览器 RTC 启动配置。
该服务没有 Studio 的 Graph 或 Runtime 管理接口;生产网页应进一步替换为业务 Token Service。
5. 常见错误
| 现象 | 原因与处理 |
|---|---|
Agora SDK directory does not exist |
路径不是解压目录;macOS 直接重新运行无参数 setup.sh |
AgoraRtcKit.xcframework not found |
手动下载了错误平台或不完整包;使用一键下载命令 |
qwen-python ready=false |
没运行 setup.sh,或项目虚拟环境损坏;重新运行安装 |
pi-typescript-agent ready=false |
安装 Node.js 22.19+,再运行 setup.sh 安装锁定的 Pi 包 |
installed Agora Node Packs are older |
先停止正在运行的 Studio,执行一次 ./examples/voice-agent/setup.sh,再重新启动;run.sh 会拒绝加载过期 Native 代码,不再静默使用旧产物 |
| Qwen 返回鉴权/模型错误 | API Key、Workspace ID、模型必须属于华北 2(北京)同一 Workspace |
| Agora 加入 Channel 失败 | App ID、Channel、UID 必须与生成该 Token 时完全一致,Token 也不能过期 |
| 页面没有麦克风 | 浏览器未授权;在浏览器站点权限中允许本地 Studio 使用麦克风 |
| 有 RTC Frame 但完全没反应 | 先看 Voice Room MIC LEVEL,再看 Observe 的 input.audio_peak_pcm16;始终接近 0 表示发布的是静音或选错输入设备 |
顶部没有 ◎ Observe |
查看启动日志 [MUXIVA][CLI];源码开发必须使用当前仓库 target/.../muxiva,重新运行 setup.sh 会自动构建并选择它 |
| 清晰听到自己的声音 | 更新 Muxiva 并重新运行 setup.sh 编译 Agora Node Pack;Bot 日志必须显示 local_remote_playback=silenced-after-mix |
| 有文字但没有语音 | 查找 [MUXIVA][AGORA][audio.published];没有该日志说明 Qwen 未产生音频,有日志则检查浏览器是否订阅 Bot 音轨 |
| 页面没有用户 ASR | 查找 Qwen input_audio_transcription.completed;新版页面显示 text + stash 实时预览和最终 transcript |
6. 工程验收
不使用凭据时,可以验证代码、Node 边界与动态 ABI:
它们不会伪装成真实通话。完整验收标准是:真实加入 Agora Channel、真实麦克风输入、 Qwen 返回字幕和语音,并且在播放期间成功插话打断。