From: hcj <1224667075@qq.com> Date: Mon, 15 Sep 2025 07:59:26 +0000 (+0800) Subject: 修改chat结果会有表情 X-Git-Tag: leiniao_debug_1.0.0_20250922_020716~13^2~31^2~3 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=720f72807f4eb46ae1e67611980199e6edd05b08;p=mirrors%2FFD230.git 修改chat结果会有表情 --- diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceModel.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceModel.cpp index b40612b9d..f579976cc 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceModel.cpp +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceModel.cpp @@ -34,7 +34,9 @@ #include "custom_runtime.h" #include "voice_call_volte_sample_wrapper.h" #include -#include +#include "websocket_server_manager.h" +#include "font/ui_font.h" + namespace OHOS { // 声明定时器变量 @@ -184,8 +186,8 @@ namespace OHOS WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetSelect4gorbt() == AI_SELECT_4G"); if (GetInit_4gai_task()) { - // uapi_UI_start_asr(GetCurUsing4GAiModelType()); - uapi_start_asr_StartTranscription(); + uapi_start_AI_asr(); + } else { @@ -974,7 +976,7 @@ namespace OHOS WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "停止录音"); if (GetSelect4gorbt() == AI_SELECT_4G) // 选的是4G需要关闭asr { - uapi_stop_asr_StopTranscription(); + uapi_stop_AI_asr(); } else if (GetSelect4gorbt() == AI_SELECT_BT) { @@ -1960,21 +1962,174 @@ extern "C" #ifdef BLE_INSTRUCT -#include "bleEvent.h" -#include "bleInstruct.h" - - void ble_set_ai_Question_str_(char *buf) - { - OHOS::AiVoiceModel::GetInstance().SetUserQuestionStr(std::string(buf)); - } - - void ble_set_ai_Answer_str_(char *buf, uint8_t type) - { - OHOS::AiVoiceModel::GetInstance().SetAiAnswerStrStr(std::string(buf), type); - } +/** + * @brief 过滤字符串中无法显示的文字(使用GetGlyphPathData接口) + * @param input_str 输入字符串 + * @param output_str 输出字符串缓冲区 + * @param max_len 输出缓冲区最大长度 + * @return 过滤后的字符串长度,-1表示失败 + */ +int32_t chat_filter_unsupported_chars(const char *input_str, char *output_str, uint32_t max_len) +{ + if (input_str == NULL || output_str == NULL || max_len == 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid parameters for asr_filter_unsupported_chars\n"); + return -1; + } + + // 初始化输出缓冲区 + memset(output_str, 0, max_len); + + uint32_t input_len = strlen(input_str); + uint32_t output_pos = 0; + uint32_t input_pos = 0; + + while (input_pos < input_len && output_pos < max_len - 1) { + uint32_t char_start = input_pos; + uint32_t char_end = input_pos; + + // 获取下一个UTF-8字符 + uint32_t unicode_char = 0; + bool valid_utf8 = false; + + // 简单的UTF-8解码 + if ((unsigned char)input_str[input_pos] < 0x80) { + // ASCII字符 + unicode_char = (unsigned char)input_str[input_pos]; + char_end = input_pos + 1; + valid_utf8 = true; + } else if ((unsigned char)input_str[input_pos] >= 0xC0 && (unsigned char)input_str[input_pos] < 0xE0) { + // 2字节UTF-8字符 + if (input_pos + 1 < input_len) { + unicode_char = ((unsigned char)input_str[input_pos] & 0x1F) << 6 | + ((unsigned char)input_str[input_pos + 1] & 0x3F); + char_end = input_pos + 2; + valid_utf8 = true; + } + } else if ((unsigned char)input_str[input_pos] >= 0xE0 && (unsigned char)input_str[input_pos] < 0xF0) { + // 3字节UTF-8字符 + if (input_pos + 2 < input_len) { + unicode_char = ((unsigned char)input_str[input_pos] & 0x0F) << 12 | + ((unsigned char)input_str[input_pos + 1] & 0x3F) << 6 | + ((unsigned char)input_str[input_pos + 2] & 0x3F); + char_end = input_pos + 3; + valid_utf8 = true; + } + } else if ((unsigned char)input_str[input_pos] >= 0xF0 && (unsigned char)input_str[input_pos] < 0xF8) { + // 4字节UTF-8字符 + if (input_pos + 3 < input_len) { + unicode_char = ((unsigned char)input_str[input_pos] & 0x07) << 18 | + ((unsigned char)input_str[input_pos + 1] & 0x3F) << 12 | + ((unsigned char)input_str[input_pos + 2] & 0x3F) << 6 | + ((unsigned char)input_str[input_pos + 3] & 0x3F); + char_end = input_pos + 4; + valid_utf8 = true; + } + } + + if (!valid_utf8) { + // 无效的UTF-8字符,跳过 + input_pos++; + continue; + } + + // 使用GetGlyphPathData接口检查字符是否可以在字体中显示 + bool char_supported = true; + + // 对于ASCII字符,直接支持 + if (unicode_char < 0x80) { + char_supported = true; + } else { + // 使用字体引擎检查字符是否支持 + OHOS::UIFont *fontEngine = OHOS::UIFont::GetInstance(); + if (fontEngine != NULL) { + // 使用GetGlyphPathData检查字符是否支持 + OHOS::GlyphPathData path; + if (!fontEngine->GetGlyphPathData(unicode_char, 0, path)) { + // 字符不支持,标记为不支持 + char_supported = false; + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Character 0x%X not supported by font engine\n", unicode_char); + } else { + // 字符支持 + char_supported = true; + } + } else { + // 字体引擎不可用,使用简化的字符范围检查 + if (unicode_char >= 0x4E00 && unicode_char <= 0x9FFF) { + // 中文字符范围 + char_supported = true; + } else if (unicode_char >= 0xAC00 && unicode_char <= 0xD7AF) { + // 韩文字符范围 + char_supported = true; + } else if (unicode_char >= 0x3040 && unicode_char <= 0x309F) { + // 平假名 + char_supported = true; + } else if (unicode_char >= 0x30A0 && unicode_char <= 0x30FF) { + // 片假名 + char_supported = true; + } else if (unicode_char >= 0x2000 && unicode_char <= 0x206F) { + // 标点符号 + char_supported = true; + } else { + // 其他字符,标记为不支持 + char_supported = false; + } + } + } + + if (char_supported) { + // 字符支持,复制到输出缓冲区 + uint32_t char_len = char_end - char_start; + if (output_pos + char_len < max_len) { + memcpy(&output_str[output_pos], &input_str[char_start], char_len); + output_pos += char_len; + } else { + break; // 输出缓冲区已满 + } + } else { + // 字符不支持,跳过不支持的字符 + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Unsupported character: 0x%X, skipping\n", unicode_char); + } + + input_pos = char_end; + } + + // 确保输出字符串以null结尾 + output_str[output_pos] = '\0'; + + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Filtered string: '%s' -> '%s' (length: %d)\n", + input_str, output_str, output_pos); + + return output_pos; +} +/** + * @brief 过滤chat结果中的无法显示字符 + * @param result chat识别结果字符串 + * @return 过滤后的字符串长度,-1表示失败 + */ +int32_t chat_filter_result_chars(char *result) +{ + if (result == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, " result string is NULL\n"); + return -1; + } + + uint32_t max_len = strlen(result) + 1; + char *temp_buffer = (char *)malloc(max_len); + if (temp_buffer == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to allocate memory for temp buffer\n"); + return -1; + } + + int32_t filtered_len = chat_filter_unsupported_chars(result, temp_buffer, max_len); + if (filtered_len >= 0) { + strcpy(result, temp_buffer); + } + + free(temp_buffer); + return filtered_len; +} - #ifdef BLE_INSTRUCT #include "bleEvent.h" #include "bleInstruct.h" @@ -1987,6 +2142,7 @@ extern "C" void ble_set_ai_Answer_str_(char *buf,uint8_t type) { +chat_filter_result_chars(buf); OHOS::AiVoiceModel::GetInstance().SetAiAnswerStrStr(std::string(buf),type); } diff --git a/code/sdk/zhihui/ai_old/ai_old_at_cmd.cpp b/code/sdk/zhihui/ai_old/ai_old_at_cmd.cpp index 17743ea46..9e665a652 100644 --- a/code/sdk/zhihui/ai_old/ai_old_at_cmd.cpp +++ b/code/sdk/zhihui/ai_old/ai_old_at_cmd.cpp @@ -366,7 +366,7 @@ static uint32_t StartTranscription(uint8_t *para, uint32_t paraLen, char *strCom printf("CAT1TEST ATCMD Convert Command Failed\n"); return ERRCODE_FAIL; } - uapi_start_asr_StartTranscription(); + uapi_start_AI_asr(); return 0; } @@ -382,7 +382,7 @@ static uint32_t STOPTranscription(uint8_t *para, uint32_t paraLen, char *strComm printf("CAT1TEST ATCMD Convert Command Failed\n"); return ERRCODE_FAIL; } - uapi_stop_asr_StopTranscription(); + uapi_stop_AI_asr(); return 0; } extern void msleep(uint32_t ms); diff --git a/code/sdk/zhihui/ai_old/asr_websocket_server.cpp b/code/sdk/zhihui/ai_old/asr_websocket_server.cpp index d15c2143d..683483971 100644 --- a/code/sdk/zhihui/ai_old/asr_websocket_server.cpp +++ b/code/sdk/zhihui/ai_old/asr_websocket_server.cpp @@ -112,19 +112,6 @@ bool asr_ws_url_init(char * put_buf) } } -/** - * @brief ASR结果分析 - */ -bool asr_result_analysis(char *buf) -{ - // 这里可以添加ASR结果解析逻辑 - if (buf && strlen(buf) > 0) { - strncpy(result_str_asr, buf, AI_RESULT_STR_LEN - 1); - result_str_asr[AI_RESULT_STR_LEN - 1] = '\0'; - return true; - } - return false; -} /** * @brief 启动ASR服务 @@ -329,8 +316,7 @@ ASR_START: last_activity = (uint32_t)osKernelGetTickCount(); if (msg_type == WS_TEXT) { - printf("ASR text data received: %s\n", asr_recv_buf); - asr_result_analysis(asr_recv_buf); + } else if (msg_type == WS_BINARY) { printf("ASR binary data received: %d bytes\n", len); send_msg_data_into_Ai_msg_queue((uint8_t *)asr_recv_buf, len, 100); @@ -544,7 +530,66 @@ asr_event_type_t aer_result_analysis(char *buf, asr_result_output_t *output) +void uapi_stop_asr_StopTranscription(WebSocketClient *client) +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"uapi_stop_asr_StopTranscription \n"); + + if (client == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ASR client is NULL, cannot stop ASR\n"); + return; + } + + char *jsonString ="{\"header\":{\"event\":\"StopTranscription\",\"trace_id\":\"3fa6b9e6a30b407ea38ad7ae69e6c291\"}}"; + + if (send_websocket_message(client,( uint8_t *)jsonString,strlen(jsonString),WS_TEXT)==0) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"send_websocket_message succ 0\n"); + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"send_websocket_message erro\n"); + } +} + + +void uapi_start_asr_StartTranscription(WebSocketClient *client) +{ + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"uapi_start_asr_StartTranscription \n"); + + if (client == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ASR client is NULL, cannot start ASR\n"); + return; + } + + char *jsonString = "{\"header\":{\"event\":\"StartTranscription\",\"trace_id\":\ + \"\"},\"payload\":{\"format\":\"MP3\",\"sample_rate\":16000}}"; + + if (send_websocket_message(client,( uint8_t *)jsonString,strlen(jsonString),WS_TEXT) == 0) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ASR start message sent successfully\n"); + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"ASR start message send failed\n"); + } +} +/* + * 使用示例: + * + * // 启动ASR转录 + * WebSocketClient *client = get_asr_client(); // 获取客户端 + * uapi_start_asr_StartTranscription(client); + * + * // 或者使用全局客户端 + * uapi_start_asr_StartTranscription(g_asr_server->client); + * + * // 停止ASR转录 + * uapi_stop_asr_StopTranscription(client); + * + * // 或者使用全局客户端停止 + * uapi_stop_asr_StopTranscription(g_asr_server->client); + */ #ifdef __cplusplus diff --git a/code/sdk/zhihui/ai_old/asr_websocket_server.h b/code/sdk/zhihui/ai_old/asr_websocket_server.h index 1448dec1d..bc616dac2 100644 --- a/code/sdk/zhihui/ai_old/asr_websocket_server.h +++ b/code/sdk/zhihui/ai_old/asr_websocket_server.h @@ -138,6 +138,18 @@ errcode_t asr_server_init(void); */ void asr_server_deinit(void); +/** + * @brief 启动ASR转录 + * @param client WebSocket客户端 + */ +void uapi_start_asr_StartTranscription(WebSocketClient *client); + +/** + * @brief 停止ASR转录 + * @param client WebSocket客户端 + */ +void uapi_stop_asr_StopTranscription(WebSocketClient *client); + /* 全局变量声明 */ extern char *asr_recv_buf; extern WebSocketClient *asr_client; diff --git a/code/sdk/zhihui/ai_old/tts_websocket_server.cpp b/code/sdk/zhihui/ai_old/tts_websocket_server.cpp index b6fbaf756..647fb75a2 100644 --- a/code/sdk/zhihui/ai_old/tts_websocket_server.cpp +++ b/code/sdk/zhihui/ai_old/tts_websocket_server.cpp @@ -776,9 +776,9 @@ void tts_server_deinit(void) is_bk_websocket_tts = 0; set_ai_tts_server_init_flag(0); } - - - +// {"header":{"event":"SentenceEnd","msg":"success","status":20000000,"task_id":"b6aeaacc79b9d6a6e3ff9d9a17c405a2"},"payload":{"text":""}} +// {"header":{"event":"SentenceBegin","msg":"success","status":20000000,"task_id":"b6aeaacc79b9d6a6e3ff9d9a17c405a2"},"payload":{"index":4}} +// TTS text data: {"header":{"event":"EndSynthesis","msg":"success","status":20000000,"task_id":"2fbbceb5d0ff4a07f05590899a9aabe2"}} // {"header":{"event":"StartedSynthesis","msg":"success","status":20000000,"task_id":"8e8996f9148b66738309602ec3219412"}} tts_event_type_t tts_analysis(char *buf) { @@ -836,6 +836,27 @@ tts_event_type_t tts_analysis(char *buf) } else { event_type = TTS_EVENT_SYNTHESIS_ERROR; } + } else if (strcmp("EndSynthesis", event_str) == 0) { + if (msg_str != NULL && strcmp("success", msg_str) == 0) { + event_type = TTS_EVENT_END_SYNTHESIS; + printf("TTS synthesis ended successfully\n"); + } else { + event_type = TTS_EVENT_SYNTHESIS_ERROR; + } + } else if (strcmp("SentenceBegin", event_str) == 0) { + if (msg_str != NULL && strcmp("success", msg_str) == 0) { + event_type = TTS_EVENT_SENTENCE_BEGIN; + printf("TTS sentence begin\n"); + } else { + event_type = TTS_EVENT_SYNTHESIS_ERROR; + } + } else if (strcmp("SentenceEnd", event_str) == 0) { + if (msg_str != NULL && strcmp("success", msg_str) == 0) { + event_type = TTS_EVENT_SENTENCE_END; + printf("TTS sentence end\n"); + } else { + event_type = TTS_EVENT_SYNTHESIS_ERROR; + } } else if (strcmp("SynthesisComplete", event_str) == 0) { event_type = TTS_EVENT_SYNTHESIS_COMPLETE; } else if (strcmp("AudioData", event_str) == 0) { @@ -846,6 +867,7 @@ tts_event_type_t tts_analysis(char *buf) event_type = TTS_EVENT_ERROR; } else { event_type = TTS_EVENT_UNKNOWN; + printf("Unknown TTS event: %s\n", event_str); } } } @@ -854,6 +876,161 @@ tts_event_type_t tts_analysis(char *buf) return event_type; } + +/** + * @brief 启动TTS服务 + */ +bool uapi_start_tts_type_start(WebSocketClient *client) +{ + cJSON *json = NULL; + cJSON *header = NULL; + cJSON *payload = NULL; + char *jsonString = NULL; + bool result = false; + + // 参数验证 + if (client == NULL) { + printf("TTS client is NULL\n"); + return false; + } + + // 创建根JSON对象 + json = cJSON_CreateObject(); + if (json == NULL) { + printf("Failed to create JSON object\n"); + return false; + } + + // 创建header对象 + header = cJSON_CreateObject(); + if (header == NULL) { + printf("Failed to create header object\n"); + goto cleanup; + } + + // 添加header字段 + if (cJSON_AddStringToObject(header, "event", "StartSynthesis") == NULL) { + printf("Failed to add event field\n"); + goto cleanup; + } + + if (cJSON_AddStringToObject(header, "trace_id", "") == NULL) { + printf("Failed to add trace_id field\n"); + goto cleanup; + } + + // 将header添加到根对象 + if (cJSON_AddItemToObject(json, "header", header) == 0) { + printf("Failed to add header to root object\n"); + goto cleanup; + } + header = NULL; // 防止重复释放 + + // 创建payload对象 + payload = cJSON_CreateObject(); + if (payload == NULL) { + printf("Failed to create payload object\n"); + goto cleanup; + } + + // 添加payload字段 + if (cJSON_AddStringToObject(payload, "voice", "xiaoyun") == NULL) { + printf("Failed to add voice field\n"); + goto cleanup; + } + + if (cJSON_AddStringToObject(payload, "format", "mp3") == NULL) { + printf("Failed to add format field\n"); + goto cleanup; + } + + if (cJSON_AddNumberToObject(payload, "sample_rate", 16000) == NULL) { + printf("Failed to add sample_rate field\n"); + goto cleanup; + } + + if (cJSON_AddNumberToObject(payload, "volume", 80) == NULL) { + printf("Failed to add volume field\n"); + goto cleanup; + } + + if (cJSON_AddNumberToObject(payload, "speech_rate", 0) == NULL) { + printf("Failed to add speech_rate field\n"); + goto cleanup; + } + + // 将payload添加到根对象 + if (cJSON_AddItemToObject(json, "payload", payload) == 0) { + printf("Failed to add payload to root object\n"); + goto cleanup; + } + payload = NULL; // 防止重复释放 + + // 生成JSON字符串 + jsonString = cJSON_Print(json); + printf("uapi_start_tts_type_start: %s\r\n",jsonString); + if (jsonString == NULL) { + printf("Failed to print JSON to string\n"); + goto cleanup; + } + + // 发送WebSocket消息 + if (send_websocket_message(client, (uint8_t *)jsonString, strlen(jsonString), WS_TEXT) == 0) { + printf("TTS start message sent successfully\n"); + // printf("JSON: %s\n", jsonString); + result = true; + } else { + printf("TTS start message send failed\n"); + } + +cleanup: + // 清理资源 + if (jsonString != NULL) { + free(jsonString); + } + if (header != NULL) { + cJSON_Delete(header); + } + if (payload != NULL) { + cJSON_Delete(payload); + } + if (json != NULL) { + cJSON_Delete(json); + } + + return result; +} + + +void uapi_stop_tts_type_stop(WebSocketClient *client) +{ + if (client) { + char *stop_json = "{\"header\":{\"event\":\"StopSynthesis\",\"trace_id\":\"\"}}"; + send_websocket_message(client, (uint8_t *)stop_json, strlen(stop_json), WS_TEXT); + tts_is_ready = TTS_READY_NOT_SENT; + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"uapi_stop_tts_type_stop \n"); + } else { + printf("TTS client is NULL, cannot stop TTS\n"); + } +} + +/* + * 使用示例: + * + * // 使用指定的WebSocket客户端启动TTS服务 + * WebSocketClient *client = get_tts_client(); // 获取客户端 + * bool result = uapi_start_tts_type_start(client); + * + * // 或者使用全局客户端 + * bool result = uapi_start_tts_type_start(g_tts_server->client); + * + * // 停止TTS服务 + * uapi_stop_tts_type_stop(client); + * + * // 或者使用全局客户端停止 + * uapi_stop_tts_type_stop(g_tts_server->client); + */ + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/code/sdk/zhihui/ai_old/tts_websocket_server.h b/code/sdk/zhihui/ai_old/tts_websocket_server.h index e819219f3..5ee5199ea 100644 --- a/code/sdk/zhihui/ai_old/tts_websocket_server.h +++ b/code/sdk/zhihui/ai_old/tts_websocket_server.h @@ -24,6 +24,9 @@ extern "C" { typedef enum { TTS_EVENT_UNKNOWN = 0, // 未知事件 TTS_EVENT_STARTED_SYNTHESIS, // 开始合成事件 + TTS_EVENT_END_SYNTHESIS, // 结束合成事件 + TTS_EVENT_SENTENCE_BEGIN, // 句子开始事件 + TTS_EVENT_SENTENCE_END, // 句子结束事件 TTS_EVENT_SYNTHESIS_COMPLETE, // 合成完成事件 TTS_EVENT_SYNTHESIS_ERROR, // 合成错误事件 TTS_EVENT_AUDIO_DATA, // 音频数据事件 @@ -39,6 +42,7 @@ typedef enum { TTS_READY_SUCCESS_READY // 成功就绪 } tts_ready_status_t; + /* 任务配置结构体 - 使用系统定义的 app_task_definition_t */ /* 常量定义 */ @@ -110,6 +114,13 @@ int32_t uapi_tts_paly_stop(void); */ bool uapi_start_tts(void); +/** + * @brief 启动TTS服务 + * @param client WebSocket客户端 + * @return 成功返回true,失败返回false + */ +bool uapi_start_tts_type_start(WebSocketClient *client); + /** * @brief TTS文本处理函数(组合版本) * @param tts_client TTS WebSocket客户端 @@ -160,6 +171,12 @@ bool uapi_tts_process_text_global(char *buf, bool ready); */ void uapi_stop_tts(void); +/** + * @brief 停止TTS服务 + * @param client WebSocket客户端 + */ +void uapi_stop_tts_type_stop(WebSocketClient *client); + /** * @brief TTS WebSocket主线程 * @param data 线程参数 diff --git a/code/sdk/zhihui/ai_old/websocket_server_example.cpp b/code/sdk/zhihui/ai_old/websocket_server_example.cpp index d89cd31fd..77988074e 100644 --- a/code/sdk/zhihui/ai_old/websocket_server_example.cpp +++ b/code/sdk/zhihui/ai_old/websocket_server_example.cpp @@ -19,6 +19,8 @@ #include "chat_websocket_server.h" #include "tts_websocket_server.h" +// #include "common/typed_text.h" + #ifdef __cplusplus extern "C" { @@ -51,11 +53,8 @@ void handle_chat_data(const ws_event_data_t *event_data); char* extract_json_content( char *json_str, char *key); -void parse_chat_result(char *json_str); - -void uapi_stop_tts_type_stop(void); +void uapi_stop_tts_type_stop(WebSocketClient *client); -bool uapi_start_tts_type_start(void); void ai_media_init(void); @@ -178,8 +177,6 @@ void handle_asr_data(const ws_event_data_t *event_data) { ai_chat_send_txt(0, data.result_text, g_chat_server->client,false); ble_set_ai_Question_str(data.result_text); - - // uapi_stop_asr_StopTranscription(); } break; @@ -221,6 +218,16 @@ void handle_tts_data(const ws_event_data_t *event_data) tts_is_ready = TTS_READY_SUCCESS_READY; uapi_tts_process_text(g_tts_server->client,"",(tts_is_ready == TTS_READY_SUCCESS_READY)); break; + case TTS_EVENT_END_SYNTHESIS: + printf("TTS synthesis ended successfully\n"); + tts_is_ready = TTS_READY_NOT_SENT; + break; + case TTS_EVENT_SENTENCE_BEGIN: + printf("TTS sentence begin\n"); + break; + case TTS_EVENT_SENTENCE_END: + printf("TTS sentence end\n"); + break; case TTS_EVENT_SYNTHESIS_COMPLETE: printf("TTS synthesis completed\n"); break; @@ -263,7 +270,7 @@ void handle_chat_data(const ws_event_data_t *event_data) if(tts_is_ready == TTS_READY_NOT_SENT) { tts_is_ready = TTS_READY_SENT_SUCCESS; - uapi_start_tts_type_start(); + uapi_start_tts_type_start(g_tts_server->client); } break; @@ -276,7 +283,7 @@ void handle_chat_data(const ws_event_data_t *event_data) case CHAT_EVENT_END: printf("Chat event: END - Final content: %s\n", buf); - uapi_stop_tts_type_stop(); + uapi_stop_tts_type_stop(g_tts_server->client); break; case CHAT_EVENT_ERROR: @@ -295,29 +302,6 @@ void handle_chat_data(const ws_event_data_t *event_data) } } -/** - * @brief 解析Chat结果 - */ -void parse_chat_result(char *json_str) -{ - // 这里可以添加JSON解析逻辑 - // 简化示例,直接显示结果 - if (strstr(json_str, "\"type\":\"middle\"")) { - // 中间结果 - char *content = extract_json_content(json_str, "content"); - if (content) { - ble_set_ai_Answer_str(content, 2); - free(content); - } - } else if (strstr(json_str, "\"type\":\"end\"")) { - // 最终结果 - char *content = extract_json_content(json_str, "content"); - if (content) { - ble_set_ai_Answer_str(content, 2); - free(content); - } - } -} /** * @brief 提取JSON内容(简化实现) @@ -582,124 +566,6 @@ void destroy_all_websocket_servers(void) printf("All WebSocket servers destroyed\n"); } -/** - * @brief 发送TTS文本 - */ -bool send_tts_text(const char *text) -{ - if (!g_tts_server || !text) { - return false; - } - - // 构建TTS请求JSON - char json_template[] = - "{" - "\"type\":\"text\"," - "\"task_id\":\"\"," - "\"text\":\"%s\"" - "}"; - - char *json_str = (char *)malloc(strlen(json_template) + strlen(text) + 100); - if (!json_str) { - return false; - } - - sprintf(json_str, json_template, text); - - bool result = ws_server_send_message(g_tts_server, (uint8_t *)json_str, - strlen(json_str), WS_TEXT); - - free(json_str); - return result; -} - -/** - * @brief 发送Chat消息 - */ -bool send_chat_message(const char *message) -{ - if (!g_chat_server || !message) { - return false; - } - - // 构建Chat请求JSON - char json_template[] = - "{" - "\"type\":\"jiutian-lan\"," - "\"content\":\"%s\"" - "}"; - - char *json_str = (char *)malloc(strlen(json_template) + strlen(message) + 100); - if (!json_str) { - return false; - } - - sprintf(json_str, json_template, message); - - bool result = ws_server_send_message(g_chat_server, (uint8_t *)json_str, - strlen(json_str), WS_TEXT); - - free(json_str); - return result; -} - -/** - * @brief 启动TTS服务 - */ -bool start_tts_service(void) -{ - if (!g_tts_server) { - return false; - } - - char *start_json = - "{" - "\"type\":\"start\"," - "\"task_id\":\"\"," - "\"audio_config\":{" - "\"sample_rate\":16000," - "\"format\":\"mp3\"," - "\"channel\":1" - "}," - "\"request_config\":{" - "\"protocol\":1," - "\"audio_buffer_size\":1024" - "}" - "}"; - - return ws_server_send_message(g_tts_server, (uint8_t *)start_json, - strlen(start_json), WS_TEXT); -} - -/** - * @brief 停止TTS服务 - */ -void stop_tts_service(void) -{ - if (!g_tts_server) { - return; - } - - char *stop_json = "{\"type\":\"stop\",\"task_id\":\"\"}"; - ws_server_send_message(g_tts_server, (uint8_t *)stop_json, - strlen(stop_json), WS_TEXT); -} - - -void uapi_start_asr_StartTranscription(void) -{ - if (!g_asr_server) { - return; - } - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"uapi_start_asr_StartTranscription \n"); - - - char *jsonString = "{\"header\":{\"event\":\"StartTranscription\",\"trace_id\":\ - \"\"},\"payload\":{\"format\":\"MP3\",\"sample_rate\":16000}}"; - - ws_server_send_message(g_asr_server,( uint8_t *)jsonString,strlen(jsonString),WS_TEXT); - -} /** * @brief 设置服务器断连处理策略 @@ -871,156 +737,18 @@ void ai_media_init(void) } - -/** - * @brief 启动TTS服务 - */ -bool uapi_start_tts_type_start(void) +void uapi_start_AI_asr(void) { - cJSON *json = NULL; - cJSON *header = NULL; - cJSON *payload = NULL; - char *jsonString = NULL; - bool result = false; - - if (g_tts_server->client == NULL) { - printf("TTS client is NULL\n"); - return false; - } - - // 创建根JSON对象 - json = cJSON_CreateObject(); - if (json == NULL) { - printf("Failed to create JSON object\n"); - return false; - } - - // 创建header对象 - header = cJSON_CreateObject(); - if (header == NULL) { - printf("Failed to create header object\n"); - goto cleanup; - } - - // 添加header字段 - if (cJSON_AddStringToObject(header, "event", "StartSynthesis") == NULL) { - printf("Failed to add event field\n"); - goto cleanup; - } - - if (cJSON_AddStringToObject(header, "trace_id", "") == NULL) { - printf("Failed to add trace_id field\n"); - goto cleanup; - } - - // 将header添加到根对象 - if (cJSON_AddItemToObject(json, "header", header) == 0) { - printf("Failed to add header to root object\n"); - goto cleanup; - } - header = NULL; // 防止重复释放 - - // 创建payload对象 - payload = cJSON_CreateObject(); - if (payload == NULL) { - printf("Failed to create payload object\n"); - goto cleanup; - } - - // 添加payload字段 - if (cJSON_AddStringToObject(payload, "voice", "xiaoyun") == NULL) { - printf("Failed to add voice field\n"); - goto cleanup; - } - - if (cJSON_AddStringToObject(payload, "format", "mp3") == NULL) { - printf("Failed to add format field\n"); - goto cleanup; - } - - if (cJSON_AddNumberToObject(payload, "sample_rate", 16000) == NULL) { - printf("Failed to add sample_rate field\n"); - goto cleanup; - } - - if (cJSON_AddNumberToObject(payload, "volume", 80) == NULL) { - printf("Failed to add volume field\n"); - goto cleanup; - } - - if (cJSON_AddNumberToObject(payload, "speech_rate", 0) == NULL) { - printf("Failed to add speech_rate field\n"); - goto cleanup; - } - - // 将payload添加到根对象 - if (cJSON_AddItemToObject(json, "payload", payload) == 0) { - printf("Failed to add payload to root object\n"); - goto cleanup; - } - payload = NULL; // 防止重复释放 - - // 生成JSON字符串 - jsonString = cJSON_Print(json); - printf("uapi_start_tts_type_start: %s\r\n",jsonString); - if (jsonString == NULL) { - printf("Failed to print JSON to string\n"); - goto cleanup; - } - - // 发送WebSocket消息 - if (send_websocket_message(g_tts_server->client, (uint8_t *)jsonString, strlen(jsonString), WS_TEXT) == 0) { - printf("TTS start message sent successfully\n"); - // printf("JSON: %s\n", jsonString); - result = true; - } else { - printf("TTS start message send failed\n"); - } - -cleanup: - // 清理资源 - if (jsonString != NULL) { - free(jsonString); - } - if (header != NULL) { - cJSON_Delete(header); - } - if (payload != NULL) { - cJSON_Delete(payload); - } - if (json != NULL) { - cJSON_Delete(json); - } - - return result; + uapi_start_asr_StartTranscription(g_asr_server->client); } -void uapi_stop_tts_type_stop(void) +void uapi_stop_AI_asr(void) { - if (g_tts_server->client) { - char *stop_json = "{\"header\":{\"event\":\"StopSynthesis\",\"trace_id\":\"\"}}"; - send_websocket_message(g_tts_server->client, (uint8_t *)stop_json, strlen(stop_json), WS_TEXT); - tts_is_ready = TTS_READY_NOT_SENT; - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"uapi_stop_tts_type_stop \n"); - } + uapi_stop_asr_StopTranscription(g_asr_server->client); } -void uapi_stop_asr_StopTranscription(void) -{ - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"uapi_stop_asr_StopTranscription \n"); - char *jsonString ="{\"header\":{\"event\":\"StopTranscription\",\"trace_id\":\"3fa6b9e6a30b407ea38ad7ae69e6c291\"}}"; - - if (send_websocket_message(g_asr_server->client,( uint8_t *)jsonString,strlen(jsonString),WS_TEXT)==0) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"send_websocket_message succ 0\n"); - } - else - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"send_websocket_message erro\n"); - } -} uint8_t get_asr_is_ready_start_old(void) { @@ -1029,6 +757,8 @@ uint8_t get_asr_is_ready_start_old(void) + + #ifdef __cplusplus } #endif diff --git a/code/sdk/zhihui/ai_old/zhihui_ws.cpp b/code/sdk/zhihui/ai_old/zhihui_ws.cpp index 0f6901029..dd6af8ec5 100644 --- a/code/sdk/zhihui/ai_old/zhihui_ws.cpp +++ b/code/sdk/zhihui/ai_old/zhihui_ws.cpp @@ -1387,7 +1387,7 @@ int receive_websocket_message(WebSocketClient *client, unsigned char *buf,int l // 超时检查函数 auto check_timeout = [&]() -> bool { uint32_t current_time = (uint32_t)osKernelGetTickCount(); - return (current_time - start_time) >= timeout_ms; + return 0;//(current_time - start_time) >= timeout_ms; }; // while(1) // {