---
summary: "macOS 通话覆盖行为和流式实时网关中继路径"
read_when:
- "在 macOS 上使用 Talk"
- "在 Mac 上启用实时网关中继"
- "诊断无法启动的实时会话"
title: "谈macOS和网关继电器"
sidebarTitle: "macOS 和网关继电器"
---
## 行为(macOS)
- 在 Talk 模式启用时始终显示覆盖层。
- **倾听 → 思考 → 说话** 阶段转换。
- 阶段通知是尽力而为的:失败的更新不会启动本地网关或重新启动其隧道。开始通话会保留正常的连接恢复。
- 在短暂停顿(静默窗口)时,当前转录内容会被发送。
- 回复会写入 WebChat(与输入相同)。
- Talk 观察接受的代理运行,直到网关报告完成,然后说出该运行的完整答复。缓慢的本地模型不会使单独的应用程序端响应窗口过期。停止仍然可以防止延迟播放。
- **语音打断**(默认开启):如果用户在助手说话时开口,播放会停止,并记录打断时间戳供下一个提示使用。
## 通过网关中继进行实时通话 (macOS)
macOS 默认为上面的本机路径:Apple 语音识别、网关聊天和 `talk.speak` 播放。仅当 `talk.realtime` 同时选择所有这三个时,它才会切换到流式实时会话:
| 键 | 所需值 |
| ----------- | --------------- |
| `mode` | `realtime` |
| `transport` | `gateway-relay` |
| `brain` | `agent-consult` |
任何其他组合(包括部分设置的组合)都会保留本机路径。
```json5
{
talk: {
realtime: {
provider: "openai",
providers: {
openai: {
model: "gpt-realtime-2.1",
speakerVoice: "cedar",
},
},
mode: "realtime",
transport: "gateway-relay",
brain: "agent-consult",
},
},
}
```
Mac 还必须通过 **设置 > 语音和通话 > 使用实时网关中继** 在本地选择加入。此首选项默认关闭并保留在该 Mac 上;单独的网关配置永远不会激活流路径。保留 `transport: "webrtc"` 用于浏览器或 iOS 客户端拥有的会话;仅当配置明确选择 `gateway-relay` 时,macOS 才使用继电器。
网关还必须为 `talk.catalog` 中选定的提供商通告 `gateway-relay` 和 `agent-consult`。实时需要macOS 26或更高版本,匹配语音唤醒;在旧版本上,通话和语音唤醒控件不可用。
在 Apple 客户端上,中继播放将保持活动状态,直到设备完成排队的音频,而不是估计持续时间到期。完成后会出现播放确认。回合制提供商保留设备路由麦克风回声抑制和本地语音中断。在 iPhone 上,当内置扬声器或接收器上开始会话时,麦克风和中继播放与语音处理共享一个音频引擎,因此回声消除功能也会使扬声器上的麦克风保持打开状态,并且本地语音中断会在那里工作。在耳机上启动的会话保留单独的引擎,无需语音处理。如果语音处理不可用,内置扬声器会在播放期间回退到抑制麦克风输入。 GPT Live 等连续提供者在播放期间保持麦克风输入打开,并自行处理语音中断。 Apple 客户端使用所选提供商的 `talk.catalog` 功能;如果目录访问不可用,他们会将语音中断留给提供商。
显式停止 GPT 实时输出会结束语音会话。 Apple 客户端保留该停止而不是自动重新连接。在 macOS 上,暂停会使 Talk 暂停;如果提供者关闭了暂停的会话,则恢复将启动一个新的会话。普通连接失败仍然使用下面的恢复路径。使用耳机以避免扬声器音频反馈到开放的麦克风中。
### 实时无法启动时
说话永远不会闲着。如果中继无法启动(无网关路由、拒绝的凭据或不受支持的模型),则会记录失败,覆盖层会显示原因,并且 Talk 会回退到该会话的本机语音路径。
一旦会话运行,断开的中继就会按照有限重试计划重新连接(大约 0.5 秒,然后 2 秒)。如果这些尝试都用尽,覆盖层会报告 `Realtime disconnected repeatedly — using native speech`,并且下一次启动会绕过实时。如果在会话中丢失麦克风,则会关闭中继并采取相同的路线。
继电器输出取消是回合范围的。客户端从 `talk.event` 音频包络复制当前的 `turnId`。匹配的 ID 返回 `applied`,过时的 ID 返回 `stale`,没有活动回合的会话返回 `idle`。省略 `turnId` 的旧客户端仍会取消当前回合:
```json
{
"method": "talk.session.cancelOutput",
"params": {
"sessionId": "relay-session-id",
"turnId": "turn-7",
"reason": "barge-in"
}
}
```