From 15a3cad7c0437e5baac1ba57a58a3c537b3c0ac1 Mon Sep 17 00:00:00 2001 From: hcj <1224667075@qq.com> Date: Mon, 22 Sep 2025 17:03:24 +0800 Subject: [PATCH] =?utf8?q?=E4=BF=AE=E5=A4=8D=E5=9B=A0=E5=A4=9A=E7=BA=BF?= =?utf8?q?=E7=A8=8B=E6=93=8D=E4=BD=9C=E5=AF=BC=E8=87=B4=E7=9A=84=E5=A4=9A?= =?utf8?q?=E6=AC=A1=E6=92=AD=E6=94=BE=E9=87=8D=E5=A4=8D=E6=96=87=E5=AD=97?= =?utf8?q?=E9=97=AE=E9=A2=98=EF=BC=88=E5=A2=9E=E5=8A=A0=E9=94=81=E4=BF=9D?= =?utf8?q?=E6=8A=A4=20=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- code/sdk/zhihui/ai_old/CMakeLists.txt | 2 + code/sdk/zhihui/ai_old/ai_old_at_cmd.cpp | 28 +- code/sdk/zhihui/ai_old/chat_https_servrt.cpp | 152 +++++++ code/sdk/zhihui/ai_old/chat_https_servrt.h | 44 ++ .../zhihui/ai_old/tts_websocket_server.cpp | 426 ++++++++++++++++-- code/sdk/zhihui/ai_old/tts_websocket_server.h | 17 + 6 files changed, 620 insertions(+), 49 deletions(-) create mode 100644 code/sdk/zhihui/ai_old/chat_https_servrt.cpp create mode 100644 code/sdk/zhihui/ai_old/chat_https_servrt.h diff --git a/code/sdk/zhihui/ai_old/CMakeLists.txt b/code/sdk/zhihui/ai_old/CMakeLists.txt index 226a3b6a4..63e56b4d3 100644 --- a/code/sdk/zhihui/ai_old/CMakeLists.txt +++ b/code/sdk/zhihui/ai_old/CMakeLists.txt @@ -24,6 +24,8 @@ ${CMAKE_CURRENT_SOURCE_DIR}/tts_websocket_server.cpp ${CMAKE_CURRENT_SOURCE_DIR}/chat_websocket_server.cpp ${CMAKE_CURRENT_SOURCE_DIR}/websocket_server_example.cpp ${CMAKE_CURRENT_SOURCE_DIR}/websocket_server_manager.cpp +${CMAKE_CURRENT_SOURCE_DIR}/chat_https_servrt.cpp + ) set(COMPONENT_PUBLIC_CCFLAGS 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 ccc03dad7..566b6dd53 100644 --- a/code/sdk/zhihui/ai_old/ai_old_at_cmd.cpp +++ b/code/sdk/zhihui/ai_old/ai_old_at_cmd.cpp @@ -32,6 +32,7 @@ extern "C" { #include "zhihui_ws.h" #include "websocket_test.h" #include "cmsis_os2.h" +#include "chat_https_servrt.h" static int ConvertCmdToParam(uint8_t *para, uint32_t paraLen, uint8_t argv[PPG_MAX_ARGC][PPG_MAX_ARGV_LEN], uint32_t* argc) @@ -145,7 +146,7 @@ static uint32_t start_record(uint8_t *para, uint32_t paraLen, char *strCommonCmd return ERRCODE_FAIL; } uapi_start_asr(); - streamingRecordAndSend_AI(0); + // streamingRecordAndSend_AI(0); return 0; } @@ -426,6 +427,30 @@ static uint32_t websocket_status(uint8_t *para, uint32_t paraLen, char *strCommo return ERRCODE_SUCC; } +static uint32_t test_http_chat(uint8_t *para, uint32_t paraLen, char *strCommonCmd) +{ + UNUSED(strCommonCmd); + uint8_t argv[PPG_MAX_ARGC][PPG_MAX_ARGV_LEN] = { 0 }; + uint32_t argc = 0; + + + int ret = ConvertCmdToParam(para, paraLen, argv, &argc); + if (ret != PPG_SUCCESS) { + printf("CAT1TEST ATCMD Convert Command Failed\n"); + return ERRCODE_FAIL; + } + + // 调用http_posttest函数 + ret = http_posttest("你好,请介绍一下你自己", NULL, 0); + if (ret == 0) { + printf("HTTP请求成功!\n"); + return ERRCODE_SUCC; + } else { + printf("HTTP请求失败,错误码: %d\n", ret); + return ERRCODE_FAIL; + } +} + static const at_cmd_table_t g_ai_old_cmd[] = { { (char *)"AT^WSTEST", wstest, (char *)"1" }, { (char *)"AT^AI_MSG", ai_msg, (char *)"1" }, @@ -447,6 +472,7 @@ static const at_cmd_table_t g_ai_old_cmd[] = { { (char *)"AT^STARTTRAN", StartTranscription, (char *)"1" }, { (char *)"AT^STOPTRAN", STOPTranscription, (char *)"1" }, { (char *)"AT^WEBSOCKSTOP", STOPserver, (char *)"1" }, + { (char *)"AT^TESTHTTPCHAT", test_http_chat, (char *)"HTTP聊天测试" }, diff --git a/code/sdk/zhihui/ai_old/chat_https_servrt.cpp b/code/sdk/zhihui/ai_old/chat_https_servrt.cpp new file mode 100644 index 000000000..081cdf338 --- /dev/null +++ b/code/sdk/zhihui/ai_old/chat_https_servrt.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include "netstack/http/include/httpclient.h" +#include "chat_https_servrt.h" + +/* @brief http request buffer */ +#define REQ_BUF_SIZE 2048 +static char req_buf[REQ_BUF_SIZE]; + +/* @brief http response buffer */ +#define RSP_BUF_SIZE 2048 +static char rsp_buf[RSP_BUF_SIZE] = {0}; + + +// { 1 +// "userId": "user123", +// "characterId": "char456", +// "message": "你好,请介绍⼀下你⾃⼰" +// } + + +// { +// "errorCode": null, +// "message": null, +// "data": { +// "message": "你好!我是你的AI助⼿,很⾼兴为你服务。我可以帮助你解答问题、提供建议或者 +// 陪你聊天。请问有什么我可以帮助你的吗?" +// } +// } + +/** + * @brief 解析HTTP响应JSON数据,提取data.message字段 + * @param json_str JSON字符串 + * @param out_message 输出消息缓冲区 + * @param max_len 缓冲区最大长度 + * @return 0成功,-1失败 + */ +int parse_http_response_message(const char *json_str, char *out_message, size_t max_len) +{ + if (!json_str || !out_message || max_len == 0) { + return -1; + } + + // 初始化输出缓冲区 + memset(out_message, 0, max_len); + + // 查找data.message字段 + const char *data_start = strstr(json_str, "\"data\""); + if (data_start) { + const char *data_message_start = strstr(data_start, "\"message\""); + if (data_message_start) { + data_message_start = strchr(data_message_start, ':'); + if (data_message_start) { + data_message_start++; // 跳过冒号 + while (*data_message_start == ' ' || *data_message_start == '\t') { + data_message_start++; // 跳过空格 + } + // 查找引号 + const char *quote_start = strchr(data_message_start, '"'); + if (quote_start) { + quote_start++; // 跳过开始引号 + const char *quote_end = strchr(quote_start, '"'); + if (quote_end) { + size_t len = quote_end - quote_start; + if (len < max_len) { + strncpy(out_message, quote_start, len); + out_message[len] = '\0'; + return 0; + } + } + } + } + } + } + + return -1; +} + +int http_posttest(const char *message, char *out_message, size_t max_len) +{ + HttpClient client = {0}; + HttpClientData client_data = {0}; + char *req_url = "https://ambybox-api.test.leiniao.com/ambybox-device-api/v1/textChat/chat?deviceId=860132060562402&deviceToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJXWVNaIiwiZGV2aWNlTW9kZWwiOiJBQjEwMSIsImRldmljZVZlcnNpb24iOiJWQjY1MF8yMDI1MDkxOV8x\NDI4MDMiLCJkZXZpY2VJZCI6Ijg2MDEzMjA2MDU2MjQwMiIsImV4cCI6MTc2MDg1OTE5OX0.B6zIfQyE9iGLlknIIDomQ3jnWxdNtcF5LHVrKS9WQFg"; + int ret = -1; + // + // 构建JSON数据,使用第13行开始的格式 + char json_data[512]; + snprintf(json_data, sizeof(json_data), + "{" + "\"userId\": \"test_user_001\"," + "\"characterId\": \"char_001\"," + "\"message\": \"%s\"" + "}", + message ? message : "你好,请介绍一下你自己"); + + client_data.postBuf = json_data; + size_t length = strlen(client_data.postBuf); + client_data.postBufLen = length; + + memset(req_buf, 0, sizeof(req_buf)); + client_data.headerBuf = req_buf; + client_data.headerBufLen = sizeof(req_buf); + + memset(rsp_buf, 0, sizeof(rsp_buf)); + client_data.responseBuf = rsp_buf; + client_data.responseBufLen= sizeof(rsp_buf); + + printf("\n http request: %s \r\n", req_url); + printf("JSON data: %s \r\n", json_data); + + + char *header_buf = (char *)malloc(128); + if (!header_buf) + return ret; + int hdr = snprintf(header_buf,128, + "deviceId: %s \r\n" + "Content-Type: application/json\r\n","860132060562402"); + if (hdr <= 0) + { + free(header_buf); + return ret; + } + HttpClientSetCustomHeader(&client, header_buf); + + + ret = HttpClientPostRequest(&client, req_url, &client_data); + if (ret >= 0 && client.responseCode == 200) { + printf("http test success!\r\n"); + + // 解析响应数据中的message字段 + if (out_message && max_len > 0) { + if (parse_http_response_message(client_data.responseBuf, out_message, max_len) == 0) { + printf("Response message: %s\n", out_message); + } else { + printf("Failed to parse response message\n"); + memset(out_message, 0, max_len); + } + } + + ret = 0; + } else { + printf("responsecode = %d \n", client.responseCode); + printf("http test failed! ret= 0x%x \r\n", ret); + + // 如果请求失败,清空输出缓冲区 + if (out_message && max_len > 0) { + memset(out_message, 0, max_len); + } + } + return ret; +} \ No newline at end of file diff --git a/code/sdk/zhihui/ai_old/chat_https_servrt.h b/code/sdk/zhihui/ai_old/chat_https_servrt.h new file mode 100644 index 000000000..58cc74026 --- /dev/null +++ b/code/sdk/zhihui/ai_old/chat_https_servrt.h @@ -0,0 +1,44 @@ +#ifndef __CHAT_HTTPS_SERVRT_H__ +#define __CHAT_HTTPS_SERVRT_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* @brief http request buffer size */ +#define REQ_BUF_SIZE 2048 + +/* @brief http response buffer size */ +#define RSP_BUF_SIZE 2048 + +/* @brief JSON data buffer size */ +#define JSON_DATA_SIZE 512 + +/* @brief response message buffer size */ +#define RESPONSE_MSG_SIZE 1024 + +/** + * @brief 解析HTTP响应JSON数据,提取data.message字段 + * @param json_str JSON字符串 + * @param out_message 输出消息缓冲区 + * @param max_len 缓冲区最大长度 + * @return 0成功,-1失败 + */ +int parse_http_response_message(const char *json_str, char *out_message, size_t max_len); + +/** + * @brief HTTP POST测试函数 + * @param message 要发送的消息内容,如果为NULL则使用默认消息 + * @param out_message 输出响应消息,可以为NULL + * @param max_len 输出缓冲区最大长度 + * @return 0成功,-1失败 + */ +int http_posttest(const char *message, char *out_message, size_t max_len); + +#ifdef __cplusplus +} +#endif + +#endif /* __CHAT_HTTPS_SERVRT_H__ */ diff --git a/code/sdk/zhihui/ai_old/tts_websocket_server.cpp b/code/sdk/zhihui/ai_old/tts_websocket_server.cpp index c67e89716..70c51d012 100644 --- a/code/sdk/zhihui/ai_old/tts_websocket_server.cpp +++ b/code/sdk/zhihui/ai_old/tts_websocket_server.cpp @@ -49,6 +49,7 @@ extern void msleep(uint32_t ms); extern int32_t VoiceCallVolteSample(int32_t argc, const char **argv); static bool uapi_send_single_tts_text(WebSocketClient *tts_client, const char *text); +static bool tts_cache_ensure_capacity(int required_size); /* TTS 配置和常量 */ #define AI_MAX_RETRY_COUNT 3 @@ -65,6 +66,199 @@ static int tts_cached_capacity = 0; // 当前分配的内存容量 static bool tts_has_stop_cached = false; // 是否缓存了stop命令 // static bool tts_is_ready = false; // TTS是否准备就绪 +/* TTS 缓存互斥锁 */ +static osMutexId_t tts_cache_mutex = NULL; + +/** + * @brief 带互斥锁保护的缓存追加操作 + * @param buf 要追加的文本 + * @return true 成功,false 失败 + */ +static bool tts_cache_append_with_mutex(const char *buf) +{ + if (tts_cache_mutex != NULL) { + if (osMutexAcquire(tts_cache_mutex, osWaitForever) == osOK) { + int buf_len = strlen(buf); + int required_size = tts_cached_length + buf_len + 1; // 预留结束符空间 + + // 确保有足够的空间 + if (!tts_cache_ensure_capacity(required_size)) { + printf("TTS cache allocation failed\n"); + osMutexRelease(tts_cache_mutex); + return false; + } + + // 追加文本到缓存字符串 + strcat(tts_cached_text, buf); + tts_cached_length += buf_len; + printf("TTS text appended to cache (length: %d/%d): %s\n", tts_cached_length, tts_cached_capacity, buf); + + osMutexRelease(tts_cache_mutex); + return true; + } else { + printf("Failed to acquire TTS cache mutex for append\n"); + return false; + } + } else { + // 如果互斥锁未初始化,直接操作(向后兼容) + int buf_len = strlen(buf); + int required_size = tts_cached_length + buf_len + 1; // 预留结束符空间 + + // 确保有足够的空间 + if (!tts_cache_ensure_capacity(required_size)) { + printf("TTS cache allocation failed\n"); + return false; + } + + // 追加文本到缓存字符串 + strcat(tts_cached_text, buf); + tts_cached_length += buf_len; + printf("TTS text appended to cache (length: %d/%d): %s\n", tts_cached_length, tts_cached_capacity, buf); + return true; + } +} + +/** + * @brief 带互斥锁保护的缓存清空操作 + * @return true 成功,false 失败 + */ +static bool tts_cache_clear_with_mutex(void) +{ + if (tts_cache_mutex != NULL) { + if (osMutexAcquire(tts_cache_mutex, osWaitForever) == osOK) { + if (tts_cached_text != NULL) { + memset(tts_cached_text, 0, tts_cached_capacity); + } + tts_cached_length = 0; + tts_has_stop_cached = false; // 同时清空stop缓存标志 + osMutexRelease(tts_cache_mutex); + printf("TTS cache cleared with mutex protection\n"); + return true; + } else { + printf("Failed to acquire TTS cache mutex for clear\n"); + return false; + } + } else { + // 如果互斥锁未初始化,直接清空(向后兼容) + if (tts_cached_text != NULL) { + memset(tts_cached_text, 0, tts_cached_capacity); + } + tts_cached_length = 0; + tts_has_stop_cached = false; // 同时清空stop缓存标志 + printf("TTS cache cleared without mutex (mutex not available)\n"); + return true; + } +} + +/** + * @brief 带互斥锁保护的获取缓存长度操作 + * @return 缓存长度 + */ +static int tts_cache_get_length_with_mutex(void) +{ + int length = 0; + + if (tts_cache_mutex != NULL) { + if (osMutexAcquire(tts_cache_mutex, osWaitForever) == osOK) { + length = tts_cached_length; + osMutexRelease(tts_cache_mutex); + } else { + printf("Failed to acquire TTS cache mutex for count\n"); + length = 0; + } + } else { + // 如果互斥锁未初始化,直接返回(向后兼容) + length = tts_cached_length; + } + + return length; +} + +/** + * @brief 带互斥锁保护的检查缓存是否有内容 + * @return true 有内容,false 无内容 + */ +static bool tts_cache_has_content_with_mutex(void) +{ + bool has_content = false; + + if (tts_cache_mutex != NULL) { + if (osMutexAcquire(tts_cache_mutex, osWaitForever) == osOK) { + has_content = (tts_cached_length > 0); + osMutexRelease(tts_cache_mutex); + } else { + printf("Failed to acquire TTS cache mutex for check\n"); + has_content = false; + } + } else { + // 如果互斥锁未初始化,直接检查(向后兼容) + has_content = (tts_cached_length > 0); + } + + return has_content; +} + +/** + * @brief 带互斥锁保护的发送缓存文本操作 + * @param tts_client TTS WebSocket客户端 + * @return true 成功,false 失败 + */ +static bool tts_cache_send_with_mutex(WebSocketClient *tts_client) +{ + if (tts_cache_mutex != NULL) { + if (osMutexAcquire(tts_cache_mutex, osWaitForever) == osOK) { + bool result = false; + + if (tts_cached_length > 0) { + printf("TTS ready, sending cached text (length: %d): %s\n", tts_cached_length, tts_cached_text); + result = uapi_send_single_tts_text(tts_client, tts_cached_text); + if (!result) { + printf("Failed to send cached text: %s\n", tts_cached_text); + } else { + printf("Successfully sent cached text: %s\n", tts_cached_text); + } + + // 发送完成后清空缓存 + if (tts_cached_text != NULL) { + memset(tts_cached_text, 0, tts_cached_capacity); + } + tts_cached_length = 0; + tts_has_stop_cached = false; // 同时清空stop缓存标志 + printf("TTS cache cleared after sending\n"); + } + + osMutexRelease(tts_cache_mutex); + return result; + } else { + printf("Failed to acquire TTS cache mutex for send\n"); + return false; + } + } else { + // 如果互斥锁未初始化,直接操作(向后兼容) + bool result = false; + + if (tts_cached_length > 0) { + printf("TTS ready, sending cached text (length: %d): %s\n", tts_cached_length, tts_cached_text); + result = uapi_send_single_tts_text(tts_client, tts_cached_text); + if (!result) { + printf("Failed to send cached text: %s\n", tts_cached_text); + } else { + printf("Successfully sent cached text: %s\n", tts_cached_text); + } + + // 发送完成后清空缓存 + if (tts_cached_text != NULL) { + memset(tts_cached_text, 0, tts_cached_capacity); + } + tts_cached_length = 0; + tts_has_stop_cached = false; // 同时清空stop缓存标志 + printf("TTS cache cleared after sending\n"); + } + + return result; + } +} + /** * @brief 初始化TTS缓存内存 * @return true 成功,false 失败 @@ -82,6 +276,17 @@ static bool tts_cache_init(void) memset(tts_cached_text, 0, TTS_MAX_CACHED_LENGTH); printf("TTS cache initialized with %d bytes\n", TTS_MAX_CACHED_LENGTH); } + + // 创建互斥锁 + if (tts_cache_mutex == NULL) { + tts_cache_mutex = osMutexNew(NULL); + if (tts_cache_mutex == NULL) { + printf("Failed to create TTS cache mutex\n"); + return false; + } + printf("TTS cache mutex created\n"); + } + return true; } @@ -97,6 +302,13 @@ static void tts_cache_deinit(void) tts_cached_length = 0; printf("TTS cache deinitialized\n"); } + + // 删除互斥锁 + if (tts_cache_mutex != NULL) { + osMutexDelete(tts_cache_mutex); + tts_cache_mutex = NULL; + printf("TTS cache mutex deleted\n"); + } } /** @@ -287,39 +499,17 @@ bool uapi_tts_process_text(WebSocketClient *tts_client, char *buf, bool ready) // 如果ready为false,将文本追加到缓存字符串 if (!ready) { if (buf && strlen(buf) > 0) { - int buf_len = strlen(buf); - int required_size = tts_cached_length + buf_len + 1; // 预留结束符空间 - - // 确保有足够的空间 - if (!tts_cache_ensure_capacity(required_size)) { - printf("TTS cache allocation failed\n"); - return false; - } - - // 追加文本到缓存字符串 - strcat(tts_cached_text, buf); - tts_cached_length += buf_len; - printf("TTS text appended to cache (length: %d/%d): %s\n", tts_cached_length, tts_cached_capacity, buf); + return tts_cache_append_with_mutex(buf); } return true; } // 如果ready为true,先发送缓存的文本,然后发送本次携带的内容 - if (tts_cached_length > 0) { - printf("TTS ready, sending cached text (length: %d): %s\n", tts_cached_length, tts_cached_text); - bool result = uapi_send_single_tts_text(tts_client, tts_cached_text); + if (tts_cache_has_content_with_mutex()) { + bool result = tts_cache_send_with_mutex(tts_client); if (!result) { - printf("Failed to send cached text: %s\n", tts_cached_text); return false; - } else { - printf("Successfully sent cached text: %s\n", tts_cached_text); - } - - // 清空缓存 - if (tts_cached_text != NULL) { - memset(tts_cached_text, 0, tts_cached_capacity); } - tts_cached_length = 0; } // 检查是否有缓存的stop命令需要发送 @@ -471,7 +661,7 @@ tts_ready_status_t uapi_get_tts_ready(void) */ int uapi_get_cached_text_count(void) { - return tts_cached_length; + return tts_cache_get_length_with_mutex(); } /** @@ -479,12 +669,7 @@ int uapi_get_cached_text_count(void) */ void uapi_clear_tts_cache(void) { - if (tts_cached_text != NULL) { - memset(tts_cached_text, 0, tts_cached_capacity); - } - tts_cached_length = 0; - tts_has_stop_cached = false; // 同时清空stop缓存标志 - printf("TTS cache cleared\n"); + tts_cache_clear_with_mutex(); } /** @@ -852,22 +1037,6 @@ tts_event_type_t tts_analysis(char *buf) if (msg_str != NULL && strcmp("success", msg_str) == 0) { event_type = TTS_EVENT_STARTED_SYNTHESIS; tts_is_ready = TTS_READY_SUCCESS_READY; - - // TTS准备就绪,发送缓存的文本(如果有的话) - if (tts_cached_length > 0) { - printf("TTS is ready, sending cached text (length: %d): %s\n", tts_cached_length, tts_cached_text); - if (tts_client != NULL) { - bool result = uapi_send_single_tts_text(tts_client, tts_cached_text); - if (result) { - printf("Successfully sent cached text: %s\n", tts_cached_text); - // 清空缓存 - memset(tts_cached_text, 0, tts_cached_capacity); - tts_cached_length = 0; - } else { - printf("Failed to send cached text: %s\n", tts_cached_text); - } - } - } } else { event_type = TTS_EVENT_SYNTHESIS_ERROR; } @@ -1049,6 +1218,167 @@ void uapi_stop_tts_type_stop(WebSocketClient *client) } } + + + // "{ \"header\": { \ + // \"event\": \"LongTextStream\", \ + // \"trace_id\": \"3fa6b9e6a30b407ea38ad7ae69e6c291\"\ + // },\ + // \"payload\": {\ + // \"voice\":\"xiaoyun\",\ + // \"format\":\"mp3\",\ + // \"sample_rate\":16000,\ + // \"volume\":80,\ + // \"speech_rate\":0,\ + // \"text\":\"%s\"\ + // } }" + +/** + * @brief 发送长文本TTS合成请求 + * @param client WebSocket客户端 + * @param text 要合成的文本 + * @param voice 语音类型,默认为"xiaoyun" + * @param format 音频格式,默认为"mp3" + * @param sample_rate 采样率,默认为16000 + * @param volume 音量,默认为80 + * @param speech_rate 语速,默认为0 + * @param trace_id 跟踪ID,可以为NULL + * @return 成功返回true,失败返回false + */ +bool uapi_send_long_text_tts(WebSocketClient *client, const char *text, + const char *voice, const char *format, + int sample_rate, int volume, int speech_rate, + const char *trace_id) +{ + cJSON *json = NULL; + cJSON *header = NULL; + cJSON *payload = NULL; + char *jsonString = NULL; + bool result = false; + + // 参数验证 + if (client == NULL || text == NULL) { + printf("TTS client or text is NULL\n"); + return false; + } + + // 设置默认值 + if (voice == NULL) voice = "xiaoyun"; + if (format == NULL) format = "mp3"; + if (trace_id == NULL) trace_id = "3fa6b9e6a30b407ea38ad7ae69e6c291"; + + // 创建根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", "LongTextStream") == NULL) { + printf("Failed to add event field\n"); + goto cleanup; + } + + if (cJSON_AddStringToObject(header, "trace_id", 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", voice) == NULL) { + printf("Failed to add voice field\n"); + goto cleanup; + } + + if (cJSON_AddStringToObject(payload, "format", format) == NULL) { + printf("Failed to add format field\n"); + goto cleanup; + } + + if (cJSON_AddNumberToObject(payload, "sample_rate", sample_rate) == NULL) { + printf("Failed to add sample_rate field\n"); + goto cleanup; + } + + if (cJSON_AddNumberToObject(payload, "volume", volume) == NULL) { + printf("Failed to add volume field\n"); + goto cleanup; + } + + if (cJSON_AddNumberToObject(payload, "speech_rate", speech_rate) == NULL) { + printf("Failed to add speech_rate field\n"); + goto cleanup; + } + + if (cJSON_AddStringToObject(payload, "text", text) == NULL) { + printf("Failed to add text 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_send_long_text_tts: %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("Long text TTS message sent successfully\n"); + result = true; + } else { + printf("Long text TTS 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; +} + + /* * 使用示例: * diff --git a/code/sdk/zhihui/ai_old/tts_websocket_server.h b/code/sdk/zhihui/ai_old/tts_websocket_server.h index dce84f013..5c591f7ed 100644 --- a/code/sdk/zhihui/ai_old/tts_websocket_server.h +++ b/code/sdk/zhihui/ai_old/tts_websocket_server.h @@ -121,6 +121,23 @@ bool uapi_start_tts(void); */ bool uapi_start_tts_type_start(WebSocketClient *client); +/** + * @brief 发送长文本TTS合成请求 + * @param client WebSocket客户端 + * @param text 要合成的文本 + * @param voice 语音类型,默认为"xiaoyun" + * @param format 音频格式,默认为"mp3" + * @param sample_rate 采样率,默认为16000 + * @param volume 音量,默认为80 + * @param speech_rate 语速,默认为0 + * @param trace_id 跟踪ID,可以为NULL + * @return 成功返回true,失败返回false + */ +bool uapi_send_long_text_tts(WebSocketClient *client, const char *text, + const char *voice, const char *format, + int sample_rate, int volume, int speech_rate, + const char *trace_id); + /** * @brief TTS文本处理函数(组合版本) * @param tts_client TTS WebSocket客户端 -- 2.17.1