异步语音通知(notify)
notify 消息允许云端在设备空闲时播放一条单向语音通知。它不会打开对话音频通道,也不会开启麦克风上行。要开始对话,仍然需要用户明确的唤醒动作。
消息格式
云端通过设备当前协议的控制连接发送下面的 JSON。对于 MQTT 设备,就是现有的 MQTT 控制主题:
{
"type": "notify",
"audio_url": "https://cdn.example.com/audio/task-complete.ogg",
"subtitles": [
{
"start_ms": 0,
"text": "Your task is complete."
},
{
"start_ms": 1800,
"text": "The result has been saved."
}
]
}audio_url 为必填,http:// 和 https:// 均可接受。HTTP 便于局域网开发,生产环境可以在生成 URL 时强制使用 HTTPS。
subtitles 为可选。每个条目包含媒体起始时间(毫秒)和要显示的文本。设备按 start_ms 排序,仅在播放进度越过新的字幕条目时更新显示。
该消息没有确认、通知 ID、状态、类型或过期字段。投递是尽力而为的,且只对在线设备生效。
音频响应
audio_url 必须返回成功的 2xx 响应,内容为单流、单声道的 Ogg Opus 文件。支持带 Content-Length 或分块传输编码的响应。设备不会跟随重定向。
文件按增量方式读取。设备不会按完整响应长度分配内存,也不会在播放前下载完整文件。通知流式播放使用现有的有界 HTTP 响应队列、2 KB 的 Ogg 逻辑包缓冲、共享的 20 包 Opus 解码队列以及现有的两帧 PCM 播放队列。在固件默认的 60 ms 包时长下,解码队列相当于 1.2 秒。这些缓冲提供 TCP 反压,使该功能可以在没有 PSRAM 的设备上使用。
在使用独立 LiteAudioEngine WakeNet 的设备上,通知播放期间会释放 WakeNet 资源,设备回到 Idle 时再重新创建。基于 AFE 的设备保持原有的本地唤醒行为。
Opus 包时长从 Opus TOC 字节读取,而不是由 MQTT 消息提供。固件解码器支持的 5 ms 至 120 ms 整数包时长均可接受。当前实现会拒绝立体声流、检测到的 Ogg 或 Opus 结构错误、不完整的流、超长的逻辑包以及 2.5 ms 的包。
设备行为
设备仅在 Idle 状态下接受 notify,随后执行以下动作:
- 进入内部的
Notifying状态,并将开发板切换到性能模式。 - 关闭常规语音处理和麦克风上行。
- 清除之前的播放内容,并将内置提示音加入队列。
- 在后台任务中发起一次 HTTP GET。
- 增量解复用 Ogg 包,并直接送入现有的 Opus 解码队列。
- 按照到达音频输出任务的 Opus 包的媒体位置显示字幕。
- 仅在 HTTP 流成功结束且所有排队音频播放完毕后才回到
Idle。
提示音在 HTTP 任务启动之前就已入队,因此远程音频不会早于它播放。HTTP 连接建立仍会与提示音的实际播放重叠。
如果在远程音频开始播放后、HTTP 流结束前,所有播放队列都被清空,设备会记录日志 Notification playback underrun #<count> at <position> ms。从提示音到流的切换以及正常播放结束,都不会被报告为欠载。
设备不会打开 UDP 音频通道、发送 start-listening,也不会自动进入 Listening。基于 AFE 的设备在播放期间可以继续本地唤醒词检测。没有播放回声消除的设备保持现有的说话模式唤醒行为;硬件唤醒控制仍然可以取消通知。
唤醒动作会取消 HTTP 生产者、清除已排队的通知音频,并继续走正常的唤醒流程。网络中断、HTTP 错误和无效音频同样会取消播放并让设备回到 Idle。设备忙碌时收到的第二条通知会被忽略。
xz-mqtt 转发
xz-mqtt 通过其现有的 Redis RPC 方法转发该消息:
{
"method": "forward",
"clientId": "device-client-id",
"params": {
"type": "notify",
"audio_url": "https://cdn.example.com/audio/task-complete.ogg",
"subtitles": [
{
"start_ms": 0,
"text": "Your task is complete."
}
]
}
}RPC 结果包含 MQTT 发送操作返回的布尔值:
{
"success": true
}该结果表示 xz-mqtt 已把发布消息写入当前在线的设备连接,并不确认设备已收到或已播放。xz-mqtt 不会创建 UDP 会话、不会启动对话桥接、不会代理 Ogg 文件,也不会为离线设备保留通知。