T1_FIX

Bug 修复说明

一、修改背景

本次修复主要解决以下问题:

  1. music/story skill 返回 MP3 URL 后播放时机不合理;

  2. 打断时可能残留播放状态或缓存 URL;

  3. ADC 采样可能干扰在线 MP3 播放;

  4. 存在潜在内存泄漏风险。

修复目标:

  • 将 URL 获取与播放动作解耦;

  • 播报结束后再启动在线音乐播放;

  • 打断时彻底释放资源;

  • 避免 ADC 干扰音乐播放。


二、tuya_audio.c 修改

1

2.1 新增全局变量

STATIC CHAR_T* last_skill_mp3_url = NULL;

用于缓存 music/story skill 返回的 MP3 URL。

2

2.2 新增函数

判断是否存在待播放 URL

bool_t tuya_audio_has_mp3_playurl() {
    return last_skill_mp3_url != NULL;
}

启动在线 MP3 播放并释放缓存

void tuya_audio_start_playurl() {
    if (last_skill_mp3_url) {
        online_mp3_player_start(last_skill_mp3_url);
        tal_system_sleep(10);
        free(last_skill_mp3_url);
        last_skill_mp3_url = NULL;
        TAL_PR_DEBUG("free last_skill_mp3_url ...");
    }
}
3

2.3 修改 skill 解析逻辑(music/story 分支)

else if (strcmp(code, "music") == 0 || strcmp(code, "story") == 0) {
    const CHAR_T* url;
    ty_cJSON* general, * data, * audios, * audio_item, * url_node;

    if (!(general = ty_cJSON_GetObjectItem(skill, "general")) ||
        !(data = ty_cJSON_GetObjectItem(general, "data")) ||
        !(audios = ty_cJSON_GetObjectItem(data, "audios")) ||
        !ty_cJSON_IsArray(audios) ||
        !(audio_item = ty_cJSON_GetArrayItem(audios, 0)) ||
        !(url_node = ty_cJSON_GetObjectItem(audio_item, "url")) ||
        !(url = ty_cJSON_GetStringValue(url_node)) || url[0] == '\0') {

        TAL_PR_WARN("%s skill missing or invalid url", code);

    } else {

        TAL_PR_DEBUG("%s skill url: %s", code, url);

        size_t len = strlen(url) + 1;

        if (last_skill_mp3_url) {
            free(last_skill_mp3_url);
            last_skill_mp3_url = NULL;
        }

        last_skill_mp3_url = malloc(len);
        if (last_skill_mp3_url) {
            memcpy(last_skill_mp3_url, url, len);
            TAL_PR_DEBUG("%s last_skill_mp3_url: %s", code, last_skill_mp3_url);
        }
    }
}

说明:将解析到的 URL 缓存到全局变量,不在此处立即启动播放,达到“URL 获取与播放动作解耦”的目的。

4

2.4 重构 ty_ai_chat_interrupt()

OPERATE_RET ty_ai_chat_interrupt(void)
{
    OPERATE_RET rt = OPRT_OK;

    if (tuya_audio_has_mp3_playurl()) {
        free(last_skill_mp3_url);
        last_skill_mp3_url = NULL;
    }

    if (is_online_mp3_playing || online_mp3_player_is_busy()) {
        TAL_PR_DEBUG("Interrupt: stopping online MP3 player");
        online_mp3_player_stop();
    }

    sg_audio_ctx.is_tts_streaming = FALSE;
    ai_audio_player_stop_playing_timer();

    if (s_chat_session_id[0] == '\0') {
        TAL_PR_ERR("ai chat interrupt ignored, chat session id or event id is null");
        return OPRT_COM_ERROR;
    }

    if (s_event_id[0] != '\0') {
        TAL_PR_NOTICE("ai chat interrupt, event_id:%s", s_event_id);
        rt = tuya_ai_event_chat_break(s_chat_session_id, s_event_id, NULL, 0);
        if (rt != OPRT_OK) {
            TAL_PR_ERR("chat break failed, rt:%d", rt);
        }
    }

    if (s_cur_stream_event_id[0] != '\0') {
        if (strcmp(s_event_id, s_cur_stream_event_id) != 0) {
            TAL_PR_NOTICE("ai chat interrupt, event_id:%s", s_cur_stream_event_id);
            rt = tuya_ai_event_chat_break(s_chat_session_id, s_cur_stream_event_id, NULL, 0);
            if (rt != OPRT_OK) {
                TAL_PR_ERR("chat break failed, rt:%d", rt);
            }
            memset(s_cur_stream_event_id, 0, AI_UUID_V4_LEN);
        }
    }

    return rt;
}

说明:打断处理时会释放缓存的 URL,并停止在线 MP3 播放器,防止残留播放状态或内存泄漏。


三、tuya_trigger.c 修改

说明:当播放结束通知到来时,检查是否存在缓存的 MP3 URL;若存在则启动播放并在启动后释放缓存,保证在线音乐在播报结束后才开始。


四、tuya_ai_battery.c 修改(定位到 static void __voltage_convert_task(void* arg))

在主循环 while (is_running) 中,添加在线 MP3 播放的让步判断:

说明:在线 MP3 播放期间,ADC 采样任务主动睡眠更长时间,避免 ADC 干扰音乐播放。


五、整体行为变化总结

  1. music/story URL 先缓存,不立即播放。

  2. 播报结束后自动播放缓存的在线 MP3(由播放结束通知触发)。

  3. 打断时彻底释放缓存并停止播放器,避免残留状态或内存泄漏。

  4. 在线 MP3 播放期间,ADC 采样任务主动让步,减少干扰。


文档生成时间:自动生成

Last updated