tuyaos_demo_wukong_ai对话出现ASR返回空文本
使用TuyaOS-3.13.6版本tuyaos_demo_wukong_ai例程,
修改PID/UUID/AUTHKEY后编译烧录T5-BOARD-V101开发板测试,长按触发方式,出现对话几轮就出现一起卡在上传中的异常,有个现象是复位或上电后第一轮对话都正常,后面测试在10轮内异常必现,同一块开发板使用TUYAOPEN固件测试测正常。
使用TuyaOS-3.13.6版本tuyaos_demo_wukong_ai例程,
修改PID/UUID/AUTHKEY后编译烧录T5-BOARD-V101开发板测试,长按触发方式,出现对话几轮就出现一起卡在上传中的异常,有个现象是复位或上电后第一轮对话都正常,后面测试在10轮内异常必现,同一块开发板使用TUYAOPEN固件测试测正常。
你好!日志我下载下来仔细看了,问题已定位,不是 ASR 偶发错误,是 demo 状态机的一个明确缺陷——当 ASR 文本为空时,状态机会卡死在 UPLOAD,必须复位才能恢复。这就是你看到的"几轮后必现卡在上传中"。
【现象核对】
日志(putty_20260517_140729.log)三轮对话全部出现:
Code: Select all
[14:07:52.135][tuya_ai_agent.c:506] ASR text: ← 云端识别返回空
[14:07:52.135][tuya_ai_agent.c:717] invalid text data 0x60c22559 0
[14:08:24.438] ASR text: ← 第二轮还是空
[14:08:46.523] ASR text:
[14:08:46.523][wukong_ai_agent.c:202] ignored alert: 7 ← AT_PLEASE_AGAIN 被吞掉
WIFI_TX 持续 31KB/s 上传,WIFI_RX = 0KB/s——设备在传,但走 alert 路径不是 text 路径。第 1/2 轮还能勉强走完(因为 mode_hold 收到了后续 type=2 事件转回 IDLE),第 3 轮没收到,就卡在 UPLOAD 状态。
【根因——一个被吞掉的事件】
链路追到底是这样的:
1. SDK 侧(components/svc_ai_agent/src/tuya_ai_agent.c:506-510):
Code: Select all
STATIC OPERATE_RET __ai_parse_asr(ty_cJSON *root, BOOL_T eof)
{
ty_cJSON *node = ty_cJSON_GetObjectItem(root, "text");
PR_DEBUG("ASR text: %s", ty_cJSON_GetStringValue(node));
if (eof && (!node || !node->valuestring || strlen(node->valuestring) == 0)) {
tuya_ai_output_alert(AT_PLEASE_AGAIN); ← 空文本走 alert,不走 text
} else {
tuya_ai_output_text(AI_TEXT_ASR, node, eof);
}
return OPRT_OK;
}
ASR 文本为空时,SDK 只触发 AT_PLEASE_AGAIN alert,不会调用 text 回调。所以 wukong_ai_skills.c:94 那条 WUKONG_AI_EVENT_ASR_EMPTY 派发路径根本走不到。
2. demo 侧(apps/tuyaos_demo_wukong_ai/src/wukong/wukong_ai_agent.c:199-207):
Code: Select all
STATIC OPERATE_RET __wukong_ai_agent_alert_cb(AI_ALERT_TYPE_E type)
{
if (type == AT_PLEASE_AGAIN) {
PR_DEBUG("ignored alert: %d", type); ← 直接吞掉不通知
return OPRT_OK;
}
wukong_ai_event_notify(WUKONG_AI_EVENT_PLAY_ALERT, (VOID *)(unsigned long)type);
return OPRT_OK;
}
3. 状态机侧(apps/tuyaos_demo_wukong_ai/src/mode/wukong_ai_mode_hold.c:383-388):
状态机只在收到 WUKONG_AI_EVENT_ASR_EMPTY/ASR_ERROR 才会从 UPLOAD 转回 IDLE:
Code: Select all
case WUKONG_AI_EVENT_ASR_EMPTY:
case WUKONG_AI_EVENT_ASR_ERROR:
{
CHAT_SUB_STATE_CHANGE(AI_CHAT_SUB_HOLD, s_ai_hold.state, AI_CHAT_IDLE);
}
break;
结论:SDK 触发 alert → demo 把 alert 吞了 → 状态机收不到 ASR_EMPTY → 卡 UPLOAD
hold/free/oneshot/picture/translate/wakeup 六种模式都受影响(每个 mode 文件都有 ASR_EMPTY 处理但都进不来)。
【为什么 TUYAOPEN 正常 / 第一轮正常】
TUYAOPEN 正常:TUYAOPEN 用的不是 wukong_ai 这套 demo 框架,alert/event 拓扑不同,没踩这个坑。
第一轮正常:你日志里第 1/2 轮 ASR 也是空,但 SDK 在 alert 之后还会跟一个 type=2 的 ai event(
Code: Select all
tuya_ai_agent.c:153 [====ai event cb====] type:2),状态机 mode_hold.c:487 case 把 SPEAK→IDLE 兜住了。第 3 轮(14:08:42)那个 type=2 没来或来得太晚,就永久卡死。这是「侥幸 + 不稳定」,不是真没问题。
【修复——3 行代码】
修改 apps/tuyaos_demo_wukong_ai/src/wukong/wukong_ai_agent.c 的 __wukong_ai_agent_alert_cb:
Code: Select all
STATIC OPERATE_RET __wukong_ai_agent_alert_cb(AI_ALERT_TYPE_E type)
{
if (type == AT_PLEASE_AGAIN) {
PR_DEBUG("ASR empty (alert: %d), notify state machine", type);
// 关键修复:把 AT_PLEASE_AGAIN 转成 ASR_EMPTY 事件派发出去
// 否则 mode_hold/free/oneshot 等状态机都会卡在 UPLOAD
WUKONG_AI_TEXT_T text = {0};
wukong_ai_event_notify(WUKONG_AI_EVENT_ASR_EMPTY, &text);
return OPRT_OK;
}
wukong_ai_event_notify(WUKONG_AI_EVENT_PLAY_ALERT, (VOID *)(unsigned long)type);
return OPRT_OK;
}
改完重编烧录,连续按 30 轮,确认:
ASR 为空时不再卡 UPLOAD,会回到 IDLE 等下一次按键
如果想给用户提示音,可以在 demo 层调一下 wukong_ai_agent_cloud_alert(AT_PLEASE_AGAIN) 走 cmd:5 播报"请再说一遍"
【为什么 ASR 经常返回空——附带建议】
虽然主因是 demo bug,但 ASR 三轮都返空说明上行音频质量也有问题,建议同步排查:
AEC/VAD 参数:日志里 wukong_audio_aec_vad.c:131 rnn_date_version: 25082101,rnn vad 工作但可能把人声当噪声滤掉。试试调高 VAD 灵敏度
MIC 增益:T5-BOARD-V101 默认 MIC 增益偏低,距离麦克风超过 50cm 容易拾不到清晰人声
上传 codec:日志 [ptype 31 upload stream] 是音频编码上传,确认 wukong_audio_input_board 里 codec 配置和云端 ASR 期望的采样率/格式一致(一般 16kHz/16bit/单声道)
录一段离线 PCM:在 mic 输入回调里把音频 dump 到本地,回放检查是不是录到的就是噪声
短期靠上面的 demo 修复消除"卡死",长期建议把 AT_PLEASE_AGAIN 在 SDK 侧也补一个 tuya_ai_output_text(AI_TEXT_ASR, "", TRUE) 让两条路径统一,避免应用层各自处理。
参考代码:tuyaos-ai @ release/3.13.6 / components/svc_ai_agent/src/tuya_ai_agent.c:506 / apps/tuyaos_demo_wukong_ai/src/wukong/wukong_ai_agent.c:199 / apps/tuyaos_demo_wukong_ai/src/mode/wukong_ai_mode_hold.c:383